Antlr4 如果存在第二个操作数,则必须使用Antlr语法生成布尔运算符

Antlr4 如果存在第二个操作数,则必须使用Antlr语法生成布尔运算符,antlr4,Antlr4,如果用户输入A和B,则解析将正确进行。但若用户输入一个B(并没有逻辑运算符),那个么解析器不会抱怨缺少“AND”标记。 我已尝试将此用于解析器规则: 布尔表达式 :simpleFilter((AND)+simpleFilter)*#SimF ; 但解析器停止考虑第二个操作数。表示如果用户输入“ab”,则仅为第一个操作数“A”生成AST,而不分析B 如果用户输入“ab”而不是“A和B”,我希望解析器抱怨缺少布尔运算符 任何帮助都将不胜感激,因为我一直试图解决这个问题,但徒劳无功 语法文件如下所述

如果用户输入A和B,则解析将正确进行。但若用户输入一个B(并没有逻辑运算符),那个么解析器不会抱怨缺少“AND”标记。 我已尝试将此用于解析器规则: 布尔表达式 :simpleFilter((AND)+simpleFilter)*#SimF ;

但解析器停止考虑第二个操作数。表示如果用户输入“ab”,则仅为第一个操作数“A”生成AST,而不分析B

如果用户输入“ab”而不是“A和B”,我希望解析器抱怨缺少布尔运算符 任何帮助都将不胜感激,因为我一直试图解决这个问题,但徒劳无功

语法文件如下所述

grammar Filter;

/* Parser rules */

filter

    :   LPAREN logicalExpression RPAREN   #ParenthesizedFilter
    |   logicalExpression EOF           #CmopositeFilterHash;

logicalExpression
       : booleanAndExpression ( OR booleanAndExpression )*                     #LogExp
       ;

booleanAndExpression
    :  simpleFilter ((AND) ? simpleFilter )*                                  #SimF
    ;

simpleFilter
    :NOT simpleFilter                                                        #NegateFilter
    | key=STR op=EQ value=(STR | DECIMAL)                                   #EqualsFilter
    |   key=STR op=NE value=(STR | DECIMAL)                                         #NotEqualsFilter
    |   key=STR op=GT value=(STR | DECIMAL)                                         #GreaterThanFilter
    |   key=STR op=GE value=(STR | DECIMAL)                            #GreaterThanEqualsFilter
    |   key=STR op=LT value=(STR | DECIMAL)                                         #LessThanFilter
    |   key=STR op=LE value=(STR | DECIMAL)                                         #LessThanEqualsFilter
    |   key=STR op=IN referenceValue                                                #InReferenceFilter
    |   key=STR op=NOT op=IN referenceValue                                         #NotInReferenceFilter
    |   key=STR op=BETWEEN fromValue=(STR | DECIMAL) AND toValue=(STR | DECIMAL)    #RangeFilter
    |   key=STR NOT BETWEEN fromValue=(STR | DECIMAL) AND toValue=(STR | DECIMAL)   #OutsideRangeFilter
    |   key=STR op=IN array                                                         #InArrayFilter
    |   key=STR NOT IN array                                                        #NotInArrayFilter
    |   key=STR op=CONTAINS value=(STR | DECIMAL)                                   #ContainsFilter
    |   key=STR NOT CONTAINS value=(STR | DECIMAL)                                  #NotContainsFilter
    |   DOLLAR LCURLY FILTER SEP id=(DECIMAL | STR) SEP name=STR RCURLY             #ReferenceFilter;

array
    :   LBRACKET (arrayItem SEP*)+ RBRACKET ;

arrayItem
    :   value=(STR | DECIMAL)
    |   referenceValue ;

referenceValue
    :   DOLLAR LCURLY type=LIST SEP id=(STR | DECIMAL) SEP name=(STR | DECIMAL) RCURLY ;


/* Lexer Rules*/

SEP: 
',' | ';';

LIST
: 'List' ;

FILTER: 'Filter';

DOLLAR: '$';
LCURLY: '{';
RCURLY: '}';
LPAREN: '(';
RPAREN: ')';
LBRACKET: '[';
RBRACKET: ']';
GT: '>';
GE: '>=';
LT: '<';
LE: '<=';
EQ: '=';
NE: '!=';
NOT: '!' | 'not' | 'NOT';
AND: 'AND' | 'and';
OR: 'OR' | 'or';
IN: 'in' | 'IN';
BETWEEN: 'between' | 'BETWEEN';
CONTAINS: 'contains' | 'CONTAINS';
AND_MUST: 'AND';

