Search code examples
javascriptnode.jsyacclexjison

JISON issues with parsing command


Hi I am a newbie to JISON and stuck in following code:
For parsing a command:

 project -a -n <projectname>  

My code is as follows:

"project"   {return 'PROJECTCOMMAND';}
"-n"        {return 'NAMEOPTION';}
("--add"|"-a")  {return 'ADDOPTION';}  
[-a-zA-Z0-9@\.]+ {return 'TEXT';}

line :   
   PROJECTCOMMAND ADDOPTION NAMEOPTION TEXT 
            {
                //Prject command with project name as argument
                var res = new Object();
                res.value = "addProject name";
                res.name = $4;
                return res;  
            }  

This works fine if command is as follows:

project -a -n samplePro  

But gives error if command is:

project -a -n project  

Error : Expecting TEXT and got PROJECTCOMMAND.
Same happens if project name in command is project1, project2, myproject, etc.. Is there any way I can fix this?
Thanks in advance


Solution

  • One way to solve this is to use state. The formal name for what I call "state" here is "start condition" but I find that "state" is a clearer term to me than "start condition".

    1. I've declared a new lexer state with %x TEXT. There is an INITIAL state that exists implicitly. This is the state in which the lexer starts. Any pattern that does not get a state specified exists only in the INITIAL state.

    2. I've put <TEXT> in front of the pattern that results in the TEXT token so that this token is generated only when we are in the TEXT state.

    3. I've set the pattern for white space to apply to the states INITIAL and TEXT.

    4. I've made it so that -n causes the lexer to enter the TEXT state and when a TEXT token is encountered, the state is popped.

    With this in place, when Jison encounters -n in project -a -n project it gets into the TEXT state where the only things expected are spaces, which are ignored, or TEXT tokens. Jison then processes the white space, which it ignores. Then it processes the text that follows which is understood as a TEXT token and pops the state.

    Complete code:

    %lex
    
    %x TEXT
    
    %%
    "project"   {return 'PROJECTCOMMAND';}
    "-n"        {this.begin('TEXT'); return 'NAMEOPTION';}
    ("--add"|"-a")  {return 'ADDOPTION';}  
    <TEXT>[-a-zA-Z0-9@\.]+ {this.popState(); return 'TEXT';}
    <INITIAL,TEXT>\s+         // Ignore white space...
    
    /lex
    
    %%
    
    line :   
       PROJECTCOMMAND ADDOPTION NAMEOPTION TEXT 
                {
                    //Prject command with project name as argument
                    var res = new Object();
                    res.value = "addProject name";
                    res.name = $4;
                    return res;  
                }  ;