我一直在为 Lua 编程语言开发编译器,并决定使用 Bison 来生成 AST。出现了一个非常烦人的错误,我对函数调用的语法定义被解析为标识符,然后是表达式组 (
( ... )
)。这是相关代码:
variable
: IDENTIFIER_T
| prefix_expression LEFT_SQUARE_T expression RIGHT_SQUARE_T
{ $$ = node_expression_index(@$, $1, $3); }
| prefix_expression DOT_T IDENTIFIER_T
{ $$ = node_name_index(@$, $1, $3, false); }
;
prefix_expression
: call
| LEFT_PARAN_T expression RIGHT_PARAN_T
{ $$ = node_expression_group(@$, $2); }
| variable_name_reference
;
arguments
: LEFT_PARAN_T RIGHT_PARAN_T
{ $$ = NULL; }
| LEFT_PARAN_T expression_list RIGHT_PARAN_T
{ $$ = $2; }
| STRING_T
;
call
: prefix_expression arguments
{ $$ = node_call(@$, $1, $2, false); }
| prefix_expression COLON_T IDENTIFIER_T arguments
{ $$ = node_call(@$, node_name_index(@$, $1, $3, true), $4, true); }
;
expression
: NIL_T | FALSE_T | TRUE_T | NUMBER_T | STRING_T | VARARG_T
| binary_operation | prefix_expression | unary_operation | array_constructor
| table_constructor
| FUNCTION_T function_body
{ $$ = $2; }
;
variable_name_reference
的定义在这里:
variable_name_reference
: variable
{ $$ = node_name_reference(@$, $1); }
;
换句话说,
print(f())
会给出语法错误,因为野牛将 f()
解析为 f ()
(表示规则分隔的空格)。
我尝试将调用定义移动到 variable_name_reference 定义之上,希望解析器首先尝试找到函数调用。
我能够解决这个问题!我在不同的语法定义中使用了
variable_name_reference
,这让 Bison 感到困惑。我提供的语法定义是有效的。