Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing 解决LALR歧义_Parsing_Compiler Construction_Grammar_Lalr_Ambiguous Grammar - Fatal编程技术网

Parsing 解决LALR歧义

Parsing 解决LALR歧义,parsing,compiler-construction,grammar,lalr,ambiguous-grammar,Parsing,Compiler Construction,Grammar,Lalr,Ambiguous Grammar,我最近对LALR的研究已经足够深入,可以编写一个语法,我正试图为它构建一个java或c风格的语法(其开头是指定的) 我知道编写解析器生成器需要额外的努力,比如重新发明轮子(为什么不使用Antlr?),但我的目标是引导一个业余操作系统,它可以在不依赖第三方工具链的情况下自行编译。我的问题不是生成器,而是语法 我在语句和表达式中遇到了reduce/reduce歧义 我知道如何解决某些类型的歧义,例如悬挂else,但这几个对我来说不是直观的,它们让我感到困惑 解决这些问题的最佳方法是什么?此外,是否有

我最近对LALR的研究已经足够深入,可以编写一个语法,我正试图为它构建一个java或c风格的语法(其开头是指定的)

我知道编写解析器生成器需要额外的努力,比如重新发明轮子(为什么不使用Antlr?),但我的目标是引导一个业余操作系统,它可以在不依赖第三方工具链的情况下自行编译。我的问题不是生成器,而是语法

我在语句和表达式中遇到了reduce/reduce歧义

我知道如何解决某些类型的歧义,例如悬挂else,但这几个对我来说不是直观的,它们让我感到困惑

解决这些问题的最佳方法是什么?此外,是否有一个原型工具,我可以用来帮助可视化的解决方案?或者,我应该回到原点,尝试为语法实现一个GLR解析器生成器吗

这些声明是合法的:

Generic.List<int> myVar1 = x + 4, myVar2; // stmt -> var-decl ;
                                          // var-decl -> type-name var-decl-list

t = 99;                           // simple-stmt -> assign

i++;                              // simple-stmt -> incr-decr
                                  // incr-decr -> primary-expr ++

json.deserialize<list<int>>(obj); // simple-stmt -> call
                                  // call -> primary-expr ( params )
                                  // ...  -> primary-expr . basic-name ( params )
                                  // ...  -> basic-name . basic-name ( params )
当标识符移位时,下一个状态为:

basic-name -> ident *
basic-name -> ident * < type-list >
潜在冲突。在父状态下,lookaheads没有帮助,因为
嵌套名称
主表达式
中有一个点。哦,太好了,让我们试着用嵌套名称来减少:

type-name -> nested-name *
nested-name -> nested-name * . basic-name
这里没什么可看的。。。 现在,用
primary expr
来降低成本怎么样:

unary-expr -> primary-expr *
primary-expr -> primary-expr * . basic-name
primary-expr -> primary-expr * ++
call -> primary-expr * ( params )
incr-decr -> primary-expr * ++
...
现在,当我们使用shift++时,我们得到:

primary-expr -> primary-expr ++ *
incr-decr -> primary-expr ++ *
…另一种方法是减少冲突

让我们尝试移动
而不是
标识

primary-expr -> ( * expr )
unary-op -> ( * type-name )
expr -> * assign-expr
assign-expr -> * assign
assign-expr -> * cond-expr
assign -> * unary-expr assign-op expr
unary-expr -> * unary-op primary-expr
unary-expr -> * primary-expr
unary-op -> * ( typename )
unary-op -> * ! | ~ | ...
primary-expr -> * call
primary-expr -> * primary-expr . basic-name
primary-expr -> * primary-expr ++
primary-expr -> * basic-name
primary-expr -> * ( expr )
call -> * primary-expr ( params )
cond-expr -> * ...
...
rel-expr -> * rel-expr < shift-expr
rel-expr -> * shift-expr
...
type-name -> * nested-name
type-name -> * basic-type
nested-name -> * nested-name . basic-name
nested-name -> * basic-name
basic-name -> * ident < type-list >
basic-name -> * ident
primary expr->(*expr)
一元运算->(*类型名称)
expr->*分配expr
分配表达式->*分配
分配expr->*条件expr
赋值->*一元表达式赋值运算表达式
一元表达式->*一元运算主表达式
一元表达式->*主表达式
一元运算->*(类型名称)
一元运算->*!| ~|。。。
主expr->*呼叫
主表达式->*主表达式基本名称
主表达式->*主表达式++
主表达式->*基本名称
主表达式->*(表达式)
调用->*主表达式(参数)
条件表达式->*。。。
...
rel expr->*rel expr*移位expr
...
类型名称->*嵌套名称
类型名称->*基本类型
嵌套名称->*嵌套名称。基本名称
嵌套名称->*基本名称
基本名称->*标识<类型列表>
基本名称->*标识
标识
移动到堆栈上时也会出现同样的问题

