我从https://raw.githubusercontent.com/bkiers/tiny-language-antlr4/master/src/main/antlr4/tl/antlr4/TL.g4下载了TL Grammar
在尝试之后,我意识到语法无法处理顶层的用户定义函数调用
例如,如果你的文件内容是:
def s(n)
return n+n;
end
s("5", "6");
你监听一个FunctionCallExpression,你不会得到一个回调。但是,如果您的文件内容是:
def s(n)
return n+n;
end
s(s("5"))
你会得到回电话
您的输入:
s("5", "6");
由以下语句匹配(不是表达式!):
functionCall
: Identifier '(' exprList? ')' #identifierFunctionCall
| ...
;
和"5", "6"
是exprList
匹配的两个表达式。
输入s(s("5"))
中的第一个s
将再次匹配identifierFunctionCall
,而内部的s
将作为表达式匹配(准确地说是functionCallExpression
)。
下面是不同的解析树:
s("5", "6");
'- parse
|- block
| '- statement
| |- identifierFunctionCall
| | |- s
| | |- (
| | |- exprList
| | | |- stringExpression
| | | | '- "5"
| | | |- ,
| | | '- stringExpression
| | | '- "6"
| | '- )
| '- ;
'- <EOF>
s(s("5"));
'- parse
|- block
| '- statement
| |- identifierFunctionCall
| | |- s
| | |- (
| | |- exprList
| | | '- functionCallExpression
| | | '- identifierFunctionCall
| | | |- s
| | | |- (
| | | |- exprList
| | | | '- stringExpression
| | | | '- "5"
| | | '- )
| | '- )
| '- ;
'- <EOF>
简而言之:语法按照它应该的方式工作。
编辑
一个有效的TL脚本是一个代码块,其中每个代码块由语句组成。为了简化语法并消除一些模棱两可的规则(这是较老的ANTLRv3所需要的),最简单的方法是不允许语句是简单表达式。例如,以下代码不是有效的TL脚本:
1 + 2;
。1 + 2
不是一个语句,而是一个表达式。
函数调用可以是一个语句,但是,当它放在赋值语句的右边时,它也可以是一个表达式:
foo(); // this is a statement
i = foo(); // now foo is an expression
这就是为什么您观察到一个s(...)
触发了某个enter...()
方法,而另一个没有。