7

単純なパーサー ジェネレーターを作成するタスクがあるため、ANTLR のような文法を作成し、「foo:bar;」のような単純なファイルを解析しようとしましたが、次の出力が得られました。

[@0,0:2='foo',<1>,1:0]
[@1,3:3=':',<16>,1:3]
[@2,4:6='bar',<1>,1:4]
[@3,7:7=';',<18>,1:7]
[@4,8:7='<EOF>',<-1>,1:8]
line 1:0 no viable alternative at input 'foo'
(rule foo : bar ;)

私の文法は次のようになります

grammar parsGen;

gram : rule SEMICOLON (NEWLINE+ rule SEMICOLON)* ;

rule : lRule | pRule ;

lRule : LRULEID COLON lRule1 ;
lRule1 : (((LRULEID | STRING | SET) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE+)+ ;

pRule : PRULEID COLON pRule1 ;
pRule1 : (((LRULEID | PRULEID) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE+)+ ;

modificator : PLUS | ASTERISK | QUESTION ;

ID : LRULEID | PRULEID ;

LRULEID : UPPERLETTER (UPPERLETTER | LOWERLETTER | DIGIT)* ;
PRULEID : LOWERLETTER (UPPERLETTER | LOWERLETTER | DIGIT)* ;

STRING : ('\''.*?'\'') ;
SET : '\''.*?'\'..\''.*?'\'' ;

UPPERLETTER : [A-Z] ;
LOWERLETTER : [a-z] ;
DIGIT : [0-9] ;

NEWLINE : '\r\n'|'\n'|'\r' ;

PLUS : '+' ;
ASTERISK : '*' ;
QUESTION : '?' ;

LBRACE : '(' ;
RBRACE : ')' ;

SPACE : ' ' ;

COLON : ':' ;

PIPE : '|' ;

SEMICOLON : ';' ;

では、どこで間違いを犯すことができますか?どこでも(Google、SOなど)検索しようとしましたが、「実行可能な代替手段はありません」というエラーが表示されましたが、実際には役に立ちませんでした。

4

2 に答える 2

19

ANTLR レクサーは、パーサーが使用される前に、明確なトークン タイプを完全に割り当てます。複数のトークン タイプが 1 つのトークンに一致する場合、文法に最初に現れるタイプが使用されます。あなたの文法では、トークンは型IDと型LRULEIDを同時に持つことはできません。入力fooはこれらのレクサー ルールの両方に一致するため、文法で最初に出現するものが使用され、トークンはIDCOLONIDSEMICOLONです<EOF>

IDトークンはパーサーで実際に参照されることはないため、次のいずれかの変更を提案します。これらのオプションのいずれかで、説明した問題が解決されるため、最終的な文法がどのように見えるかは、完全に好みの問題です。

序文

SPACE+スペース参照を からに変更する必要があります。変更しSPACE*ないと、ルールで との間に少なくとも 1 つのスペース文字が必要barになり;ます。

オプション1

IDレクサー規則を完全に削除します。

オプション 2

  1. パーサー ルールを変更して、すべての識別子IDにトークン タイプを割り当てようとしないようにします。ID

    id : LRULEID | PRULEID;
    
  2. pRule1を参照してルールを更新しますid

    pRule1 : ((id | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE+)+ ;
    

無関係な補足事項

andルール+内の最も外側のクロージャを削除し、代わりに、次のようにルール参照自体に追加すると、文法が読みやすくなる場合があります。前書きで説明したように、参照を変更したことに注意してください。lRulepRule1SPACE

lRule : LRULEID COLON lRule1+ ;
lRule1 : ((LRULEID | STRING | SET) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE* ;

pRule : PRULEID COLON pRule1+ ;
pRule1 : ((LRULEID | PRULEID) | LBRACE lRule1 PIPE lRule1 RBRACE) modificator? SPACE* ;
于 2013-05-31T14:36:47.437 に答える