C# ANTLR语法如何捕获行尾的所有字符
我正在尝试捕获一个命令 _资深大律师弹钢琴1 到具有3个节点的树“\u SC”“play”和“Piano 1” 到目前为止,我掌握的语法是C# ANTLR语法如何捕获行尾的所有字符,c#,antlr,C#,Antlr,我正在尝试捕获一个命令 _资深大律师弹钢琴1 到具有3个节点的树“\u SC”“play”和“Piano 1” 到目前为止,我掌握的语法是 grammar PBScript; options { output = AST; language = CSharp2; } line : COMMAND WS ACTION; COMMAND : '_SC'; ACTION : 'play'; WS : (' '|'\t')+ ; 当我创建另一个规则来捕捉“Piano
grammar PBScript;
options {
output = AST;
language = CSharp2;
}
line : COMMAND WS ACTION;
COMMAND : '_SC';
ACTION : 'play';
WS : (' '|'\t')+ ;
当我创建另一个规则来捕捉“Piano 1”部分时,如下所示:
grammar PBScript;
options {
output = AST;
language = CSharp2;
}
line : COMMAND WS ACTION WS PARAMETER;
COMMAND : '_SC';
ACTION : 'play';
WS : (' '|'\t')+;
PARAMETER
: (~('\n'|'\r'))+ ;
我得到一个不匹配的TokenException(6!=5)。我知道语法是错的,我也知道部分原因。这是不明确的,因为WS-overlaps参数。我只是不知道怎么修
除了_SC和参数应该是可选的之外,还有其他的操作,甚至最终会有一个不同的线型,看起来像Name:blah blah blah
,在树中我至少需要“Name”和“blah blah blah blah”,以防万一,这很重要,但现在我只是想弄清楚参数使用什么
~z~汤姆
编辑:字符串“Piano 1”应该是任何非换行符字符串,因此从播放后的第一个非空白字符到行的结尾。此语法将解析您的_scplay Piano 1语句:
grammar PBScript;
options {
language = CSharp2;
output=AST;
}
tokens
{
COMMAND;
ACTION;
PARAM;
}
program : lines;
lines : line*;
line: 'command:' command action parameter param_modifier
;
command
: IDENTIFIER
-> ^(COMMAND IDENTIFIER)
;
action : IDENTIFIER
-> ^(ACTION IDENTIFIER)
;
parameter : IDENTIFIER
-> ^(PARAM IDENTIFIER)
;
param_modifier : INTEGER
;
IDENTIFIER : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
INTEGER : '0'..'9'+
;
COMMENT
: '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
| '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
;
WS : ( ' '
| '\t'
| '\r'
| '\n'
) {$channel=HIDDEN;}
;
然后,对于输入:
command: _SC play Piano 1
command: _SR doSomething someInstrument 2
您将获得以下解析树:
然后,当您编写AST语法时,您应该为您的命令检查命令名,例如:
如果命令名==\u SC do something
等。您不能在lexer中使用这样的参数
规则。ANTLR的lexer贪婪地匹配令牌:因此参数
会占用整行:不会创建命令
或操作
令牌
为了能够将某个内容匹配到行的末尾,您需要一个解析器规则。但是解析器必须知道新行是什么(即lexer需要生成新行标记)
如果您现在解析您的输入“\u SC play Piano 1”
,您将得到以下结果:
您不能更改语法,使命令为“弹钢琴1”,而不是“弹钢琴1”吗?引号将消除歧义。双引号字符作为字符串的一部分是有效的。如果我只希望其他程序员使用这个,我可以强迫他们避开双引号,但是我把这个交给了那些对计算机不是特别友好的人。嗨,巴特,我想问你关于user1237541语法中的参数规则。您说过ANTLR的lexer贪婪地匹配令牌:所以参数会占用整行:不会创建任何命令或动作令牌。但我认为,若在参数令牌之前定义了命令令牌,解析器将匹配命令令牌。是这样吗?Tnx.@VladimirRadojicic,只有当两个规则匹配相同数量的字符时,第一个定义的规则才会“赢”。因为
PARAMETER
匹配的字符最多,所以它“赢”。我想这就是我要寻找的,但当我解析它时,我得到的结果略有不同@majinnaibu,你可能在用ANTLRWorks的解释器。不要。这是出了名的马车。改为尝试调试器(我发布的AST映像来自调试器)。
grammar T;
options {
output=AST;
}
tokens {
LINE;
PARAMS;
}
line
: COMMAND ACTION rest_of_line NL
-> ^(LINE COMMAND ACTION ^(PARAMS rest_of_line))
;
rest_of_line
: ~NL* // match any token other than a line break zero or more times
;
COMMAND : '_SC';
ACTION : 'play';
WORD : ('a'..'z' | 'A'..'Z')+;
NUMBER : '0'..'9';
WS : (' '|'\t')+ {skip();};
NL : '\r'? '\n' | '\r';