C# ANTLR语法如何捕获行尾的所有字符

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

我正在尝试捕获一个命令 _资深大律师弹钢琴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 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';