DECIMAL: '-'? DIGIT+ ( '.' DIGIT+ )? ;
fragment DIGIT: [0-9] ;
STR: ALPHANUMERIC+ | '"' (ALPHANUMERIC | [ ] | '""')+ '"';
fragment ALPHANUMERIC: [a-z0-9A-Z!.:@#$%&^*'+/?_`~-];

WS  : [ \t\r\n\f]+ -> skip ;
语法过滤器;
/*解析器规则*/
滤波器
:LPAREN LogicalPression RPAREN#圆括号过滤器
|逻辑表达式EOF#CmopositeFilterHash;
逻辑表达
:booleanAndExpression(或booleanAndExpression)*#LogExp
;
布尔表达式
:simpleFilter((和)?simpleFilter)*#SimF
;
单纯形滤波器
:非简单过滤器#否定过滤器
|key=STR op=EQ值=(STR |十进制)#EqualsFilter
|key=STR op=NE value=(STR |十进制)#NotEqualsFilter
|key=STR op=GT value=(STR |十进制)#大于过滤器
|key=STR op=GE value=(STR |十进制)#大于equalsfilter
|key=STR op=LT value=(STR |十进制)#LessThanFilter
|key=STR op=LE value=(STR |十进制)#LessThanEqualsFilter
|key=STR op=IN referenceValue#IN referencefilter
|key=STR op=NOT op=IN referenceValue#notin referencefilter
|key=STR op=介于fromValue=(STR | DECIMAL)和toValue=(STR | DECIMAL)#RangeFilter之间
|key=STR不在fromValue=(STR | DECIMAL)和toValue=(STR | DECIMAL)#过滤器之间
|key=STR op=IN数组#inarayFilter
|key=STR不在数组中#NotInArrayFilter
|key=STR op=CONTAINS value=(STR |十进制)#CONTAINS过滤器
|key=STR不包含值=(STR |十进制)#不包含筛选器
|美元LCURLY FILTER SEP id=(十进制| STR)SEP name=STR RCURLY#ReferenceFilter;
排列
:LBRACKET(arrayItem SEP*)+RBRACKET;
arrayItem
:value=(STR |十进制)
|参考价值;
参考值
:DOLLAR LCURLY type=列表SEP id=(STR | DECIMAL)SEP name=(STR | DECIMAL)RCURLY;
/*Lexer规则*/
九月:
',' | ';';
列表
:“名单”;
过滤器:“过滤器”;
美元:“$”;
立法会:“{”;
循环:'}';
LPAREN:'(';
RPAREN:')';
勒布朗:“[”;
RBRACKET:']';
GT:“>”;
GE:“>=”;

LT:“此语法不解析“A和B”,更不用说从
booleanAndExpression
filter
开始解析“A和B”。我怀疑您的驱动程序代码(您没有提供)没有检查parse和lex中的错误条件。我无法告诉您正在使用的目标,因此很难知道您的构建环境是什么,以及它是否正常工作。但是,我也会调查一下

这是一个完整的C#应用程序,语法保持原样()。驱动程序代码由我的Antlr4BuildTasks.Templates生成,并使用Antlr v4.9和Antlr4BuildTasks,这也是我编写的。驱动程序检查解析错误,打印出两个示例的标记和树。在“A和B”和“A B”中,解析都失败。下面是在这些输入上运行语法的输出

A and B
line 1:2 no viable alternative at input 'Aand'
line 1:2 no viable alternative at input 'Aand'
line 1:7 no viable alternative at input 'B'
line 1:7 no viable alternative at input 'B'
error in parse.
[@0,0:0='A',<25>,1:0]
[@1,2:4='and',<18>,1:2]
[@2,6:6='B',<25>,1:6]
[@3,7:6='<EOF>',<-1>,1:7]
( booleanAndExpression
  ( simpleFilter
  )
  ( simpleFilter
    ( STR i=0 txt=A tt=25 DEFAULT_TOKEN_CHANNEL
  ) )
  ( AND i=1 txt=and tt=18 DEFAULT_TOKEN_CHANNEL
  )
  ( simpleFilter
  )
  ( simpleFilter
    ( STR i=2 txt=B tt=25 DEFAULT_TOKEN_CHANNEL
) ) )

A B
line 1:2 no viable alternative at input 'AB'
line 1:2 no viable alternative at input 'AB'
error in parse.
[@0,0:0='A',<25>,1:0]
[@1,2:2='B',<25>,1:2]
[@2,3:2='<EOF>',<-1>,1:3]
( booleanAndExpression
  ( simpleFilter
  )
  ( simpleFilter
    ( STR i=0 txt=A tt=25 DEFAULT_TOKEN_CHANNEL
  ) )
  ( simpleFilter
    ( STR i=1 txt=B tt=25 DEFAULT_TOKEN_CHANNEL
) ) )
A和B
第1行:2输入“A”处无可行的替代方案
第1行:2输入“A”处无可行的替代方案
第1行:7在输入“B”处没有可行的替代方案
第1行:7在输入“B”处没有可行的替代方案
分析错误。
[@0,0:0='A',1:0]
[@1,2:4='and',1:2]
[@2,6:6='B',1:6]
[@3,7:6='',,1:7]
(布尔表达式
(简单过滤器
)
(简单过滤器
(STR i=0 txt=A tt=25默认令牌信道
) )
(i=1 txt=和tt=18默认\u令牌\u信道
)
(简单过滤器
)
(简单过滤器
(STR i=2 txt=B tt=25默认令牌信道
) ) )
A B
第1行:2输入“AB”处无可行的替代方案
第1行:2输入“AB”处无可行的替代方案
分析错误。
[@0,0:0='A',1:0]
[@1,2:2='B',1:2]
[@2,3:2='',,1:3]
(布尔表达式
(简单过滤器
)
(简单过滤器
(STR i=0 txt=A tt=25默认令牌信道
) )
(简单过滤器
(STR i=1 txt=B tt=25默认令牌信道
) ) )
下面是一些修正语法的建议。我做了一些改变

  • 您应该养成查看来自Antlr工具的警告消息的习惯,并解决它们。警告
    …Filter.g4:76:0:令牌和_中的一个值必须不可访问。并且始终由标记和
    重叠。规则
    AND_必须:'AND'永远无法匹配,因为lexer始终匹配第一条规则。由于规则
    以及
    和_必须
    匹配同一字符串,并且
    出现在
    和_必须
    之前,因此它将始终匹配,
    和_必须
    将永远不匹配。您应该删除
    和_MUST
    规则。(a) Antlr在创建令牌时尝试匹配尽可能多的输入字符;(b) 当两个或多个lexer规则可以匹配相同的输入时,首先定义的规则获胜

  • Antlr解析输入字符串,直到满足规则。如果部分字符串起作用,它将这样做,而不会抱怨输入的其余部分。来自
    布尔表达式
    的解析,不使用
    EOF进行扩充
    
      $ grun Question_OP filter -tokens input1.txt 
      [@0,0:0='A',<STR>,1:0]
      [@1,2:4='and',<AND>,1:2]
      [@2,6:6='B',<STR>,1:6]
      [@3,8:7='<EOF>',<EOF>,2:0]
      line 1:2 no viable alternative at input 'Aand'
      line 2:0 no viable alternative at input 'B'
    
    simpleFilter
         : NOT simpleFilter
         | key=STR op=EQ value=(STR | DECIMAL)
         ...
         | DOLLAR LCURLY FILTER SEP id=(DECIMAL | STR) SEP name=STR RCURLY
         ;
    grammar Filter;
    
    filter
        :   LPAREN logicalExpression RPAREN                      #ParenthesizedFilter
        |   logicalExpression EOF                                #CompositeFilterHash;
    
    logicalExpression
        :   booleanAndExpression ( OR booleanAndExpression )*    #LogExp
        ;
    
    booleanAndExpression
        :    simpleFilter ((AND) ? simpleFilter )*                #SimF
        ;
    
    simpleFilter
        : NOT simpleFilter                                        #NegateFilter
        | key=STR op=EQ value=(STR | DECIMAL)                     #EqualsFilter
        ;
    
    LPAREN : '(' ;
    RPAREN : ')' ;
    EQ     : '=' ;
    NOT    : '!' | 'not' | 'NOT' ;
    AND    : 'AND' | 'and' ;
    OR     : 'OR' | 'or' ;
    DECIMAL: '-'? DIGIT+ ( '.' DIGIT+ )? ;
    STR    : ALPHANUMERIC+ | '"' (ALPHANUMERIC | [ ] | '""')+ '"' ;
    WS     : [ \t\r\n\f]+ -> skip ;
    
    fragment ALPHANUMERIC: [a-z0-9A-Z!.:@#$%&^*'+/?_`~-];
    fragment DIGIT: [0-9] ;
    $ grun Filter filter -tokens input1.txt 
    [@0,0:0='A',<STR>,1:0]
    [@1,2:4='and',<AND>,1:2]
    [@2,6:6='B',<STR>,1:6]
    [@3,8:7='<EOF>',<EOF>,2:0]
    line 1:2 mismatched input 'and' expecting '='
    line 2:0 mismatched input '<EOF>' expecting '='
    $ cat input1.txt 
    A and B
    
    simpleFilter
        : STR
        ;
    A and B
     A B
    $ grun Filter filter -tokens -gui input.txt 
    [@0,0:0='A',<STR>,1:0]
    [@1,2:4='and',<AND>,1:2]
    [@2,6:6='B',<STR>,1:6]
    [@3,8:8='A',<STR>,2:0]
    [@4,10:10='B',<STR>,2:2]
    [@5,12:11='<EOF>',<EOF>,3:0]
    
    grammar Question;
    
    prog
        :   ( line NL )+ EOF
        ;
    
    line
        :   expr      {System.out.println("Found expression `" + $expr.text + "`");}
        |   a=ID b=ID {System.out.println("Hey user, you forgot the `and` between " + $a.text + " and " + $b.text + " !");}
        ;
    
    expr
        :   NOT expr                    # ExprNot
        |   expr AND expr               # ExprAnd
        |   expr OR  expr               # ExprOr
        |   simpleFilter                # SimF
        |   LPAREN expr RPAREN          # ParenthesizedExpression
        ;
    
    simpleFilter
        :   ID
        |   STRING
        ;
    
    LPAREN : '(' ;
    RPAREN : ')' ;
    NOT    : '!' | 'not' | 'NOT' ;
    AND    : 'AND' | 'and' ;
    OR     : 'OR' | 'or' ;
    ID     : [a-zA-Z_]+ ;  
    STRING : '"' .*? '"' ;
    WS     : [ \t]+ -> channel(HIDDEN) ;
    NL     : [\r\n\f]+ ;
    
    A and B
    A B
    C or "xyz"
    
    $ export CLASSPATH=".:/usr/local/lib/antlr-4.9-complete.jar"
    $ alias a4='java -jar /usr/local/lib/antlr-4.9-complete.jar'
    $ alias grun='java org.antlr.v4.gui.TestRig'
    $ a4 Question.g4 
    $ javac Question*.java
    $ grun Question prog -tokens input.txt 
    [@0,0:0='A',<ID>,1:0]
    [@1,1:1=' ',<WS>,channel=1,1:1]
    [@2,2:4='and',<AND>,1:2]
    [@3,5:5=' ',<WS>,channel=1,1:5]
    [@4,6:6='B',<ID>,1:6]
    [@5,7:7='\n',<NL>,1:7]
    [@6,8:8='A',<ID>,2:0]
    [@7,9:9=' ',<WS>,channel=1,2:1]
    [@8,10:10='B',<ID>,2:2]
    [@9,11:11='\n',<NL>,2:3]
    [@10,12:12='C',<ID>,3:0]
    [@11,13:13=' ',<WS>,channel=1,3:1]
    [@12,14:15='or',<OR>,3:2]
    [@13,16:16=' ',<WS>,channel=1,3:4]
    [@14,17:21='"xyz"',<STRING>,3:5]
    [@15,22:22='\n',<NL>,3:10]
    [@16,23:22='<EOF>',<EOF>,4:0]
    Found expression `A and B`
    Hey user, you forgot the `and` between A and B !
    Found expression `C or "xyz"`
    
    AND_MUST: 'AND';