0

SMLメッセージのパーサーを書いています。入力:多くのSMLメッセージを含むファイル。Ouput:識別された要素を持つメッセージのキュー。これは私のコードです:

grammar SML;
options {language = Java;}
@header {
  package SECSParser;
 import SECSParser.SMLLexer;
}

@lexer::header {
  package SECSParser;
}

@parser::members {
  public static void main(String[] args) throws Exception {
    String file = "C:\\Messages.sml";
    SMLLexer lexer = new SMLLexer(new ANTLRFileStream(file));
    SMLParser parser = new SMLParser(new CommonTokenStream(lexer));
    parser.program();
  }
}

@lexer::members {
  public static String place = "end";
  public static void setPlace(String text) { SMLLexer.place = text; }
  public static String getPlace() {return SMLLexer.place;}
  public static boolean placeIsType() {
    return (SMLLexer.place.equals("wb")
    | SMLLexer.place.equals("value")
    | SMLLexer.place.equals("type"));
  }
  public static boolean placeIsStreamFunction() {
    return (SMLLexer.place.equals("sf") | SMLLexer.place.equals("name"));
  }
  public static boolean placeIsWaitBit() {
    return (SMLLexer.place.equals("sf") | SMLLexer.place.equals("wb"));
  }
  public boolean ahead() {
    if ((input.LA(-2) == 'S') || (input.LA(-2) == 's')) {
      return false;
    }
    return true;
  }
}

program:(message)* EOF;
message:{System.out.println("MESSAGE     : \n");}
  {SMLLexer.setPlace("name");}
  name ws* ':' ws* {SMLLexer.setPlace("sf");} str_func 
  (ws+ {SMLLexer.setPlace("wb");} waitbit)? (ws+ item)? '.' 
   ws* {SMLLexer.setPlace("end");};

name:LETTER(LETTER| NUMBER| '_')* {System.out.println("NAME     : " + $text + "\n");};
fragment STR:~('\'' | '\"');
NUMBER:'0'..'9';
LETTER:(('A'..'Z') | ('a'..'z'));
str_func: (('S' | 's') stream ('F' | 'f') function);
stream: NUMBER+ {System.out.println("STREAM     : " + $text + "\n");};
function: NUMBER+ {System.out.println("FUNCTION     : " + $text + "\n");};
waitbit: {SMLLexer.placeIsWaitBit()}?=>('W' | 'w') {
  System.out.println("WAITBIT     : " + $text + "\n");
};
item:{System.out.println("ITEM     : \n");} ws* SITEM ws* {SMLLexer.setPlace("type");}
  TYPE ( (ws* '[' number_item ']')? ws+ {SMLLexer.setPlace("value");}value)? 
  ws* EITEM ws* COMMENT? ws*;
SITEM: '<' {SMLLexer.setPlace("type");};
EITEM: '>';
TYPE:{SMLLexer.placeIsType()}?=>( 'A' | 'a' | 'L'| 'l'| 'BINARY'| 'binary'| 'BOOLEAN'| 'boolean'| 'JIS'| 'jis'| 'I8'| 'i8' | 'I1'| 'i1'| 'I2'| 'i2' | 'I4'| 'i4'| 'F4'| 'f4'| 'F8'| 'f8'| 'U8'| 'u8' | 'U1'| 'u1'| 'U2' | 'u2'| 'U4'| 'u4' ){System.out.println("TYPE     : " + $text + "\n");};
number_item: NUMBER+ {System.out.println("NUMBER ITEM     : " + $text + "\n");};
value:(item ws*)+| (string ws*)+| ((LETTER| NUMBER)ws*)+;
COMMENT:('/*' (options {greedy=false;}: .)* '*/') {$channel = HIDDEN;};
string:('\'' STR? '\'')| ('\"' STR? '\"') {System.out.println("VALUE     : " + $text + "\n");};
ANY:.;
ws:(' '| '\t'| '\r'| '\n'| '\f');

これは私のファイル「Message.sml」です

Are_You_There1l : S1F4 W.
On_Line_Data:S1F4 W
<L[2]
    <U4 13>
    <U4 7>
>.
W1Are_You_There: S1F4 W.

そして結果は次のとおりです。

MESSAGE     : 
NAME     : Are_You_There1l
STREAM     : 1
FUNCTION     : 4
WAITBIT     : W
MESSAGE     : 
NAME     : On_Line_Data
STREAM     : 1
FUNCTION     : 4
WAITBIT     : W
ITEM     : 
MESSAGE     : 
NAME     : L
TYPE     : U4
TYPE     : U4
MESSAGE     : 
NAME     : Are_You_There
STREAM     : 1
FUNCTION     : 4
WAITBIT     : W

**C:\Messages.sml line 4:1 mismatched input 'L' expecting TYPE
C:\Messages.sml line 4:2 mismatched input '[' expecting ':'**

プログラムがTYPE:'L'を認識できない理由がわかりません。TYPE'U4'で試してみましたが、動作します。

4

1 に答える 1

0

あなたの質問に答えることができないほど多くの問題があります。たとえあなたの質問が答えられたとしても、文法にはあまりにも多くのエラーが含まれているので、それは何の助けにもなりません。これを捨てて最初からやり直すことをお勧めします。ただし、最初からやり直す前に、いくつかのANTLRチュートリアルを読むか、 The DefinitiveANTLRReferenceのコピーを入手してください。

いくつかの問題:

  • パーサールールとレクサールールの違いを知らないようです。パーサールールの一部はレクサールールである必要があり、レクサールールの一部は実際にはパーサールールである必要があります。
  • パーサールール内でフラグメントルールを使用します。フラグメントルール自体がトークンに変わることはないため、これは機能しません。フラグメントルールは、レクサールール(または他のフラグメントルール)でのみ使用できます。
  • パーサーから(静的)レクサー変数を設定しています:これはできません!パーサーはそれ自体でトークンをバッファリングするため、ロジックがひどく間違ってしまいます。レクサーとパーサーの間には厳密な分離があります。レクサーは、パーサーからの干渉なしにトークンを生成するだけです。字句解析は別のプロセスです。それが必要な場合は、ANTLR(「スキャナーレス解析」、「PEG」、「packrat」のGoogle)以外のものを選択してください。この問題はおそらく、特定のケースで'L'トークン化されていない理由です。TYPE
  • のようなリテラルトークンを使用していますが、レクサールールとして('W' | 'w')も使用しています。LETTERただし、単一'w'または'W'は、以降としてトークン化されることはありませんLETTER。パーサールール内でリテラルトークンを定義することは、次のようにすることとほぼ同じです。

    W : 'w' | 'W';
    LETTER : 'a'..'z' | 'A'..'Z'; // this will never match a 'w' or 'W' now!

    これは、ANTLRのレクサーがパーサーから独立して動作するという事実とも関係があります。

繰り返しますが、IMOを続行する前に、基本をマスターする必要があります。

頑張ってください!

于 2012-07-13T16:02:48.907 に答える