2014-05-01 98 views
0

我正在爲Clasp的輸出寫入解析器ANTLR 4。典型的輸出是這樣的:使用INT和FLOAT進行意外的ANTLR4優化?

clasp version 3.0.3 
Reading from stdin 
Solving... 
Answer: 1 
bird(a) bird(b) bird(c) penguin(d) bird(d) 
Optimization: 7 0 
Answer: 2 
bird(a) bird(b) bird(c) penguin(d) bird(d) flies_abd(b) flies(b) 
Optimization: 6 5 
Answer: 3 
bird(a) bird(b) bird(c) penguin(d) bird(d) flies_abd(c) flies(c) 
Optimization: 2 5 
Answer: 4 
bird(a) bird(b) bird(c) penguin(d) bird(d) flies_abd(a) flies_abd(c) flies(a) flies(c) 
Optimization: 1 10 
Answer: 5 
bird(a) bird(b) bird(c) penguin(d) bird(d) flies_abd(a) flies_abd(b) flies_abd(c) flies(a) flies(b) flies(c) 
Optimization: 0 15 
OPTIMUM FOUND 

Models  : 5  
    Optimum : yes 
Optimization : 0 15 
Calls  : 1 
Time   : 0.002s (Solving: 0.00s 1st Model: 0.00s Unsat: 0.00s) 
CPU Time  : 0.000s 

我必須檢查clasp是版本3所以我寫類似以下的語法:

/** 
* Define a grammar for Clasp 3's output. 
*/ 
grammar Output; 

@header {package ac.bristol.clasp.parser;} 

output: 
    version source solving answer* result separation statistics NEWLINE* EOF; 

version: 'clasp version 3.' INT '.' INT NEWLINE; 

source: 'Reading from stdin' NEWLINE # sourceSTDIN 
    | 'Reading from ' path NEWLINE # sourceFile; 

path: 
    DRIVE? folder (BSLASH folder)* filename # pathWindows 
    | FSLASH? folder (FSLASH folder)* filename # pathNIX; 

folder: 
    LETTER+ # genericFolder 
    | DOTDOT # parentFolder 
    | DOT # currentFolder; 

solving: 'Solving...' NEWLINE; 

filename: 
    LETTER+ extension?; 

extension: 
    DOT LETTER*; 

answer: 'Answer: ' INT NEWLINE // 
    model? NEWLINE // 
    'Optimization: ' INT (SPACE INT)* NEWLINE; 

model: 
    fact (SPACE fact)*; 

fact: 
    groundPredicate; 

groundTermList: 
    groundTerm (COMMA groundTerm)*; 

groundTerm: 
    groundCompound | STRING | number | atom; // literal? 

groundCompound: 
    groundPredicate 
    | groundExpression; 

groundPredicate: 
    IDENTIFIER (LROUND groundTermList RROUND)?; 

groundExpression: 
    groundBits AND groundBits 
    | groundBits OR groundBits 
    | groundBits XOR groundBits; 

groundBits: 
    groundCompare GT groundCompare 
    | groundCompare GE groundCompare 
    | groundCompare LT groundCompare 
    | groundCompare LE groundCompare; 

groundCompare: 
    groundItem EQ groundItem 
    | groundItem NE groundItem; 

groundItem: 
    groundFactor PLUS groundFactor 
    | groundFactor MINUS groundFactor; 

groundFactor: 
    groundUnary TIMES groundUnary 
    | groundUnary DIVIDE groundUnary 
    | groundUnary MOD groundUnary; 

groundUnary: 
    TILDE groundTerm 
    | MINUS groundTerm; 

atom: 
    IDENTIFIER 
    | QUOTED; 

number: 
    INT 
    | FLOAT; 

//------------------------------------------------------------------------------ 

result: 'OPTIMUM FOUND' NEWLINE 
    | 'SATISFIABLE' NEWLINE 
    | 'UNKNOWN' NEWLINE; 

separation: 
    NEWLINE; 

statistics: 
    models optimum? optimization calls time cputime; 

models: 'Models  : ' INT SPACE* NEWLINE; 

optimum: ' Optimum : yes' NEWLINE 
    | ' Optimum : no' NEWLINE; 

