Reputation: 5454
I'm using Jison to build a simple calculator language, which includes variables. I want these variables to work similar to JavaScript, that is you have to initialise it with the var
keyword the first time. In my language, I want to show an error if a variable gets re-initialise.
var myVar = 4
var myVar = 3
// Error, cannot reinitialise variable myVar on line 2
My question is, how do I get the line number for an AST node? In my grammer file, I can pass the line number from the parser to my AssignVariable
object, but I'm wondering if there is a better way to do this?
stmt
: 'PRINT' expr
{ $$ = new yy.Print($2) }
| 'VAR' 'IDENTIFIER' 'ASSIGN' expr
{ $$ = new yy.AssignVariable($2, $4, $3); $$.lineNo = yylineno }
| 'IDENTIFIER' 'ASSIGN' expr
{ $$ = new yy.SetVariable($1, $3, $2) }
;
I will also need the line number for other nodes in my compiler for other types of error checking.
A more high-level takeaway from this question could be: What's the best way to detect and handle compile time errors using Jison (or similar)?
Upvotes: 4
Views: 1591
Reputation: 5454
I was able to inject the line number into my AST nodes by monkey-patching the generated parser in my compiler. This was suggested by Zach. facepalms
// load in your generated parser
var parser = require('./parser');
// store the current performAction function
parser._performAction = parser.performAction;
// override performAction
parser.performAction = function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) {
// invoke the original performAction
var ret = parser._performAction.call(this, yytext, yyleng, yylineno, yy, yystate, $$, _$);
// Do your own stuff
if (this.$._type) {
this.$.lineNo = yylineno;
}
return ret;
}
Upvotes: 5