Jison parser generator shift reduce 与括号冲突,如何解决?
Jison parser generator shift reduce conflict with parenthesis, how to solve?
我试图在我的解析器中实现括号,但我的语法出现冲突。
"Conflict in grammar: multiple actions possible when lookahead token is )"
这是它的简化版本:
// grammar
{
"Root": ["", "Body"],
"Body": ["Line", "Body TERMINATOR Line"],
"Line": ["Expression", "Statement"],
"Statement": ["VariableDeclaration", "Call", "With", "Invocation"],
"Expression": ["Value", "Parenthetical", "Operation", "Assign"],
"Identifier": ["IDENTIFIER"],
"Literal": ["String", "Number"],
"Value": ["Literal", "ParenthesizedInvocation"],
"Accessor": [". Property"],
"ParenthesizedInvocation": ["Value ParenthesizedArgs"],
"Invocation": ["Value ArgList"],
"Call": ["CALL ParenthesizedInvocation"],
"ParenthesizedArgs": ["( )", "( ArgList )"],
"ArgList": ["Arg", "ArgList , Arg"],
"Arg": ["Expression", "NamedArg"],
"NamedArg": ["Identifier := Value"],
"Parenthetical": ["( Expression )"],
"Operation": ["Expression + Expression", "Expression - Expression"]
}
//precedence
[
['right', 'RETURN'],
['left', ':='],
['left', '='],
['left', 'IF'],
['left', 'ELSE', 'ELSE_IF'],
['left', 'LOGICAL'],
['left', 'COMPARE'],
['left', '&'],
['left', '-', '+'],
['left', 'MOD'],
['left', '\'],
['left', '*', '/'],
['left', '^'],
['left', 'CALL'],
['left', '(', ')'],
['left', '.'],
]
在我的实现中,我需要这样的函数调用(括号和逗号分隔):
Foo(1, 2)
Foo 1, 2
并且能够使用正则括号来表示操作的优先级。即使在函数调用中(但仅在带括号的函数调用中):
Foo(1, (2 + 4) / 2)
Foo 1, 2
不带括号的函数调用被视为语句,带括号的函数调用被视为表达式。
我该如何解决这个冲突?
在VBA中,函数调用语句(相对于表达式)有两种形式(简化):
CALL name '(' arglist ')'
name arglist
请注意,第二个参数列表没有括号。这正是为了避免歧义:
Func (3)
这就是您 运行 的歧义。
歧义在于不清楚括号是围绕参数列表的括号,还是围绕括号表达式的括号。这不是本质上的歧义,因为结果实际上是相同的。但它仍然很重要,因为程序可能会这样继续:
Foo (3), (4)
在这种情况下,必须将括号解析为括号表达式周围的括号。
因此,一种可能是将您的语法修改为类似于 VBA reference:
中的语法
call-statement = "Call" (simple-name-expression / member-access-expression / index-expression / with-expression)
call-statement =/ (simple-name-expression / member-access-expression / with-expression) argument-list
但我想您确实想实现一种类似于 VBA 的语言,但又不想严格遵守。这让事情稍微复杂一些。
作为第一个近似值,您可以要求表单 name '(' [arglist] ')'
至少有两个参数(除非它为空):
# Not tested
"Invocation": ["Literal '(' ArgList2 ')' ", "Literal '(' ')' ", "Literal ArgList"],
"ArgList": ["Arg", "ArgList2"],
"ArgList2": ["Arg ',' Arg", "ArgList2 ',' Arg"],
我试图在我的解析器中实现括号,但我的语法出现冲突。 "Conflict in grammar: multiple actions possible when lookahead token is )" 这是它的简化版本:
// grammar
{
"Root": ["", "Body"],
"Body": ["Line", "Body TERMINATOR Line"],
"Line": ["Expression", "Statement"],
"Statement": ["VariableDeclaration", "Call", "With", "Invocation"],
"Expression": ["Value", "Parenthetical", "Operation", "Assign"],
"Identifier": ["IDENTIFIER"],
"Literal": ["String", "Number"],
"Value": ["Literal", "ParenthesizedInvocation"],
"Accessor": [". Property"],
"ParenthesizedInvocation": ["Value ParenthesizedArgs"],
"Invocation": ["Value ArgList"],
"Call": ["CALL ParenthesizedInvocation"],
"ParenthesizedArgs": ["( )", "( ArgList )"],
"ArgList": ["Arg", "ArgList , Arg"],
"Arg": ["Expression", "NamedArg"],
"NamedArg": ["Identifier := Value"],
"Parenthetical": ["( Expression )"],
"Operation": ["Expression + Expression", "Expression - Expression"]
}
//precedence
[
['right', 'RETURN'],
['left', ':='],
['left', '='],
['left', 'IF'],
['left', 'ELSE', 'ELSE_IF'],
['left', 'LOGICAL'],
['left', 'COMPARE'],
['left', '&'],
['left', '-', '+'],
['left', 'MOD'],
['left', '\'],
['left', '*', '/'],
['left', '^'],
['left', 'CALL'],
['left', '(', ')'],
['left', '.'],
]
在我的实现中,我需要这样的函数调用(括号和逗号分隔):
Foo(1, 2)
Foo 1, 2
并且能够使用正则括号来表示操作的优先级。即使在函数调用中(但仅在带括号的函数调用中):
Foo(1, (2 + 4) / 2)
Foo 1, 2
不带括号的函数调用被视为语句,带括号的函数调用被视为表达式。
我该如何解决这个冲突?
在VBA中,函数调用语句(相对于表达式)有两种形式(简化):
CALL name '(' arglist ')'
name arglist
请注意,第二个参数列表没有括号。这正是为了避免歧义:
Func (3)
这就是您 运行 的歧义。
歧义在于不清楚括号是围绕参数列表的括号,还是围绕括号表达式的括号。这不是本质上的歧义,因为结果实际上是相同的。但它仍然很重要,因为程序可能会这样继续:
Foo (3), (4)
在这种情况下,必须将括号解析为括号表达式周围的括号。
因此,一种可能是将您的语法修改为类似于 VBA reference:
中的语法call-statement = "Call" (simple-name-expression / member-access-expression / index-expression / with-expression)
call-statement =/ (simple-name-expression / member-access-expression / with-expression) argument-list
但我想您确实想实现一种类似于 VBA 的语言,但又不想严格遵守。这让事情稍微复杂一些。
作为第一个近似值,您可以要求表单 name '(' [arglist] ')'
至少有两个参数(除非它为空):
# Not tested
"Invocation": ["Literal '(' ArgList2 ')' ", "Literal '(' ')' ", "Literal ArgList"],
"ArgList": ["Arg", "ArgList2"],
"ArgList2": ["Arg ',' Arg", "ArgList2 ',' Arg"],