这些就是我到目前为止遇到的问题。由于
basic name
优先于
rel expr
,我假设
x
之类的东西会被解释为
basic name->ident
,如果它实际上是一个关系表达式,就会出错


我的大脑已经到了需要帮助的地步。

你的帖子中有几个问题,这让我觉得不是很理想。但我会尽力为每个问题提供一些想法。在我看来,你有三个问题:

  • 区分表达式语句和非表达式语句的表达式

  • 解析声明中的分层命名类型,而不与表达式语句中的字段访问表达式冲突


  • 区分LALR生成器的使用是否实现了类似bison的优先级声明?如果不是,我们如何解释“因为基本名称优先于rel expr…”?@rici因为
    rel expr
    在这么多步骤中派生出
    basic name
    ,我是说它有更高的优先级。这对我来说没有任何意义。事实上,a派生出B对LR算法的移位或缩减决定没有影响。@rici可能我还不完全理解。因为lookahe只有一个符号ad,为了移动rel expr的
    rel expr*
    。如果我们这样做,即使完整输入是
    x()
    ,我们已经减少到
    rel-expr
    rel-expr*()
    ,我们无法从接下来的3个令牌中获取
    ,因为要做到这一点,我们必须在堆栈上获取
    基本名称->标识*
    ,而不是
    基本名称->rel expr*
    。这当然是一个移位-减少冲突。甚至可能是一个歧义。
    unary-expr -> primary-expr *
    primary-expr -> primary-expr * . basic-name
    primary-expr -> primary-expr * ++
    call -> primary-expr * ( params )
    incr-decr -> primary-expr * ++
    ...
    
    primary-expr -> primary-expr ++ *
    incr-decr -> primary-expr ++ *
    
    primary-expr -> ( * expr )
    unary-op -> ( * type-name )
    expr -> * assign-expr
    assign-expr -> * assign
    assign-expr -> * cond-expr
    assign -> * unary-expr assign-op expr
    unary-expr -> * unary-op primary-expr
    unary-expr -> * primary-expr
    unary-op -> * ( typename )
    unary-op -> * ! | ~ | ...
    primary-expr -> * call
    primary-expr -> * primary-expr . basic-name
    primary-expr -> * primary-expr ++
    primary-expr -> * basic-name
    primary-expr -> * ( expr )
    call -> * primary-expr ( params )
    cond-expr -> * ...
    ...
    rel-expr -> * rel-expr < shift-expr
    rel-expr -> * shift-expr
    ...
    type-name -> * nested-name
    type-name -> * basic-type
    nested-name -> * nested-name . basic-name
    nested-name -> * basic-name
    basic-name -> * ident < type-list >
    basic-name -> * ident
    
    StatementExpression:
      Assignment
      PreIncrementExpression
      PreDecrementExpression
      PostIncrementExpression
      PostDecrementExpression
      MethodInvocation
      ClassInstanceCreationExpression
    
    Expression:
      LambdaExpression
      AssignmentExpression
    
    AssignmentExpression:
      ConditionalExpression
      Assignment
    
    Assignment:
      LeftHandSide AssignmentOperator Expression
    
    ...
    
    UnaryExpression:
      PreIncrementExpression
      + UnaryExpression
      UnaryExpressionNotPlusMinus
    
    PreIncrementExpression:
      ++ UnaryExpression
    
    UnaryExpressionNotPlusMinus:
      PostfixExpression
      ~ UnaryExpression
    
    PostfixExpression:
      Primary
      ExpressionName
      PostIncrementExpression
    
    PostIncrementExpress:
      PostfixExpression ++
    
    assignment-expression:
      conditional-expression
      logical-or-expression assignment-operator initializer-clause
    
    primary-expr : field-access-expr
                 | nested-name
    
    non-field-access-expr:
                   call
                 | post-increment-expression  // was primary-expr ++
                 | ( expr )
                 ...
    
    field-access-expr :
                   non-field-access-expr
                 | field-access-expr . basic-name
    
    ConstructorDeclarator:
      [TypeParameters] SimpleTypeName ( [FormalParameterList] )
    
    MethodInvocation:
      Primary . [TypeArguments] Identifier ( [ArgumentList] )