【问题标题】:Generating AST from ANTLR Grammar: arrays inside structs从 ANTLR 语法生成 AST:结构中的数组
【发布时间】:2012-04-09 20:15:42
【问题描述】:

我正在尝试从 ANTLR 语法解析和生成 AST。当我尝试解析结构内部的数组和结构数组时,我发现了一些问题。

这是一个声明示例:

TYPE MY_ARRAY : 
     ARRAY [ 0..2 ] OF INT;
END_TYPE

TYPE est :
     STRUCT
          c1 : INT;
          c : MY_ARRAY;
     END_STRUCT;
END_TYPE

TYPE MSA : 
    ARRAY [ 0..2 ] OF est; 
END_TYPE

VAR 
      MA : MY_ARRAY;
      STR : est;
      STR2 : MSA;
END_VAR

我对声明没有任何问题。我无法编写语法来解析表达式,如下所示:

STR.c[1]
STR2[2].c[1]

下一个代码显示了我的 ANTLR 语法的摘录:

operand
    : variable_simbolic
    | DIRECT_VAR<Localization>
    | CTE_INT<ConstantINT>
    | CTE_BOOL<ConstantBOOL>
    | CTE_REAL<ConstantREAL>
    ;

variable_simbolic
    : (ID -> ID<Identificador>) ( (('[' operand (',' operand)* ']') -> ^(ARRAY_ACCESS<ArrayAccess> ID<Identificador> operand+))
                    | (('.' operand )   -> ^(FIELD_ACCESS<FieldAccess> ID<Identificador> operand))
                    | (('#' operand )   -> ^(ENUM_ACCESS<EnumAccess> ID<Identificador> operand))
                    )?
    ;

此语法允许我解析 STR.c1MA[1] 之类的表达式,但它不解析 STR.c[1] 之类的表达式。如果定义了数组访问,则它必须是父表达式。我希望下一张图有所帮助:

有什么方法可以修改我的语法以接受那种表达方式吗?提前谢谢你。

【问题讨论】:

    标签: antlr interpreter abstract-syntax-tree


    【解决方案1】:

    可能是这样的:

    operand
     : variable_simbolic
     | CTE_INT
     ;
    
    variable_simbolic
     : (ID -> ID) (variable_simbolic_tail -> ^(ID variable_simbolic_tail))?
     ;
    
    variable_simbolic_tail
     : array variable_simbolic_tail?  -> ^(ARRAY_ACCESS array variable_simbolic_tail?)
     | '.' ID variable_simbolic_tail? -> ^(FIELD_ACCESS ID variable_simbolic_tail?)
     | '#' ID variable_simbolic_tail? -> ^(ENUM_ACCESS ID variable_simbolic_tail?)
     ;
    
    array
     : '[' operand (',' operand)* ']' -> ^(ARRAY_OPS operand+)
     ;
    

    ?

    编辑

    我提出了一种稍微不同的方式。与其尝试构建具有许多不同级别的复杂 AST,不如简单地创建一个 LOOKUP AST 并将 tails 作为子节点添加到该 ast。

    一个小例子语法:

    grammar T;  
    
    options {
      output=AST;
    }
    
    tokens {
      LOOKUP;
      ARRAY_ACCESS;
      FIELD_ACCESS;
      ENUM_ACCESS;
    }
    
    parse
     : operand EOF
     ;
    
    operand
     : variable_simbolic
     | CTE_INT
     ;
    
    variable_simbolic
     : ID variable_simbolic_tail* -> ^(LOOKUP ID variable_simbolic_tail*)
     ;
    
    variable_simbolic_tail
     : '[' operand (',' operand)* ']' -> ^(ARRAY_ACCESS operand+)
     | '.' ID                         -> ^(FIELD_ACCESS ID)
     | '#' ID                         -> ^(ENUM_ACCESS ID)
     ;
    
    CTE_INT : '0'..'9'+;
    ID      : ('a'..'z' | 'A'..'Z') ('a'..'z' | 'A'..'Z'  |'0'..'9')*;
    SPACE   : (' ' | '\t' | '\r' | '\n')+ {skip();};
    

    如果你解析输入:STR2[2].c[1],你会得到以下 AST:

    孩子们从左到右走很容易评估。

    【讨论】:

    • 感谢您的回答。该语法可以正确解析所有内容,但不会生成我需要的 AST 节点层次结构。在您的语法中,根节点始终是一个 ID,我需要 ARRAY_ACCESS 作为根节点,然后是 FIELD_ACCESS,最后是 ID。有什么办法吗?再次感谢您。
    • @JoseEsperon,请参阅我的编辑
    • 我一直在更改我的语言解释器以使用该语法。现在,我可以说它完美无缺。 LR 语法让我发疯(我习惯了 LL 语法)。非常感谢您的帮助;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多