2015-02-24 87 views
1

我想通過javaCC解析文本文件。該文件由多個句子組成,用換行符分隔。每行可以包含任何「a」和「b」序列,但應該在換行符之前以「a」結尾,之後是「b」。 JavaCC不會解析相同的消息並將終端令牌a和b作爲可選系列的一部分。javaCC解析限制

這應當成功的JavaCC解析:

aa ab aab 
aab 

的JJT文件如下:

options { 
STATIC = false ; 
FORCE_LA_CHECK = true; 
LOOKAHEAD = 20000; 
DEBUG_PARSER = true; 
DEBUG_LOOKAHEAD = true; 
OTHER_AMBIGUITY_CHECK = 3; 
} 

PARSER_BEGIN(Test) 
class Test { 
public static void main(String[] args) 
throws ParseException { 
    Test act = new Test (System.in); 
    SimpleNode root = act.Start() ; 
    root.dump (" "); 
    //ystem.out.println("Total = "+val); 
} 
}PARSER_END(Test) 

TOKEN_MGR_DECLS : 
{ 
    int stringSize; 
} 

SKIP : { < WS : " " > } 
SKIP : {"\t" | "\r" | "\uFFFF" | "\u201a" | "\u00c4" | "\u00ee" | "\u00fa" | "\u00f9" | "\u00ec" | "\u2013" } 

TOKEN [IGNORE_CASE] : 
{ 
    < A : "a" > 
| < B : "b" > 
| < NEWLINE : (("\n")+) > 
} 


SimpleNode Start() throws NumberFormatException : 
{ 
    int i ; 
    int value=0 ; 
} { 
chapter() 
{ 
    return jjtThis; } 
} 

void chapter() : 
{ } { 
    (LOOKAHEAD (part_sentence()) part_sentence())+ (newline())? <EOF> 
} 
void part_sentence() : 
{ } { 
    <NEWLINE> (a() | b())+ a() b() 
} 
void a() : 
{ } { 
    <A> 
} 
void b() : 
{ } { 
    <B> 
} 
void newline() throws NumberFormatException : 
{ }{ 
    <NEWLINE> 
    { System.out.print ("N# "); } 
} 

它可以被澄清,非端子a()和b()不能用代幣代替;爲了簡單起見,它們被認爲是「a」和「b」。另外,由於其他限制,「NEWLINE」不能移動到非終端「part_sentence」的末尾。

我被困在這個問題從過去的4天。我最後的希望是語義解析--LOOKAHEAD({!(getToken(1).kind == a()& & getToken(2).kind == b()& & getToken(3).kind == newline()} ),但不能得到非終端的句柄!任何幫助將不勝感激

回答

0

[注意:你說a和b的任何序列以「ab」結尾,但您的代碼使用+而不是*。我會假設你確實是指任何以「ab」結尾的序列,包括「ab」序列。尾註。]

你需要在展望的基礎上退出循環。想要做的是這個

(LOOKAHEAD(x) 
    (a() | b()) 
)* 
a() b() <NEWLINE> 

其中x表示如果下一項輸入不匹配a() b() <NEWLINE>。不幸的是,沒有辦法使用句法預測來說「不匹配」。訣竅是用遞歸替換循環。

void oneLine() : {} { 
    LOOKAHEAD(a() b() <NEWLINE>) 
    a() b() <NEWLINE> 
| 
    a() oneLine() 
| 
    b() oneLine() 
} 

你說你想要<NEWLINE>在生產開始。出於常見問題中解釋的原因,我不喜歡使用超出手頭選擇範圍的語法預測。但是可以做到以下幾點。

void oneLine() : {} { <NEWLINE> oneLinePrime() } 

void oneLinePrime() : {} { 
    LOOKAHEAD(a() b() <NEWLINE>) 
    a() b() 
| 
    a() oneLinePrime() 
| 
    b() oneLinePrime() 
} 
+0

西奧多,我留下了深刻的印象,看到你的答案的深度以及你可能會寫的同樣的痛苦。你已經回答了我的問題。將嘗試在我的相對複雜的語法中實現這一點,並更新結果。謝謝(順便說一句,這是我第一次在stackoverflow(或任何其他網站)關於此事的每一篇文章 – 2015-02-26 14:12:30

+0

歡迎來到StackOverflow。 – 2015-02-26 20:04:18