我正在尝试捕获一个看起来像_SC弹奏钢琴1的命令到一个有3个节点的树"_SC""play"和"Piano 1"
我到目前为止的语法是
grammar PBScript;
options {
output = AST;
language = CSharp2;
}
line : COMMAND WS ACTION;
COMMAND : '_SC';
ACTION : 'play';
WS : (' '|'\t')+ ;
Run Code Online (Sandbox Code Playgroud)
当我创建另一个规则以捕获"钢琴1"部分时,如下所示:
grammar PBScript;
options {
output = AST;
language = CSharp2;
}
line : COMMAND WS ACTION WS PARAMETER;
COMMAND : '_SC';
ACTION : 'play';
WS : (' '|'\t')+;
PARAMETER
: (~('\n'|'\r'))+ ;
Run Code Online (Sandbox Code Playgroud)
我得到一个MismatchedTokenException(6!= 5).我知道语法是错的,我知道为什么它是错的.这是不明确的,因为WS与PARAMETER重叠.我只是不知道如何解决它.
除了_SC和PARAMETER之外还有其他的动作应该是可选的,甚至会有一个不同的线型最终看起来像Name: blah blah blah我在树中至少需要"名字"和"等等等等",以防万一重要但是对现在我只想弄清楚PARAMETER的用途.
〜汤姆
编辑:字符串"钢琴1"应该是任何非换行符的字符串,所以从播放到行尾之后的第一个非空格.
你不能PARAMETER在你的词法分析器中使用这样的规则.ANTLR的词法分析器贪婪地匹配令牌:因此PARAMETER会吞噬整行:不会创建任何令牌COMMAND或ACTION令牌.
为了能够将某些内容匹配到行尾,您需要一个解析器规则.但是解析器必须具有新行的概念(即词法分析器将需要生成新行令牌).
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';
Run Code Online (Sandbox Code Playgroud)
如果你现在解析你的输入,"_SC play Piano 1"你最终得到以下AST:

| 归档时间: |
|
| 查看次数: |
4002 次 |
| 最近记录: |