W jaki sposób negacja meta-znaku, ~
, może być użyta w regułach lexer i parser ANTLR?Negowanie wewnętrznych zasad i parsera
Odpowiedz
Negowanie może wystąpić wewnątrz lexer and parser rules.
Wewnątrz reguł leksykalnych można negować postacie, a wewnątrz reguł parsera można negować żetony (zasady lexera). Jednak obie reguły lexer i parser mogą negować tylko pojedyncze znaki lub pojedyncze tokeny.
Kilka przykładów:
zasad Lexer
dopasować jeden lub więcej znaków, z wyjątkiem małych liter ASCII, można zrobić:
NO_LOWERCASE : ~('a'..'z')+ ;
(negacja-meta-char, ~
, ma wyższy priorytet niż +
, więc powyższa reguła jest równa (~('a'..'z'))+
)
Zauważ, że 'a'..'z'
dopasowuje pojedynczy znak (i może być zatem zostać zanegowana), ale następująca reguła jest nieprawidłowy:
ANY_EXCEPT_AB : ~('ab') ;
Ponieważ 'ab'
(oczywiście) pasuje 2 znaki, to nie może być zanegowany. Pasujące token, który składa się z 2 znaków, ale nie 'ab'
, trzeba wykonać następujące czynności:
ANY_EXCEPT_AB
: 'a' ~'b' // any two chars starting with 'a' followed by any other than 'b'
| ~'a' . // other than 'a' followed by any char
;
zasad parsera
wewnętrzne zasady parser, ~
neguje pewien znak, lub więcej niż jeden znak. Na przykład, masz następujące tokeny zdefiniowane:
A : 'A';
B : 'B';
C : 'C';
D : 'D';
E : 'E';
Jeśli teraz chcesz dopasować dowolny znak z wyjątkiem A
, robisz:
p : ~A ;
A jeśli chcesz, aby dopasować dowolny znak z wyjątkiem B
i D
, można zrobić:
p : ~(B | D) ;
Jednakże, jeśli chcesz dopasować dowolne dwa znaki inne niż A
następnie B
, ty nie można zrobić:
p : ~(A B) ;
Podobnie jak w przypadku zasad Lexer, nie można negować więcej niż jeden znak. Aby zrealizować powyższe, trzeba zrobić:
P
: A ~B
| ~A .
;
Zauważ, że (DOT) char w ciągu zasad parsera .
robi nie dowolny znak jak ma to miejsce w środku zasad Lexer. Wewnątrz reguł parsera pasuje do dowolnego tokena (w tym przypadku: A
,, D
lub lub lub .
Należy pamiętać, że nie można zanegować reguł parsera. Poniższe informacje są niezgodne z prawem:
p : ~a ;
a : A ;
Dziękujemy za wyjaśnienia. Nie wiedziałem, że operator '~' będzie stosować tokeny, gdy występuje w regule parsera. – Gunther
@Gunther, bez problemu. Często wspominam o tym krótko w moich odpowiedziach, więc od teraz mogę linkować do tego pytania i odpowiedzi. W.r.t. Twój konwerter, być może już go używasz, ale może nie: klasa 'org.antlr.tool.Strip' usuwa cały kod niestandardowy z plików gramatycznych ANTLR, co może ułatwić życie podczas analizowania gramatyk ANTLR. –