パーサから文脈を伝えてレキサのふるまいを変更する
catalog : item*; item : 'item' ID* ';
- ここで、"item small white item;"のように、'item'というキーワードを含むものが現れた場合にはどうすればよいか?
引用符を使う
item camera item small power plant; item "small white item";文法
catalog : item*; item : 'item' item_name ';';item_name : (ID | QUOTED_STRING)* ; QUOTED_STRING : '"' (options{greedy = false;} : .)* '"';
QUOTED_STRING : '"' ('""' | ~('"'))* '"';
catalog : item*; item : 'item' item_name CONDITION?';'; CONDITION : NESTED_CONDITION; fragment NESTED_CONDITION : '{' (CONDITION_CHAR | NESTED_CONDITION)* '}'; fragment CONDITION_CHAR : ~('{'|'}') ;
Lexical State
<YYINITIAL> "item" {return symbol(K_ITEM);} <YYINITIAL> {Word} {return symbol(WORD);}#br <gettingName> {Word} {return symbol(WORD);}#br ";" {return symbol(SEMI);} {WS} {/* ignore */} {Comment} { /* ignore */}
BNF
catalog ::= item | catalog item ;
item_name ::= WORD:w {: RESULT = w; :} | item_name:n WORD:w {: RESULT = n + " " + w; :} ;
item ::= K_ITEM {: parser.helper.startingItemName(); :} item_name:n {: parser.helper.recognizedItem(n); :} SEMI ;
class ParsingHelper... void recognizedItem(String name) { items.add(name); setLexicalState(Lexer.YYINITIAL); } public void startingItemName() { setLexicalState(Lexer.gettingName); } private void setLexicalState(int newState) { getLexer().yybegin(newState); }
item item the troublesome
Token Type Mutation
catalog : item*; item : 'item' {helper.adjustItemNameTokens();} ID* SEP ; SEP : ';';
void adjustItemNameTokens() { for (int i = 1; !isEndOfItemName(parser.getTokenStream().LA(i)); i++) { assert i < 100 : "This many tokens must mean something's wrong"; parser.getTokenStream().LT(i).setType(parser.ID); } } private boolean isEndOfItemName(int arg) { return (arg == parser.SEP);
Ignoring Token Types
catalog : item*; item : 'item' item_name SEP; item_name : ~SEP* ; SEP : ';';
item : (ID | 'item')* SEP;