1

私は QuickBasic のパーサーを作成しようとしていますが、これはコメントを取得するための私の試みです:

grammar QuickBasic;

options 
{
    language = 'CSharp2';
    output = AST;
}

tokens
{
    COMMENT;
}

parse
    :    .* EOF
    ;

// DOESN'T WORK
Comment
    :    R E M t=~('\n')* { Text = $t; } -> ^(COMMENT $t)
    |    Quote t=~('\n')* { Text = $t; } -> ^(COMMENT $t)
    ;

Space  
    :    (' ' | '\t' | '\r' | '\n' | '\u000C') { Skip(); }  
    ;

fragment Quote : '\'';    
fragment E     : 'E' | 'e';
fragment M     : 'M' | 'm';
fragment R     : 'R' | 'r';

トークン COMMENT だけを使用して書き直しても、同じエラーが発生します。

// It DOESN'T WORK EITHER
Comment
    :    (R E M | Quote) ~('\n')* -> ^(COMMENT)
    ;

書き直しをあきらめると、うまくいきます:

// THIS WORKS
Comment
    :    (R E M | Quote) ~('\n')*
    ;
4

1 に答える 1

3

書き換えルールはパーサー ルールでのみ機能し、レクサー ルールでは機能しません。そしてt=~('\n')*、最後の非改行のみがt-label に格納されるため、とにかく機能しませんでした。

Commentしかし、これらのトークンをまとめてスキップしないでください。それらをトークン ストリームに残しておくとComment、すべてのパーサー ルール (Commentトークンが発生しても有効な場合)でトークンを考慮する必要があります。

をスキップするにSkip()は、ルールの最後で次のように呼び出します。

Comment
    :    R E M ~('\r' | '\n')* { Skip(); }
    |    Quote ~('\r' | '\n')* { Skip(); }
    ;

またはより簡潔に:

Comment
    :    (Quote | R E M) ~('\r' | '\n')* { Skip(); }
    ;

Commentただし、トークンをストリームに残しておきたい場合"rem"や、コメントからの引用を削除したい場合は、次のようにします。

Comment
    :    (Quote | R E M) t=NonLineBreaks { Text = $t.text; }
    ;

fragment NonLineBreaks : ~('\r' | '\n')+;

次に、ルートとしてを使用して AST を作成するパーサー ルールを作成することもできますCOMMENT(ただし、単純に を使用するよりも利点はありませんComment)。

comment
    :    Comment -> ^(COMMENT Comment)
    ;
于 2012-06-01T12:26:43.617 に答える