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