Question

I would like to use ParseKit for analyzing some javascript code. I got the framework setup with a javascript grammar, but I can't really get my head around what route to take to analyze the code. The thing is, i would like in the end to for example get an array of all globally declared var's (so var's that are defined outside a function). But i can't really see how i can get that result! I've been reading a lot of questions here on stack overflow, and can see that I somehow probably should use the stack and target of the assembler, but the thing is that the function callback is called when it reaches the functions block end, so all the var definitions get's callbacked before. How do i know when i get a callback on a var inside a function, that its inside?

var i = 0;
function test(){
   var u = 0;
}

Here i want to find i for example, not u. But the callbacks are

#1  Found var i
#2  Found var u
#3  Found func test

Jonas

Was it helpful?

Solution

Developer of ParseKit here.

First, checkout this answer to another, somewhat-related ParseKit question. There's lots of relevant info there (and in the other answers linked there).

Then, for your particular example, the key is to set a flag whenever a function begins, and to clear the flag when it ends. So whenever a var decl is matched, just check the flag. If the flag is set, then ignore the var decl. If the flag is not set, then store it.

It is vitally important that the flag I mentioned be stored on the PKAssembly object which is the argument to your assembler callback functions. You cannot store that flag as an ivar or global var. That won't work (see prior linked answers for details why).

Here's some example callbacks for setting the flag and matching var decls. They should give you an idea of what I'm talking about:

// matched when function begins
- (void)parser:(PKParser *)p didMatchFunctionKeyword:(PKAssembly *)a {
    [a push:[NSNull null]]; // set a flag
}

// matched when a function ends
- (void)parser:(PKParser *)p didMatchFunctionCloseCurly:(PKAssembly *)a {
    NSArray *discarded = [a objectsAbove:[NSNull null]];
    id obj = [a pop]; // clear the flag
    NSAssert(obj == [NSNull null], @"null should be on the top of the stack");
}

// matched when a var is declared
- (void)parser:(PKParser *)p didMatchVarDecl:(PKAssembly *)a {
    id obj = [a pop];
    if (obj == [NSNull null]) { // check for flag
        [a push:obj]; // we're in a function. put the flag back and bail.
    } else {
        PKToken *fence = [PKToken tokenWithTokenType:PKTokenTypeWord stringValue:@"var" floatValue:0.0];
        NSArray *toks = [a objectsAbove:fence]; // get all the tokens for the var decl
        // now do whatever you want with the var decl tokens here.
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top