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

问题描述:

我试图捕捉看起来像 _SC弹钢琴1 在树上用3个节点“_SC”“玩”和“钢琴1”ANTLR语法如何捕捉所有字符到行尾

的命令

到目前为止,我已经得到了语法

grammar PBScript; 
options { 
output = AST; 
language = CSharp2; 
} 

line :  COMMAND WS ACTION; 
COMMAND : '_SC'; 
ACTION : 'play'; 
WS : (' '|'\t')+ ; 

当我创建另一个规则来捕捉,像这样的“钢琴1”的一部分:

grammar PBScript; 
options { 
output = AST; 
language = CSharp2; 
} 

line :  COMMAND WS ACTION WS PARAMETER; 
COMMAND : '_SC'; 
ACTION : 'play'; 
WS : (' '|'\t')+; 
PARAMETER 
    :  (~('\n'|'\r'))+ ; 

我得到一个MismatchedTokenExceptio N(6!= 5)。我知道语法错了,我知道它为什么错了。这是不明确的,因为WS与PARAMETER重叠。我只是不知道如何解决它。

除_SC和PARAMETER之外还有其他动作应该是可选的,最终甚至会有不同的线型,看起来像Name: blah blah blah,我至少需要在树中使用“Name”和“blah blah blah”以防万一这很重要,但现在我只是想弄清楚PARAMETER的用途。

〜汤姆

编辑:字符串“钢琴1”应该是不换行字符的任意字符串所以从第一个非空白戏后,该行的末尾。

+0

不能更改你的语法,这样的命令_SC玩“钢琴1” ,而不是_SC播放钢琴1?引号将消除歧义。 – Eduardo 2012-02-28 10:31:55

+0

双引号字符作为字符串的一部分有效。如果我只希望其他程序员使用它,我可以强迫他们摆脱双引号,但是我将这些交给那些不特别使用计算机的人。 – majinnaibu 2012-02-29 01:06:32

您不能在您的词法分析器中使用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'; 

如果现在分析你输入"_SC play Piano 1"你最终用下面的AST:

enter image description here

+0

嗨巴特,我想问你关于user1237541语法中的PARAMETER规则。你说ANTLR的词法分析器贪婪地匹配了令牌:所以PARAMETER会吞噬整条线:不会创建命令或动作令牌。但我认为如果COMMAND标记被定义在PARAMETER标记之前,解析器将匹配COMMAND标记。这是一个案子吗? TNX。 – vldmrrdjcc 2012-02-28 12:16:58

+1

@ VladimirRadojicic,只有两个规则匹配相同数量的字符,首先定义的字符才会“赢”。由于'PARAMETER'匹配最多的字符,*它*“胜利”。 – 2012-02-28 12:23:41

+0

我认为这就是我正在寻找的东西,但是当我解析它时,我会得到一些稍微不同的东西。 [链接](http://bayimg.com/NAMBHAAdp) – majinnaibu 2012-02-29 10:48:41

此语法将解析您的_SC弹钢琴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 

您将获得以下分析树:

enter image description here

然后,当你制作AST语法时,你应该使用命令的名字s为您的命令,例如:if Name Of command == _SC do something etc ...