2012-02-28 51 views
5

我試圖捕捉看起來像 _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

回答

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'; 

如果現在分析你輸入"_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

2

此語法將解析您的_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 ...