2012-07-13 1 views
0

SML 메시지 용 구문 분석기를 쓰고 있습니다. 입력 : 많은 SML 메시지가있는 파일. Ouput : 식별 된 요소가있는 메시지 큐. 'ANTLR 입력이 문법과 일치하지만 프로그램에서 인식 할 수 없습니다.

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 ':'** 

내가 왜 내 프로그램이 할 수있는 모르는이 내 코드입니다 :

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. 

그리고 그 결과는 유형 실현 : 'L'?? 나는 TYPE'U4 '로 해봤 다.

답변

0

질문에 대한 답변을 제공하기에는 너무 많은 일이 잘못되어 있습니다. 질문에 답을 얻더라도 문법에 너무 많은 오류가 포함되어있어 도움이되지 않습니다. 나는 이것을 버리고 다시 시작하는 것이 좋습니다. 그러나 처음부터 다시 시작하기 전에 ANTLR tutorials 두 개를 읽거나 The Definitive ANTLR Reference 사본을 보유하십시오.

문제 중 일부는 :

  • 당신은 파서와 렉서 규칙의 차이를 알고하지 못하는 것 같습니다. 파서 규칙 중 일부는 렉서 규칙이어야하며 렉서 규칙 중 일부는 실제로 파서 규칙이어야합니다.
  • 파서 규칙 내에서 조각 규칙을 사용합니다. 조각 규칙이 결코 토큰 자체로 변환되지 않으므로 결코 작동하지 않습니다. 조각 규칙은 렉서 규칙 (또는 다른 조각 규칙)에서만 사용할 수 있습니다.
  • 파서에서 (정적 인) 렉서 변수를 설정하고 있습니다. 이렇게 할 수 없습니다! 파서 버퍼 자체가 토큰을 사용하면 논리가 끔찍하게 잘못 될 수 있습니다. 렉서와 파서 사이에는 엄격한 구분이 있습니다. 렉서는 파서의 간섭없이 토큰을 단순히 생성합니다! 렉싱은 별도의 과정입니다. 원하신다면 ANTLR 이외의 것을 선택하십시오 ("스캐너리스 파싱", "PEG"및/또는 "팩트"). 이 문제는 대부분 '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를 계속하기 전에 기본 사항을 숙지해야합니다.

행운을 빈다.