我正在尝试解析并从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.c1
或MA[1]
这样的表达式,但它不解析像STR.c[1]
这样的表达式。如果定义了数组访问,则必须是父表达式。我希望下图有所帮助:
有没有办法修改我的语法来接受那种表达?提前谢谢。
答案 0 :(得分: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:
可以通过从左到右走孩子来轻松评估。