简体   繁体   English

Jison解析器生成器,移位减少语法冲突,如何解决?

[英]Jison parser generator, shift reduce grammar conflict, how to solve?

I'm currently working on visual basic converter using jison, and I have these conflicts in my grammar:我目前正在使用 jison 开发 Visual Basic 转换器,并且我的语法中有这些冲突:

Conflict in grammar: multiple actions possible when lookahead token is ELSE in state 11
- reduce by rule: If -> IfBlock
- shift token (then go to state 16)
Conflict in grammar: multiple actions possible when lookahead token is ELSE_IF in state 11
- reduce by rule: If -> IfBlock
- shift token (then go to state 17)
Conflict in grammar: multiple actions possible when lookahead token is TERMINATOR in state 27
- reduce by rule: IfBlock -> IF Expression THEN Body
- shift token (then go to state 13)
Conflict in grammar: multiple actions possible when lookahead token is TERMINATOR in state 29
- reduce by rule: IfBlock -> IfBlock ELSE_IF Expression THEN Body
- shift token (then go to state 13)

States with conflicts:
State 11
  If -> IfBlock . #lookaheads= $end TERMINATOR IF_END ELSE ELSE_IF SUB_END
  If -> IfBlock .ELSE Body IF_END #lookaheads= $end TERMINATOR IF_END ELSE ELSE_IF SUB_END
  IfBlock -> IfBlock .ELSE_IF Expression THEN Body #lookaheads= $end ELSE ELSE_IF TERMINATOR SUB_END IF_END
State 27
  IfBlock -> IF Expression THEN Body . #lookaheads= $end ELSE ELSE_IF TERMINATOR SUB_END IF_END
  Body -> Body .TERMINATOR Line
  Body -> Body .TERMINATOR
State 29
  IfBlock -> IfBlock ELSE_IF Expression THEN Body . #lookaheads= $end ELSE ELSE_IF TERMINATOR SUB_END IF_END
  Body -> Body .TERMINATOR Line
  Body -> Body .TERMINATOR



Here is simplified version of my grammar (actions deleted):这是我的语法的简化版本(已删除操作):

const grammar = {
  Root: [
    [
      ''
    ],
    [
      'Body'
    ]
  ],
  Body: [
    [
      'Line'
    ],
    [
      'Body TERMINATOR Line'
    ],
    [ 'Body TERMINATOR' ]
  ],
  Line: [ [ 'Expression' ], [ 'Statement' ] ],
  Statement: [ [ 'Return' ], [ 'If' ] ],
  Expression: [ [ 'Code' ] ],
  Return: [
    [
      'RETURN Expression'
    ],
    [
      'RETURN'
    ]
  ],
  Code: [
    [
      'SUB_START Identifier PARAM_START ParamList PARAM_END TERMINATOR Body SUB_END'
    ]
  ],
  IfBlock: [
    [
      'IF Expression THEN Body'
    ],
    [
      'IfBlock ELSE_IF Expression THEN Body'
    ]
  ],
  If: [
    [ 'IfBlock' ],
    [
      'IfBlock ELSE Body IF_END'
    ]
  ]
}

The conflict is happening when I'm trying to implement a rule for If statement, it seems to conflict with the Body rule.当我尝试为 If 语句实施规则时发生冲突,它似乎与 Body 规则发生冲突。

I spent almost a day trying to solve it, but I can't.我花了将近一天的时间试图解决它,但我不能。 I know that the parser can look only one token ahead, but I can't figure out solution by myself.我知道解析器只能向前看一个标记,但我无法自己找出解决方案。 And I'm bound to jison so I cannot use another parser generator.而且我必须使用 jison,所以我不能使用另一个解析器生成器。 Is there any workaround for my grammar?我的语法有什么解决方法吗?

Looking at these these productions:看看这些作品:

If: [
        [ 'IfBlock' ],
        [ 'IfBlock ELSE Body IF_END ']
    ]

It seems to me like the grammar is saying that an if statement must be terminated by IF_END only if it includes an else clause.在我看来,语法似乎是说if语句只有在包含else子句时才必须由IF_END终止。 An if which lacks an else clause cannot be terminated by IF_END .if缺少了else条款不能被终止IF_END

That's not my understanding of the syntax of visual basic.这不是我对visual basic语法的理解。 END_IF is mandatory in the multiline syntax and is not used in the single line syntax. END_IF在多行语法中是强制性的,在单行语法中不使用。

So you have two conflicts, because your If production accepts some statements with END_IF and some without:所以你有两个冲突,因为你的If生产接受一些带有END_IF语句,而END_IF一些则没有:

  • For if statements without END_IF , you have the classic "dangling else" ambiguity.对于没有END_IF if语句,您会遇到经典的“悬空 else”歧义。

  • In addition, for multiline if statements without END_IF , the grammar provides no way to tell whether a following statement is part of the last clause in the if statement or a new statement.此外,对于没有END_IF多行if语句,语法无法判断后面的语句是if语句的最后一个子句还是新语句的一部分。 (That's why multiline if statements need END_IF . (这就是为什么多行if语句需要END_IF

The "dangling else" ambiguity is relatively benign -- that is, the normal resolution which prefers shift to reduce will produce the correct result. “dangling else”的歧义是相对良性的——也就是说,喜欢 shift 到 reduce 的正常分辨率会产生正确的结果。 If you want to eliminate the error message, you can make the resolution explicit using precedence rules, giving ELSE and ELSE_IF higher precedence than IF .如果您想消除错误消息,您可以使用优先级规则明确解析,给予ELSEELSE_IFIF更高的优先级。 To use this technique, you must make the IF visible in the rules which depend on precedence, which basically means removing IF from IfBLock to leave you with:要使用此技术,您必须使IF在依赖于优先级的规则中可见,这基本上意味着从IfBLock删除IF以留下:

IfBlock: [
  [ 'Expression THEN Body' ],
  [ 'IfBlock ELSE_IF Expression THEN Body' ]
],
If: [
  [ 'IF IfBlock' ],
  [ 'IF IfBlock ELSE Body' ]  // IF_END removed
]

You'll also need the precedence relations:您还需要优先关系:

[ 'left', 'IF' ],
[ 'left', 'ELSE', 'ELSE_IF' ]

That will more or less get you going on single-line if statements, except that you'll need to replace Block with something which does not allow a TERMINATOR .这或多或少会让你使用单行 if 语句,除了你需要用不允许TERMINATOR东西替换Block

For multiline if statements, though, you'll need a different syntax:但是,对于多行if语句,您需要不同的语法:

  • The END_IF is mandatory END_IF是强制性的

  • There must be a TERMINATOR after THEN and ELSE , and before ELSE and END_IF . THENELSEELSEEND_IF之前必须有一个TERMINATOR In other words, the blocks of statements in a multiline if must start at the beginning of a line and be terminated with TERMINATOR .换句话说,多行if的语句块必须从一行的开头开始并以TERMINATOR

These restrictions aren't just cosmetic: They are there because otherwise it is impossible to put a statement after a multiline if statement, since without the END_IF , any following statement would be added to the last THEN or ELSE clause.这些限制不仅仅是装饰性的:它们存在是因为否则不可能在多行if语句之后放置语句,因为没有END_IF ,任何后续语句都将添加到最后一个THENELSE子句。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM