ANTLR语法如何捕获所有字符到行尾

maj*_*ibu 4 c# antlr

我正在尝试捕获一个看起来像_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"应该是任何非换行符的字符串,所以从播放到行尾之后的第一个非空格.

Bar*_*ers 5

你不能PARAMETER在你的词法分析器中使用这样的规则.ANTLR的词法分析器贪婪地匹配令牌:因此PARAMETER会吞噬整行:不会创建任何令牌COMMANDACTION令牌.

为了能够将某些内容匹配到行尾,您需要一个解析器规则.但是解析器必须具有新行的概念(即词法分析器将需要生成新行令牌).

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:

在此输入图像描述