【问题标题】:javaCC Parsing LimitationjavaCC解析限制
【发布时间】:2015-02-24 14:26:56
【问题描述】:

我正在尝试通过 javaCC 解析文本文件。该文件由多个句子组成,以换行符分隔。每行可以包含“a”和“b”的任何序列,但应以“a”结尾,然后在换行符之前的“b”。 JavaCC 不解析相同的内容,并将终端标记 a 和 b 作为可选系列的一部分使用。

这应该被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()}) 但是无法处理非终端!任何帮助将不胜感激。

【问题讨论】:

    标签: parser-generator javacc negative-lookahead


    【解决方案1】:

    [注意:您说的是任何以“ab”结尾的 a 和 b 序列,但您的代码使用 + 而不是 *。我将假设您确实指的是任何以“ab”结尾的序列,包括“ab”的序列。结束注。]

    需要在前瞻的基础上退出循环。你想做的就是这个

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

    x 表示下一个输入项是否不匹配 a() b() &lt;NEWLINE&gt;。不幸的是,没有办法使用语法向前说“不匹配”。诀窍是用递归替换循环。

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

    您说您想要在制作开始时使用&lt;NEWLINE&gt;。出于常见问题解答中解释的原因,我不喜欢使用超出手头选择的语法前瞻性。但可以做到以下几点。

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

    【讨论】:

    • 西奥多,看到您的回答的深度以及您为编写同样的内容可能付出的痛苦,我印象深刻。你已经回答了我的问题。将尝试在我相对复杂的语法中实现相同的功能并更新结果。谢谢(顺便说一句;这是我在 stackoverflow 上的第一篇文章(或任何其他网站)
    • 欢迎来到 StackOverflow。
    猜你喜欢
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多