0

R6RS 用のレクサー/パーサーを作成しようとしていますが、データをスキップするコメントに悩まされています。

これが私のレクサー/パーサールールの一部です:

BOOLEAN: '#t' | '#f' | '#T' | '#F';
NUMBER: DIGIT+; // TODO: incomplete
CHAR: '#\\' CHARNAME | '#\\x' HEXDIGIT+ | '#\\' . ;
STRING: '"' STRELEMENT* '"';
IDENTIFIER: INITIAL SUBSEQUENT* | PERCULIAR_ID;

COMMENT: (';' .*? LINE_ENDING | '#!r6rs' ) -> skip;
NESTED_COMMENT: '#|' (NESTED_COMMENT | ~[#|] | ('|' ~'#') | ('#' ~'|') )* '|#' -> skip;

datum: lexemeDatum
     | compoundDatum;
compoundDatum: list
             | vector
             | bytevector;

// (rest omitted...)

では、 のように書きたいと思いskipDatum: '#;' datum -> skipます。残念ながら、パーサー ルールでは許可されていません->skipSKIPDATUM: '#;' datum -> skipレクサー規則はパーサー規則を参照できないため、どちらも機能しません。

私の意見では、「コメントアウト」はレクサーの責任であり、「データムの構築」はパーサーの責任ですが、ルールに関するルールには#;両方が必要です。

これが私の現在の解決策です:

skipDatum: '#;' datum;

list: '(' (datum|skipDatum)* ')' #ProperListDatum
    | '[' (datum|skipDatum)* ']' #ProperListDatum
    | '(' skipDatum* datum (datum|skipDatum)* '.' skipDatum* datum skipDatum* ')' #ImproperListDatum
    | '[' skipDatum* datum (datum|skipDatum)* '.' skipDatum* datum skipDatum* ']' #ImproperListDatum

それが機能している間、それはとても醜いようです。を使用してルールを書きたい場合datumは、常に次のように書く必要があります。skipDatum* datum skipDatum*

より良い解決策はありますか?前もって感謝します。

4

1 に答える 1

0

このようなものを使用できます。

datum
    :   SKIP_DATUM? ...
    ;

SKIP_DATUM : '#;';

DatumContextこれにより、文法を簡素化しながら、生成されたコードでa を使用するたびに次のチェックを実行する必要があります。

if (ctx.SKIP_DATUM() != null) {
    // handle skipped datum here (return?)
}
于 2013-04-23T13:16:00.837 に答える