以下是语法。
expression
: primary
| expression '.' Identifier
| expression '(' expressionList? ')'
| expression '[' expression ']'
| expression ('++' | '--')
| ('+'|'-'|'++'|'--') expression
| ('~'|'!') expression
| expression ('*'|'/'|'%') expression
| expression ('+'|'-') expression
| expression ('<' '<' | '>' '>' '>' | '>' '>') expression
| expression ('<=' | '>=' | '>' | '<') expression
| expression ('==' | '!=') expression
| expression '&' expression
| expression '^' expression
| expression '|' expression
| expression '&&' expression
| expression '||' expression
| expression '?' expression ':' expression
| <assoc=right> expression
( '='
| '+='
| '-='
| '*='
| '/='
| '&='
| '|='
| '^='
| '>>='
| '>>>='
| '<<='
| '%='
)
expression
;
这个语法是正确的,但无法区分属性访问expr,调用方法expr,数组访问expr。所以我把语法改为
attributeAccessMethod:
expression '.' Identifier;
expression
: primary
| attributeAccessMethod
| expression '(' expressionList? ')'
| expression '[' expression ']'
| expression ('++' | '--')
| ('+'|'-'|'++'|'--') expression
| ('~'|'!') expression
但是这个语法是左递归[expression,attributeAccessMethod] ,那么如何编写更好的语法可以删除左递归并区分这些条件?
答案 0 :(得分:1)
为不同的规则替代添加标签,例如:
expression
: primary # RulePrimary
| expression '.' Identifier # RuleAttribute
| expression '(' expressionList? ')' # RuleExpression
| expression '[' expression ']' # RuleArray
... etc.
当您在此规则中对所有您的替代方案执行此操作时,将针对这些特殊情况生成BaseVisitor或BaseListener以及公共覆盖,您可以根据需要处理每个特殊情况。
答案 1 :(得分:0)
我建议你不要这样定义你的语法。除了@ JLH的回答之外,你的语法还有可能弄乱这些表达的相关性。
我建议的是你应该&#34;自上而下&#34;你的语法与关联顺序。
例如,您可以将语法中的所有文字,方法调用等视为原子(因为它们将始终以文字或标识符开头),并且您将这些原子与关联运算符相关联。
然后你可以写下你的语法:
expression: binary_expr;
// Binary_Expr
// Logic_Expr
// Add_expr
// Mult_expr
// Pow_expr
// Unary_expr
associate_expr
: index_expr # ToIndexExpr
| lhs=index_expr '.' rhs=associate_expr # AssociateExpr
;
index_expr
: index_expr '[' (expression (COMMA expression)*) ']' # IndexExpr
| atom #ToAtom
;
atom
: literals_1 #wwLiteral
| ... #xxLiteral
| ... #yyLiteral
| literals_n #zzLiteral
| function_call # FunctionCall
;
function_call
: ID '(' (expression (',' expression)*)? ')';
// Define Literals
// Literals Block
您的算术表达式的一部分可能如下所示:
add_expr
: mul_expr # ToMulExpr
| lhs=add_expr PLUS rhs=mul_expr #AddExpr
| lhs=add_expr MINUS rhs=mul_expr #SubtractExpr
;
mul_expr
: pow_expr # ToPowExpr
| lhs=mul_expr '+' rhs=pow_expr # MultiplyExpr
| lhs=mul_expr '/' rhs=pow_expr # DivideExpr
| lhs=mul_expr '%' rhs=pow_expr # ModExpr
;
您将左侧视为当前expr,将右侧视为与其他级别关联的expr,以便在保留递归时保持关联顺序。