1

パーサーで次のルールを検討してください。

expression 
    :   IDENTIFIER
    |   (...)
    |   procedure_call // e.g. (foo 1 2 3)
    |   macro_use   // e.g. (xyz (some datum))
    ;

procedure_call
    :   '(' expression expression* ')'
    ;

macro_use
    :   '(' IDENTIFIER datum* ')'
    ;

// Note that any string that parses as an <expression> will also parse as a <datum>.
datum 
    : simple_datum 
    | compound_datum
    ;

simple_datum 
    :   BOOLEAN
    |   NUMBER
    |   CHARACTER
    |   STRING
    |   IDENTIFIER
    ;

compound_datum 
    : list 
    | vector
    ;

list 
    :   '(' (datum+ ( '.' datum)?)? ')'
    |   ABBREV_PREFIX datum
    ;

fragment ABBREV_PREFIX
    :   ('\''   | '`' | ',' | ',@')
    ;

vector 
    : '#(' datum* ')'
    ; 

式ルールの procedure_call と macro_rule の代替は、非 LL(*) 構造エラーを生成します。(IDENTIFIER)両方として解析されるので、私は問題を見ることができます。ただし、* の代わりに + を使用して両方を定義しても、上記の例はもう解析されていないにもかかわらず、エラーが発生します。
構文述語の使用法を思いつきましたが、ここでトリックを行うためにそれらを使用する方法がわかりません。
何かのようなもの

expression 
    :   IDENTIFIER 
    |   (...)
    |   (procedure_call)=>procedure_call // e.g. (foo 1 2 3)
    |   macro_use   // e.g. (xyz (some datum))
    ; 

また

expression 
    :   IDENTIFIER
    |   (...)
    |   ('(' IDENTIFIER expression)=>procedure_call // e.g. (foo 1 2 3)
    |   macro_use   // e.g. (xyz (some datum))
    ;

最初のルール以外は何にも一致しないため、どちらも機能しません。それを解決する適切な方法はありますか?

4

1 に答える 1