2012-02-28 11 views
5

Próbuję uchwycić polecenie, które wygląda jak _SC grać na pianinie 1 do drzewa z 3 węzły „_SC” „Play” i „Piano 1”ANTLR gramatyka jak uchwycić wszystkie znaki do końca linii

gramatyka mam tak daleko jest

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

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

Kiedy tworzę kolejną regułę, aby uchwycić „Piano 1” część tak:

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

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

dostaję MismatchedTokenExceptio n (6! = 5). Uważam, że gramatyka jest zła i częściowo wiem, dlaczego jest źle. Jest niejednoznaczny, ponieważ WS pokrywa się z PARAMETREM. Po prostu nie wiem, jak to naprawić.

Są inne działania oprócz _SC i PARAMETER powinny być opcjonalne, będzie nawet inny typ linii, który ostatecznie będzie wyglądał jak Name: blah blah blah, gdzie będę potrzebował przynajmniej "Nazwa" i "bla bla bla" w drzewie na wszelki wypadek to się liczy, ale teraz próbuję po prostu dowiedzieć się, co użyć w PARAMETRZE.

~ Tom

EDIT: Ciąg „Piano 1” powinien być dowolny ciąg znaków spoza nowej linii tak od pierwszej nie spacji po grze do końca linii.

+0

Nie możesz zmienić gramatykę tak, że polecenie jest _SC play „Piano 1” zamiast _SC grać na Piano 1? Cytaty usunęłyby niejednoznaczność. – Eduardo

+0

Znaki dwuznaczne są prawidłowe jako część ciągu. Gdybym oczekiwał, że tylko inni programiści skorzystają z tego, mógłbym zmusić ich do ucieczki z podwójnej wersji, ale przekazuję to osobom, które nie są szczególnie przyjazne komputerowi. – majinnaibu

Odpowiedz

5

Nie możesz użyć takiej reguły w swoim lexierze pod numerem PARAMETER. Lexer ANTLR pasuje łapczywie do żetonów: więc PARAMETER pożrełoby całą linię: nie będzie nigdy tworzonych tokenów COMMAND lub ACTION.

Aby móc dopasować coś do końca linii, potrzebna jest dla niego reguła analizatora składni. Ale wtedy parser musi mieć pojęcie o tym, czym jest nowa linia (tj. Lexer będzie musiał generować tokeny nowej linii).

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

Jeśli teraz analizować swój wkład "_SC play Piano 1" chcesz skończyć z następującym AST:

enter image description here

+0

Witam Bart, chciałbym Cię zapytać o regułę PARAMETRU w gramatyce user1237541.Powiedziałeś, że lexer ANTLR pasuje łapczywie do żetonów: więc PARAMETER pożera całą linię: nie będzie nigdy tworzonych tokenów COMMAND lub ACTION. Ale pomyślałem, że jeśli token COMMAND zostanie zdefiniowany przed tokenem PARAMETER, parser dopasuje token COMMAND. Czy to jest przypadek? Tnx. – vldmrrdjcc

+1

@ VladimirRadojicic, tylko jeśli obie reguły pasują do tej samej liczby znaków, pierwsza zdefiniowana "wygra". Ponieważ 'PARAMETER' pasuje do większości znaków, * it *" wygrywa ". –

+0

Myślę, że tego właśnie szukam, ale kiedy parsuję to dostaję coś nieco innego. [link] (http://bayimg.com/NAMBHAAdp) – majinnaibu

2

Ta gramatyka będzie analizować swoją _SC grać na pianinie 1 oświadczenie:

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

Następnie na wejściu:

command: _SC play Piano 1 

command: _SR doSomething someInstrument 2 

Dostaniesz następujące drzewo składniowy:

enter image description here

Następnie, kiedy tworzysz gramatykę AST, powinieneś sprawdzić nazwy polecenia s dla twoich poleceń, na przykład: if Name Of command == _SC do something itd ...

Powiązane problemy