0

我正在使用 Jison 包开发 clike 语言编译器。在我介绍了课程之前,我做得很好,因此Type可以成为LITERAL现在。这是一个简化的语法:

%lex

%%
\s+                       /* skip whitespace */

int                       return 'INTEGER'
string                    return 'STRING'
boolean                   return 'BOOLEAN'
void                      return 'VOID'
[0-9]+                    return 'NUMBER'
[a-zA-Z_][0-9a-zA-Z_]*    return 'LITERAL'
"--"                      return 'DECR'
<<EOF>>                   return 'EOF'
"="                       return '='
";"                       return ';'


/lex

%%

Program
  : EOF
  | Stmt EOF
  ;

Stmt
  : Type Ident ';'
  | Ident '=' NUMBER ';'
  ;

Type
  : INTEGER
  | STRING
  | BOOLEAN
  | LITERAL
  | VOID
  ;

Ident
  : LITERAL
  ;

和jison冲突:

Conflict in grammar: multiple actions possible when lookahead token is LITERAL in state 10
- reduce by rule: Ident -> LITERAL
- reduce by rule: Type -> LITERAL
Conflict in grammar: multiple actions possible when lookahead token is = in state 10
- reduce by rule: Ident -> LITERAL
- reduce by rule: Type -> LITERAL

States with conflicts:
State 10
  Type -> LITERAL . #lookaheads= LITERAL =
  Ident -> LITERAL . #lookaheads= LITERAL =

我发现了一个非常相似的问题,没有得到回答,有没有人知道如何解决这个问题?

4

1 回答 1

1

这显然是 jison 中的一个错误,因为语法肯定是 LALR(1),并且由 bison 处理没有问题。显然,jison 错误地计算了发生冲突的状态的前瞻。(更新:似乎是错误 205,于 2014 年 1 月报告。)

如果您要求 jison 生成 LR(1) 解析器而不是 LALR(1) 语法,那么它会正确计算前瞻,并且语法会在没有警告的情况下通过。但是,我认为这不是一个可持续的解决方案。

这是另一种解决方法。DeclAssign产生式不是必需的;“修复”是从中删除LITERALType为其添加单独的产品。

Program
  : EOF
  | Stmt EOF
  ;

Decl
  : Type Ident ';'
  | LITERAL Ident ';'
  ;

Assign
  : Ident '=' NUMBER ';'
  ;

Stmt
  : Decl
  | Assign
  ;

Type
  : INTEGER
  | STRING
  | BOOLEAN
  | VOID
  ;

Ident
  : LITERAL
  ;

您可能需要考虑识别多个陈述:

Program
  : EOF
  | Stmts EOF
  ;

Stmts
  : Stmt
  | Stmts Stmt
  ;
于 2015-12-17T16:17:21.237 回答