ANTL3 中针对 Javascript 的表达式解析器
我已经开始使用ANTL3,我发现它非常酷,它对多种语言的支持非常棒。
现在我正在尝试使用 Javascript。我扩展了发现的语法@ 函数
我将允许我的用户调用他定义的 在 javascript 中,例如:
function sum(args){
var s=0;
for(var i=0;i<args.length;i++)
s+=args[i];
return s;
}
function avg(args){
var s=sum(args);
return s/args.length;
}
请找到我的语法:
grammar Excel;
options {
output=AST;
language=JavaScript;
}
tokens {
// define pseudo-operations
FUNC;
CALL;
}
parse
: exp EOF -> exp
;
exp
: orExp
;
orExp
: andExp (OR^ andExp)*
;
andExp
: eqExp (AND^ eqExp)*
;
eqExp
: relExp (( EQUALS | NOTEQUALS)^ relExp)*
;
relExp
: addExp ( (LT^|LTEQ^|GT^|GTEQ^) addExp)*
;
addExp
: multExp ( (PLUS^| MINUS^) multExp)*
;
multExp
: unaryExp (( MULT^ | DIV^ | MOD^ |POW^| IS^) unaryExp)*
;
unaryExp
: NOT atom -> ^(NOT atom)
| atom
;
atom
: TRUE
| FALSE
| INT
| FLOAT
| function
| '(' exp ')' -> exp
;
POW : '^';
DIV : '/';
MOD : '%';
MULT : '*';
PLUS : '+';
MINUS : '-';
LT : '<';
LTEQ : '<=';
GT : '>';
GTEQ : '>=';
EQUALS : '==';
NOTEQUALS : '<>';
INT : '0'..'9'+;
FLOAT : ('0'..'9')* '.' ('0'..'9')+;
OR : 'or' ;
AND : 'and' ;
IS : 'is' ;
NOT : 'not' ;
TRUE : 'true' ;
FALSE : 'false' ;
function
: IDENT '(' ( exp (',' exp)* )? ')' -> ^(FUNC IDENT exp*)
;
IDENT
: ('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' |'0'..'9')*
;
SPACE : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;
树语法:
tree grammar ExcelWalker;
options {
tokenVocab=Excel;
ASTLabelType=CommonTree;
language=JavaScript;
}
// `walk` returns a string
walk returns [expr]
: exp {expr = $exp.expr;} //($exp.expr == 1) ? 'True' : 'False';}
//| ^(FUNC IDENT a=exp*)
;
// `exp` returns either 1 (true) or 0 (false)
exp returns [expr]
: ^(OR a=exp b=exp) {expr = ($a.expr == 1 || $b.expr == 1) ? true : false;}
| ^(AND a=exp b=exp) {expr = ($a.expr == 1 && $b.expr == 1) ? true : false;}
| ^(IS a=exp b=exp) {expr = ($a.expr == $b.expr) ? true : false;}
| ^(NOT a=exp) {expr = ($a.expr == 1) ? false : true;}
| ^(LT a=exp b=exp) { expr = a<b;}
| ^(LTEQ a=exp b=exp) { expr = a<=b;}
| ^(GT a=exp b=exp) { expr = a>b;}
| ^(GTEQ a=exp b=exp) { expr = a>=b;}
| ^(PLUS a=exp b=exp) { expr = a+b;}
| ^(MINUS a=exp b=exp) { expr = a-b;}
| ^(MULT a=exp b=exp){ expr = a*b;}
| ^(DIV a=exp b=exp) { expr = a/b;}
| ^(MOD a=exp b=exp) { expr = a \% b;}
| ^(POW a=exp b=exp) { expr = Math.pow(a,b); }
| call { expr=$call.value;}
| TRUE {expr = true;}
| FALSE {expr = false;}
| INT { expr = $INT.text-0;}
| FLOAT { expr = $FLOAT.text-0;}
;
call returns [value]
: ^(FUNC IDENT a=exp*) {
console.info($FUNC.toStringTree());
var fn=$IDENT.text;
var params=[];
for(var i=1;i<$FUNC.getChildCount();i++)
params.push($FUNC.getChild(i));
var method=fn+'(['+params+'])';
alert(method);
var evalResult=eval(method);
value=evalResult;
alert(value);
//alert('function '+fn+' with params '+params.length+' will be called');
//alert($FUNC.getChildCount());alert($IDENT.text);alert(a.toString());
}
;
我的测试装备:
sum(2,3) produces 5
avg(1,2,3) produces 2
但是当我尝试评估时:
sum(2+3,4+7,sum(4,5,6),avg(4,4,4,4))
它失败了。
请帮助我编写正确的 AST walker 来评估多值函数。
提前致谢。
I have started playing with ANTL3, I found it very cool, it's support for multiple languages is awesome.
Right now I am experimenting with Javascript. I've extended the grammar found @
antlr3 - Generating a Parse Tree
I would allow my user to call the functions defined by him in javascript such as:
function sum(args){
var s=0;
for(var i=0;i<args.length;i++)
s+=args[i];
return s;
}
function avg(args){
var s=sum(args);
return s/args.length;
}
Please find my grammar:
grammar Excel;
options {
output=AST;
language=JavaScript;
}
tokens {
// define pseudo-operations
FUNC;
CALL;
}
parse
: exp EOF -> exp
;
exp
: orExp
;
orExp
: andExp (OR^ andExp)*
;
andExp
: eqExp (AND^ eqExp)*
;
eqExp
: relExp (( EQUALS | NOTEQUALS)^ relExp)*
;
relExp
: addExp ( (LT^|LTEQ^|GT^|GTEQ^) addExp)*
;
addExp
: multExp ( (PLUS^| MINUS^) multExp)*
;
multExp
: unaryExp (( MULT^ | DIV^ | MOD^ |POW^| IS^) unaryExp)*
;
unaryExp
: NOT atom -> ^(NOT atom)
| atom
;
atom
: TRUE
| FALSE
| INT
| FLOAT
| function
| '(' exp ')' -> exp
;
POW : '^';
DIV : '/';
MOD : '%';
MULT : '*';
PLUS : '+';
MINUS : '-';
LT : '<';
LTEQ : '<=';
GT : '>';
GTEQ : '>=';
EQUALS : '==';
NOTEQUALS : '<>';
INT : '0'..'9'+;
FLOAT : ('0'..'9')* '.' ('0'..'9')+;
OR : 'or' ;
AND : 'and' ;
IS : 'is' ;
NOT : 'not' ;
TRUE : 'true' ;
FALSE : 'false' ;
function
: IDENT '(' ( exp (',' exp)* )? ')' -> ^(FUNC IDENT exp*)
;
IDENT
: ('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z' |'0'..'9')*
;
SPACE : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;} ;
Tree Grammar:
tree grammar ExcelWalker;
options {
tokenVocab=Excel;
ASTLabelType=CommonTree;
language=JavaScript;
}
// `walk` returns a string
walk returns [expr]
: exp {expr = $exp.expr;} //($exp.expr == 1) ? 'True' : 'False';}
//| ^(FUNC IDENT a=exp*)
;
// `exp` returns either 1 (true) or 0 (false)
exp returns [expr]
: ^(OR a=exp b=exp) {expr = ($a.expr == 1 || $b.expr == 1) ? true : false;}
| ^(AND a=exp b=exp) {expr = ($a.expr == 1 && $b.expr == 1) ? true : false;}
| ^(IS a=exp b=exp) {expr = ($a.expr == $b.expr) ? true : false;}
| ^(NOT a=exp) {expr = ($a.expr == 1) ? false : true;}
| ^(LT a=exp b=exp) { expr = a<b;}
| ^(LTEQ a=exp b=exp) { expr = a<=b;}
| ^(GT a=exp b=exp) { expr = a>b;}
| ^(GTEQ a=exp b=exp) { expr = a>=b;}
| ^(PLUS a=exp b=exp) { expr = a+b;}
| ^(MINUS a=exp b=exp) { expr = a-b;}
| ^(MULT a=exp b=exp){ expr = a*b;}
| ^(DIV a=exp b=exp) { expr = a/b;}
| ^(MOD a=exp b=exp) { expr = a \% b;}
| ^(POW a=exp b=exp) { expr = Math.pow(a,b); }
| call { expr=$call.value;}
| TRUE {expr = true;}
| FALSE {expr = false;}
| INT { expr = $INT.text-0;}
| FLOAT { expr = $FLOAT.text-0;}
;
call returns [value]
: ^(FUNC IDENT a=exp*) {
console.info($FUNC.toStringTree());
var fn=$IDENT.text;
var params=[];
for(var i=1;i<$FUNC.getChildCount();i++)
params.push($FUNC.getChild(i));
var method=fn+'(['+params+'])';
alert(method);
var evalResult=eval(method);
value=evalResult;
alert(value);
//alert('function '+fn+' with params '+params.length+' will be called');
//alert($FUNC.getChildCount());alert($IDENT.text);alert(a.toString());
}
;
My Test Rig:
sum(2,3) produces 5
avg(1,2,3) produces 2
however when I am trying to evaluate:
sum(2+3,4+7,sum(4,5,6),avg(4,4,4,4))
It's getting failed.
Please help me to write proper AST walker to evaluate mutli-value functions.
Thanks in Advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在树语法的
call
规则内,您应该推送exp*
的计算值。目前,您正在将实际 AST 推送到您的params
数组中。将您的
call
规则更改为:现在,表达式:
将被计算为:
Inside the
call
rule of the tree grammar, you should push the evaluated values ofexp*
. At the moment, you're pushing the actual AST's onto yourparams
array.Change your
call
rule to:Now, the expression:
will be evaluated to: