My diary of software development

I have a personal project I am working on in which I want to compile the method and class signatures (but not the implementation logic) of JavaScript files.

I found the solution I’m going to use but not before wandering through a buh-zillion pages on the web and trying a few approaches until I arrived at something which I think will work for what I need. This blog entry is about that wandering.

A JavaScript file for testing

I needed a script file with a class and method in it to use for my tests. There are different ways to create a ‘class’ in JavaScript, but for this test I decided to use the function prototype method generated from Script#.

The C# class:

public class Class1
{
    public void DoSomething(int parm1)
    {
    }
}

The resulting JavaScript:

//! SSGen.debug.js
//

(function() {

////////////////////////////////////////////////////////////////////////////////
// Class1

window.Class1 = function Class1() {
}
Class1.prototype = {

    doSomething: function Class1$doSomething(parm1) {
        ///
        ///
    }
}

Class1.registerClass('Class1');
})();

//! This script was generated using Script# v0.7.4.0

Attempt I – Use the Microsoft.JScript.Vsa.VsaEngine

I found an entry on Rick Strahl’s blog about evaluating JavaScript in C# and although it talks about evaluating JavaScript instead of parsing it, I figured it would be a good place to start.

I wrote this C# test code:

        static private void ParseJsWithVsa()
        {
            string jsPath = @"SSGen.debug.js";
            string javaScript = File.ReadAllText(jsPath);
            VsaEngine engine = VsaEngine.CreateEngine();
            object evalResult = Eval.JScriptEvaluate(javaScript, engine);
        }

And got these compilation warnings:

Warnings

But it it did compile! So I ran it and this was my result:

Err1

Okay, well that’ll be easy to fix I thought. I decided to just remove the Window. from line 10 of the JavaScript and try it again with this result:

Err1

Arrgh. I guess that the parsing worked without trouble but the actual evaluation failed, I couldn’t find any way to get the parsing results so I decided not to work on this approach any longer. Instead I decided I’d try the ICodeCompiler noted in the compilation warnings above.

Attempt II – Use the ICodeProvider

Here’s the c#:

        static private void ParseJsWithICodeCompiler()
        {
            string jsPath = @"SSGen.debug.js";
            JScriptCodeProvider jsProvider = CodeDomProvider.CreateProvider("JScript") as JScriptCodeProvider;
            using (TextReader text = File.OpenText(jsPath))
            {
                CodeCompileUnit ccu = jsProvider.Parse(text);
            }
        }

Here’s the result:

ICC Error

Oh well. So much for that idea.

Attempt III – Use JSLint

I know that JSLint is a code quality tool but I figured that somewhere down in the mess of JSLint code it’s got to parse the target script and maybe I could hook into it and get the results of the parsing action.

I created a test ASP.Net web site which would show me the results of running JSLint against my test script file.

Here is my ASP.Net site’s markup:


    JSLint Parse Tester
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js"></script><script type="text/javascript" src="Scripts/Test.js"></script>
<script type="text/javascript" src="Scripts/JSLint.js"></script></pre>
<form id="form1">
<div>
<h3>Result of calling JSLINT(script);</h3>

<hr />

<h3 id="resultsTitle"></h3>
<div id="results"></div>
</div>
</form>
<pre>

And here is the JavaScript I wrote to execute JSLint against my test script file:

///
///

function OnGetScriptToParseComplete(script)
{
    var result = JSLINT(script);
    $('#jsLintResult').text(result);

    if (result)
    {
        var tree = JSON.stringify(JSLINT.tree, [
         'string', 'arity', 'name', 'first',
         'second', 'third', 'block', 'else'
     ], 4);

        tree = tree.replace(/\n/g, "
");
        tree = tree.replace(/ /g, " ");
        $('#results').html(tree);

        $('#resultsTitle').text("JSLINT.tree:");
    }
    else
    {
        var errs = JSON.stringify(JSLINT.errors, undefined, 4);
        errs = errs.replace(/\n/g, "
");
        errs = errs.replace(/ /g, " ");
        $('#results').html(errs).css('color', 'red');

        $('#resultsTitle').text("JSLINT.errors:");
    }
}

$(document).ready(function ()
{
    $.ajax({
        url: "scripts/ToParse.js",
        dataType: 'text',
        success: OnGetScriptToParseComplete
    });
});

And here are the results:

JSLint results

Before I delved into this approach any further I continued looking online for solutions to parse JavaScript and found something named ANTLR which seemed to be exactly what I needed.

Attempt IV – Use ANTLR

ANTLR is a tool which, among many other things, allows me to generate lexers and parsers in a target language (i.e. C#) to use against a specific grammar.

I’ve been working with ANTLR for a couple of days now, it’s got several ‘pieces’ which must be downloaded, version matched, and fitted together to do what I need but it seems to be the best solution so far. I’ll write more about ANTLR and my project in the next part of this series.

Advertisements

Comments on: "Parsing JavaScript in C# Part I" (1)

  1. Hi Chris,
    I have a somewhat similar need. I am attempting to create help documentation for a large and complex JavaScript library that is currently undocumented. I started to manually document the library but after a few weeks, I am only half way through. I use a 3rd party documentation tool which just so happens to persist it’s projects into SQLite which is everso easy to update using the devart SQLite Connect API. My thought is that if I could automatically parse the JavaScript library than I may be able to auto generate the specifics within my help documentation project, which would allow me to scan the script and build out relating links to variables and functions. Not sure if that all makes sense. I looked at ANTLR but I am not sure where to begin. I am highly proficient at C# and somewhat so at JavaScript and am hoping you can point me in the right direction.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: