Antlr4:如何更改语法以解析链接元素?

时间:2016-11-17 01:52:32

标签: parsing antlr4

我需要一个语法来解析分隔标记的双点,如:

1..5v[1]..v[2]1+f(1)..2+v[f(2)]..3+f(3)

基本上,这些标记表示整数范围,例如,1..5表示范围1到5的整数。标记文字只应表示为" Integer..Integer"

我还必须解析一些整数文字和真正的文字。 所以目前,我有一个自下而上的语法:

unary_expr
  : range_expr                 # ToRangeExpr
  | PLUS rhs=unary_expr        # UnaryPlusExpr
  | MINUS rhs=unary_expr       # UnaryMinusExpr
  | NOT rhs=unary_expr         # UnaryNotExpr
  ;

range_expr
  : index_expr                             # ToIndexExpr
  | lhs=index_expr RANGEDOT rhs=index_expr # RangeExpr
  | lhs=range_literal rhs=index_expr       # RangeLiteralExpr
  ;

index_expr
  : atom                      # ToAtom
  | atom LBRACK expression RBRACK   # IndexExpr
  ;

atom
  : vector_atom               # ToVectorAtom
  | matrix_atom               # ToMatrixAtom
  | boolean_literal           # ToBooleanLiteral
  | int_literal               # ToIntegerLiteral
  | real_literal              # ToRealLiteral
  | char_literal              # ToCharLiteral
  | string_literal            # ToStringLiteral
  | tuple_literal             # ToTupleLiteral
  | range_literal             # ToRangeLiteral
  | tuple_element             # ToTupleElement
  | type_cast                 # ToTypeCast
  | stream_state              # ToStreamState
  | function_call             # ToFunctionCall
  | ID                        # IDAtom
  | IDENTITY                  # IdentityLiteral
  | NULL                      # NullLiteral
  | LPAREN expression RPAREN  # ToSubExpr


range_literal: RANGE_LITERAL;

RANGE_LITERAL
    : INT_LITERAL RANGEDOT INT_LITERAL
    ;

REAL_LITERAL
    : DOT US+ INT_LITERAL REAL_EXP?
    | INT_LITERAL DOT US* INT_LITERAL? REAL_EXP?
    | INT_LITERAL REAL_EXP
    | DOT INT_LITERAL REAL_EXP
    ;

REAL_EXP
    : 'e' US* (PLUS | MINUS |)? US* INT_LITERAL
    ;

INT_LITERAL: NUM (NUM | US)*;

目前,我的语法可以解析多整数链式范围标记。但是,我无法解析任何多表达式链接范围标记。我试图将range_expr更改为(使其更加模糊):

range_expr
  : range_literal
  | index_expr (RANGEDOT index_expr*)
  ;

但是,它并没有改变我的解析敏感度。那么我应该做些什么改变让我的语法解析多个index_expr链式范围标记?

2 个答案:

答案 0 :(得分:1)

说明

我无法重复使用你的语法(因为缺少词法分析器/解析器规则)但是如果我正确理解了这个问题:你想要一个简单的两个数字范围或者将任意数量的{{{ 1}}。这样做的想法是在expr中创建一个子规则,该子规则将匹配数字范围(index_expr的专用版本),并具有exprChain的递归定义,该定义将由链接表达式(expr)。

解决方案

作为这个想法的一个例子,我介绍了小语法。

exprChain

此示例语法能够匹配您提到的所有远程表达式:grammar test; INT : [0-9]+; REAL : [0-9]* '.' [0-9]+; NAME : [a-zA-Z]+; numeric : INT | REAL ; reference : NAME # variable | NAME '[' expr ']' # array | NAME '(' expr ')' # functionCall ; index_expr : numeric '..' numeric # rangeOfNumbers | expr # classicExpr ; expr : expr '+' expr # exprAdd | reference # exprRef | numeric # exprNumber | expr '..' expr # exprChain ; 1..5(作为.1...3),rangeOfNumbersv[1]..v[2](两者)作为1+f(1)..2+v[f(2)]..3+f(3))。

答案 1 :(得分:0)

问题是我无法在语法中将range_expr视为unary_expr,因为它会将antlr4与real_literal选项混淆,并强制使用antlr4匹配{{1} }令牌(即logic_exprxor,我没有在我的问题中显示它们。在我的微观修复之后,部分语法将是:

or