optimization: 'Optimization : ' INT (SPACE INT)* NEWLINE; 
calls: 'Calls  : ' INT NEWLINE; 
time: 'Time   : ' FLOAT 's (Solving: ' FLOAT 's 1st Model: ' FLOAT 's Unsat: ' FLOAT 's)' NEWLINE; 
cputime: 'CPU Time  : ' FLOAT 's'; 

//------------------------------------------------------------------------------ 

AND:  '&'; 
BSLASH: '\\'; 
COLON:  ':'; 
COMMA:  ','; 
DIVIDE: '/'; 
DOT:  '.'; 
DOTDOT: '..'; 
EQ:  '=='; 
FSLASH: '/'; 
GE:  '>='; 
GT:  '>'; 
LE:  '<='; 
LROUND: '('; 
LT:  '<'; 
MINUS:  '-'; 
MOD:  '%'; 
NE:  '!='; 
OR:  '?'; 
PLUS:  '+'; 
RROUND: ')'; 
SEMICOLON: ';'; 
SPACE:  ' '; 
TILDE:  '~'; 
TIMES:  '*'; 
XOR:  '^'; 

DRIVE:  (LOWER | UPPER) COLON BSLASH?; 
IDENTIFIER: LOWER FOLLOW*; 
INT:  DIGIT+; 
FLOAT:  DIGIT+ DOT DIGIT+; 
NEWLINE: '\r'? '\n'; 
QUOTED:  '\'' (~[\'\\] | ESCAPE)+? '\''; 
STRING:  '"' (~["\\] | ESCAPE)+? '"'; 

fragment DIGIT:  [0] | NONZERO; 
fragment ESCAPE:  '\\' [btnr"\\] | '\\' [0-3]? [0-7]? [0-7] | '\\' 'u' [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F] [0-9a-fA-F]; 
fragment FOLLOW:  LOWER | UPPER | DIGIT | UNDERSCORE; 
fragment LETTER:  LOWER | UPPER | DIGIT | SPACE; 
fragment LOWER:  [a-z]; 
fragment NONZERO: [1-9]; 
fragment UNDERSCORE: [_]; 
fragment UPPER:  [A-Z]; 

注意,沒有規則skip一些部分輸入流,因爲我想檢查每一個字符。 另請注意,我有一個終止規則INT有史以來和FLOATINT是在FLOAT之前定義的,FLOAT s是如在Prolog中定義的。

來解析上述例子中的第一行的規則是以下內容:

version: 'clasp version 3.' INT '.' INT NEWLINE; 

,因爲它我要檢查正在使用的clasp主版本號是3,比我要消耗其餘該行讀取次要版本號,點號,內部版本號和換行符(不帶空格或任何內容)。 不幸的是,我得到以下警告消息,這讓我覺得ANTLR是認識次要版本號,點和內部版本號爲FLOAT

line 1:16 mismatched input '0.3' expecting INT 

能否請你解釋我是怎麼回事?
我假設我不應該這樣做嗎?
或者是ANTLR這是應用不需要的優化?

回答

0

ANTLR將您的輸入分解爲令牌,並且只有在解析出令牌後。在解析器規則中使用'clasp version 3.'會隱式定義與該文本字符串匹配的匿名標記。該令牌後面的文本以0.0開頭,後者與浮點數匹配。詞法分析器不知道解析器在那個時候會在version規則中;它只是從當前位置開始選擇最長的令牌,並且0.0作爲FLOAT0更長,作爲INT。我提出以下建議:

  1. 獨立你的語法爲parser grammar OutputParser;lexer grammar OutputLexer;在解析器語法,使用tokenVocab選項指明哪一個詞法分析器定義您的令牌。這種分離將迫使你爲語法所用的所有東西定義真正的標記。

    options { 
        tokenVocab = OutputLexer; 
    } 
    
  2. 或者使用的,而不是FLOATINT '.' INT,或創建一個新的標記來表示一個版本:

    VERSION 
        : DIGIT+ DOT DIGIT+ DOT DIGIT+ 
        ; 
    
+0

嗨山姆(@ 280Z28),感謝您的幫助的解釋!我的誤解可能是由於我正在考慮將解析器作爲基本的遞歸後裔解析器,並選擇了令牌接受的產品。無論如何,我認爲我會將'INT DOT INT'變成'FLOAT',作爲使警告消失的臨時解決方案(畢竟我沒有在其他地方使用這些數字),但我會研究如何區分語法分析器語法和詞法分析器語法,因爲學習新東西總是一件好事!非常感謝您的幫助! –