Antlr4 对于简单语法,在输入时没有可行的替代方案

Antlr4 对于简单语法,在输入时没有可行的替代方案,antlr4,Antlr4,我正在尝试使用ANTLR 4为一个简单的DSL创建一个解析器。我从我的测试和ANTLRWorks中得到“输入时没有可行的替代方案” 语法: grammar Test; process: action ('|' action)* ; action: (filter) | (transform) | (log); transform: 'transform' '(' ( ('name' '=' transformName)|('regex' '=' regex)) ')' ; transformNa

我正在尝试使用ANTLR 4为一个简单的DSL创建一个解析器。我从我的测试和ANTLRWorks中得到“输入时没有可行的替代方案”

语法:

grammar Test;
process: action ('|' action)* ;
action: (filter) | (transform) | (log);
transform: 'transform' '(' ( ('name' '=' transformName)|('regex' '=' regex)) ')' ;
transformName: NAME;
filter: 'filter' '(' ( ('name' '=' filterName)|('regex' '=' regex)) ')' ;
filterName: NAME;
regex: QUOTEDSTRING;
log: 'log' ('(' 'name' '=' logName (',' 'level' '=' logLevel)? ')')? ;
logName: NAME;
logLevel: NAME;
NAME : [a-zA-Z][a-zA-Z0-9_.]* ;
STRING : (~["])+ ;
QUOTEDSTRING: '"' STRING '"';
WS :  [ \t\r\n\u000C]+ -> skip ;
输入:

log (name=mylog,level=debug)

感谢您的帮助

我认为您混合了ANTLR4语法和ANTLR3语法(由ANTLRWorks支持)

试试这样吧

grammar Test;
eval    :process EOF;
process :action ('|' action)*;
action  :(filter) | (transform) | (log);
transform   :'transform' '(' ( ('name' '=' transformName)|('regex' '=' regex)) ')' ;
transformName   :NAME;
filter  :'filter' '(' ( ('name' '=' filterName)|('regex' '=' regex)) ')' ;
filterName  :NAME;
regex   :QUOTEDSTRING;
log :'log' ('(' 'name' '=' logName (',' 'level' '=' logLevel)? ')')? ;
logName :NAME;
logLevel:NAME;
WS  
    :   (
             ' '
        |    '\r'
        |    '\t'
        |    '\u000C'
        |    '\n'
        ) 
            {
                skip();
            }          
    ;
QUOTEDSTRING    :'"' NAME '"';
NAME    :('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*;
似乎是这样的


您的lexer令牌不是间断的:

NAME : [a-zA-Z][a-zA-Z0-9_.]* ;
STRING : (~["])+ ;
QUOTEDSTRING: '"' STRING '"';
WS :  [ \t\r\n\u000C]+ -> skip ;
NAME : [a-zA-Z][a-zA-Z0-9_.]* ;
QUOTEDSTRING: '"' (~["])+? '"';
WS :  [ \t\r\n\u000C]+ -> skip ;
ANTLR首先在输入上处理这些规则。令牌是这些规则中匹配的最长序列。由于
STRING
包含了几乎所有内容(双引号除外):

log(name=mylog,level=debug)
作为字符串匹配,因为它匹配字符、空格、括号和相等运算符的序列。没有其他令牌类型获得如此长的匹配,所以字符串是首选

要解决此问题,请将lexer规则分离:

NAME : [a-zA-Z][a-zA-Z0-9_.]* ;
STRING : (~["])+ ;
QUOTEDSTRING: '"' STRING '"';
WS :  [ \t\r\n\u000C]+ -> skip ;
NAME : [a-zA-Z][a-zA-Z0-9_.]* ;
QUOTEDSTRING: '"' (~["])+? '"';
WS :  [ \t\r\n\u000C]+ -> skip ;

QUOTEDSTRING将只匹配以双引号开头和结尾的长序列。您的行将不包含任何字符串。

我可能应该自己解决这个问题,但有时需要另一双眼睛。谢谢你指的是名字还是WS?我从权威的ANTLR4参考资料中得到了上述信息,而ANTLRWorks的设计就是为了与ANTLR3一起工作。你试过我的例子吗?