Ich versuche, ein semantisches Prädikat im Lexer zu verwenden, um einen Token vorauszusehen, aber irgendwie kann ich es nicht richtig machen. Hier ist, was ich habe:ANRLR4 lexer semantisches Prädikat Problem
Lexer Grammatik
lexer grammar TLLexer;
DirStart
: { getCharPositionInLine() == 0 }? '#dir'
;
DirEnd
: { getCharPositionInLine() == 0 }? '#end'
;
Cont
: 'contents' [ \t]* -> mode(CNT)
;
WS
: [ \t]+ -> channel(HIDDEN)
;
NL
: '\r'? '\n'
;
mode CNT;
CNT_DirEnd
: '#end' [ \t]* '\n'?
{ System.out.println("--matched end--"); }
;
CNT_LastLine
: ~ '\n'* '\n'
{ _input.LA(1) == CNT_DirEnd }? -> mode(DEFAULT_MODE)
;
CNT_Line
: ~ '\n'* '\n'
;
Parser Grammatik
parser grammar TLParser;
options { tokenVocab = TLLexer; }
dirs
: (dir
| NL
)*
;
dir
: DirStart Cont
contents
DirEnd
;
contents
: CNT_Line* CNT_LastLine
;
Im Wesentlichen jede Zeile in dem Zeug in dem CNT-Modus ist Freiform, aber es beginnt nie mit #end gefolgt von optionalen Leerzeichen. Grundsätzlich möchte ich das #end Tag im Standard-Lexer-Modus beibehalten.
Meine Testeingang ist wie folgt:
#dir contents
..line..
#end
Wenn ich dies in grun laufen bekomme ich folgende
$ grun TL dirs test.txt
--matched end--
line 3:0 extraneous input '#end\n' expecting {CNT_LastLine, CNT_Line}
So klar CNT_DirEnd abgestimmt wird, aber irgendwie das Prädikat nicht erkennt es .
Ich weiß, dass diese besondere Aufgabe kein semantisches Prädikat erfordert, aber das ist nur der Teil, der nicht funktioniert. Der eigentliche Parser, obwohl er ohne das Prädikat geschrieben werden kann, wird viel weniger sauber sein, wenn ich einfach die Übereinstimmung des Tags #end in den Modus CNT verschiebe.
Danke,
Kesha.
Es scheint CNT_Line definiert ist als nicht übereinstimmend mit '..line ..' –
@ThomasG Es stimmt überein, was Sie mit der Option -gui sehen können, oder wenn Sie DRUCK-Aktionen zu CNT_Line hinzufügen (dann druckt grun es dreimal, weil es nie aus der CNT-Modus) und CNT_LastLine (druckt es nie). –