【问题标题】:Jison parser generator shift reduce conflict with parenthesis, how to solve?Jison parser generator shift reduce与括号冲突,如何解决?
【发布时间】:2020-03-14 11:02:43
【问题描述】:

我正在尝试在我的解析器中实现括号,但我的语法出现了冲突。 “语法冲突:当前瞻标记为 ) 时可能执行多个操作” 这是它的简化版本:

// 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 吗?还是这是一种类似于 VBA 但在所有细节上都不相同的语言?
  • @rici 仍在尝试实现 vba
  • 我的理解是VBA不允许Foo(a,b)形式的调用语句;只有Call Foo(a,b)Foo a, b。至少,它是这么说的here
  • " 如果使用 Call 关键字调用需要参数的过程,argumentlist 必须用括号括起来。如果省略 Call 关键字,则还必须省略argumentlist 周围的括号。"
  • @rici,不,您可以省略 call 关键字并同时使用 Foo(a,b) Foo a,b

标签: parsing bison yacc parser-generator jison


【解决方案1】:

在 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"],

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多