...パーザとレクサー間の通信を許可する方法はありますか?
いいえ、カスタムレクサーを作成しないでください。 ANTLRのデフォルトのlexer/parserには厳密な分離があります。つまり、lexerはパーサーとは別に動作します。
しかし、私が見る限り、これは必要ありません。あなたは再帰的にレクサールールを呼び出すことができます。だから、あなたがタグの始まりである<element
を見つけたときは、先読みして/>
または>
と一致するかのいずれかになります。 >
が一致する場合は、<
以外の文字を一致させるか、このレクサールール全体を再帰的に呼び出してください。その最後にはもちろん、</element>
があるはずです。
迅速なデモ(属性なしには、簡単な文法を維持する):
grammar Test;
parse
: (t=. {System.out.printf("type=\%-15s text='\%s'\n", tokenNames[$t.type], $t.text);})* EOF
;
XML
: '<' Identifier ('/>'
| '>' (~'<' | XML)* '</' Identifier '>'
)
;
Identifier
: ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
;
QAssign
: '?='
;
SCol
: ';'
;
Spaces
: (' ' | '\t' | '\r' | '\n')+ {skip();}
;
あなたが今入力パーサ場合:
X ?= <element>text<another/>more<i><b>text</b></i></element>;
はあなたがコンソールに出力されている以下の表示されます。
を
type=Identifier text='X'
type=QAssign text='?='
type=XML text='<element>text<another/>more<i><b>text</b></i></element>'
type=SCol text=';'
ご覧のとおり、XMLブロックは単一のトークンとして扱われています。それらの間にPCDATAトークンを持つopeneingとclosingタグトークンを使用する場合は、 "opening tags"の数を数え、その数が0より大きい場合は、~'<'+
のようにPCDATAトークンと一致させる必要があります。このアプローチでは、レクサーとパーサーの間で通信する必要もありません。オープニングタグを保持するカウンタは、レクサーで定義されます。
デモ:
grammar Test;
@lexer::members {
private int openTags = 0;
}
parse
: any* EOF
;
any
: Identifier
| QAssign
| SCol
| xml
;
xml
: OTag (PCData | xml)* CTag
| Tag
;
PCData
: {openTags > 0}?=> ~'<'+
;
OTag
: '<' Identifier ('>' {openTags++;} | '/>' {$type=Tag;})
;
CTag
: '</' Identifier '>' {openTags--;}
;
Identifier
: ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
;
QAssign
: '?='
;
SCol
: ';'
;
Spaces
: (' ' | '\t' | '\r' | '\n')+ {skip();}
;
fragment Tag : ;
が今のように入力をパース:
おかげバート:
すると、次のパースになります。私が探していたソリューションより優れた優れた答えです! –
ようこそ@AndrewMatthews。 –