Parsing ANTLR 4语法分析器

Parsing ANTLR 4语法分析器,parsing,compiler-construction,antlr,antlr4,Parsing,Compiler Construction,Antlr,Antlr4,如何改进解析器语法,从而不必为测试代码创建包含两条decFunc规则的AST。它将只创建一个,并且sum将成为第二个根。我试图用多种不同的方法来解决这个问题,但我总是得到一个左递归错误。 这是我的测试代码: f :: [Int] -> [Int] -> [Int] f x y = zipWith (sum) x y sum :: [Int] -> [Int] sum a = foldr(+) a 这是我的语法: 这是此链接中有两个decFunc的图像 测试输入包含两个与de

如何改进解析器语法,从而不必为测试代码创建包含两条
decFunc
规则的AST。它将只创建一个,并且
sum
将成为第二个根。我试图用多种不同的方法来解决这个问题,但我总是得到一个左递归错误。 这是我的测试代码:

f :: [Int] -> [Int] -> [Int]
f x y = zipWith (sum) x y
sum :: [Int] -> [Int]
sum a = foldr(+) a
这是我的语法: 这是此链接中有两个
decFunc
的图像


测试输入包含两个与
decFunc
规则匹配的内容实例。生成的解析树精确地显示:两个子树,每个子树的根为
deFunc

Antlr v4不会产生真正的AST,其中
f
sum
是独立子树的根

我能用语法做些什么来同时做
f
sum
根吗

不是直接在Antlr v4语法中。你可以:

  • 切换到Antlr v3或其他解析器工具,并根据需要定义生成的AST
  • 遍历antlrv4解析树并创建所需表单的单独AST
  • 只要直接使用解析树,就可以认识到它在信息上等同于经典定义的AST,并且实现提供了许多实际好处
  • 具体而言,标准学术AST是可变的,这意味着每个(或除第一个以外的所有)访问者都是自定义的,而不是生成的,并且AST的基本语法或临时结构的任何更改都需要重新考虑,并且可能会对每个后续访问者及其实现的逻辑进行更改

    Antlr v4解析树本质上是不可变的,允许对树节点累积修饰,而不会丢失关系完整性。访问者都使用一个公共的基本结构,大大减少了由于语法变化和先前执行的访问者的影响而导致的脆弱性。实际上,除非明确要求,否则树行步道易于建造、快速且相互独立。它们可以在设计中实现更大的关注点分离,并在实践中更易于代码维护


    为整个作业选择合适的工具,无论您以何种方式定义它。

    所需的输出是什么?说“创建一个而不是两个
    decFunc
    ”没有多大意义。尝试创建一个类似于您想要的AST。@Mephy我改进了我的问题。我基本上是想让sum引用另一个stat,它可以是一个声明或实现。然而,sum仅仅是声明或实现的第一个词,我如何才能做到这一点?这就是我所要求的。有人建议向前看。但我不知道怎么做,直到不清楚你在问什么。测试输入包含两个与
    decFunc
    规则匹配的内容实例。生成的解析树正好显示:两个子树,每个子树都有一个
    deFunc
    实例作为根。Antlr v4不会生成真正的AST,其中
    f
    sum
    是独立子树的根,如果这是您正在寻找的,则。@GRosenberg感谢您的回答。我能用语法做些什么来做f和和和的根吗?谢谢你宝贵的时间和你的回答。它帮助我认识到,如果我要继续使用ANTLR4,我应该接受AST的现状。我想问你,在实现翻译人员、听众或访问者时,你更喜欢哪一种。翻译将生成另一个不需要计算的代码。访问者和侦听器之间唯一实际的区别是访问者传递一个返回对象,而侦听器不传递任何内容。在某些情况下,返回对象可能很有用。真正取决于你决定它是否有助于你的具体设计。
    prog        : stat+;
    
    stat        : decFunc  | impFunc ;
    
    
    decFunc     : ID '::' formalType ( ARROW formalType )* NL impFunc
                ;
    
    anotherFunc : ID+;
    
    
    formalType  : 'Int' | '[' formalType ']' ;
    
    
    impFunc     : ID+ '=' hr NL
    
                ;
    
    
    hr          : 'map' '(' ID* ')'  ID*
                    | 'zipWith' '(' ('*' |'/' |'+' |'-') ')' ID+ | 'zipWith' '(' anotherFunc ')' ID+
                    | 'foldr'   '(' ('*' |'/' |'+' |'-') ')' ID+
                    | hr  op=('*'| '/' | '.&.' | 'xor' ) hr | DIGIT
                    | 'shiftL' hr hr | 'shiftR' hr hr
                    | hr  op=('+'| '-') hr | DIGIT
                    | '(' hr ')'
                    | ID '(' ID* ')'
                    | ID
                    ;