如何在 LL(1) 解析器中区分标识符和函数调用

1 compiler-construction parsing

我和我的研究生正在开发一个训练编译器,我们将用它来教授学生“编译器和口译员”主题。输入程序语言是 Java 语言的一个有限子集,编译器实现语言是 Java。

输入语言句法的文法是LL(1),因为它更容易被学生理解和实现。我们在解析器实现中有以下一般问题。在解析过程中如何区分标识符和函数调用?

例如我们可能有:

b = sum(10,5) //sum is a function call  
Run Code Online (Sandbox Code Playgroud)

或者

b = a //a is an identifier  
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,=我们在符号之后都有一个标识符。
是否可以区分在等号之后我们有什么样的构造(函数调用或标识符)=

可能在 LL(1) 解析器中是不可能的,因为我们只能向前看 1 个符号?如果这是真的,您建议如何在语法中定义函数调用?也许在函数调用之前需要一些额外的符号,例如b = @sum(10,5)

你认为这个符号会让学生感到困惑吗?什么样的函数调用符号是合适的?

sep*_*p2k 7

您确实不能在 LL(1) 语法中为函数调用和变量制定单独的规则,因为这需要额外的前瞻。对此的常见解决方案是将它们组合成一个匹配标识符的规则,可选地后跟一个参数列表:

primary_expression ::= ID ( "(" expression_list ")" )?
                     | ...
Run Code Online (Sandbox Code Playgroud)

在函数可以是任意表达式而不仅仅是标识符的语言中,您需要像对待任何其他后缀运算符一样对待它:

postfix_expression ::= primary_expression postfix_operator*

postfix_operator ::= "++"
                   | "--"
                   | "[" expression "]"
                   | "(" expression_list ")"
Run Code Online (Sandbox Code Playgroud)