JavaCC换行符可能会导致解析问题

时间:2018-02-02 22:08:50

标签: java javacc

我的语法如下:

PARSER_BEGIN(Parser)
    package parser;
    public class Parser {}
PARSER_END(Parser)

SKIP: {
    " "
    |    "\t"
    |    "\n"
    |    "\r"
    |    "\f"
}

TOKEN : {
    <MIX: "mix">
    |    <WITH: "with">
    |    <FUNCTION: "function">
    |    <MANIFEST: "manifest">
    |    <REPEAT: "repeat">
    |    <NAT: "nat">
    |    <REAL: "real">
    |    <MAT: "mat">
    |    <FOR: "for">
    |    <INSTRUCTIONS: "instructions">
}

TOKEN : {
    <LPAREN: "(">
    |    <RPAREN: ")">
    |    <LBRACE: "{">
    |    <RBRACE: "}">
    |    <COLON: ":">
    |    <ASSIGN: "=">
}

// Include the necessary <INTEGER_LITERAL> included in most examples

TOKEN : {
    <IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)*>
    // Letter and Digit are the unicode values.
}

void Program() :
{}
{
    ( Manifest() )*
    <INSTRUCTIONS>
    Statement()
    <EOF>
}

void Manifest() :
{}
{
    <MANIFEST> (Type())? PrimaryExpression()
}

void Statement() :
{}
{
    Instruction()
    |    Function()
}

void Instruction() :
{}
{
    (TypingList())* Identifier() <ASSIGN> Expression()
}

void TypingList() :
{}
{
    Type() ( TypingRest() )*
}

void TypingRest() :
{}
{
    <COMMA> Type()
}

void Type() :
{}
{
    <MAT>
    |    <NAT>
    |    <REAL>
}

void Function() :
{}
{
    <FUNCTION> Identifier() <LPAREN> (FormalParameterList())* <RPAREN> (<COLON> TypingList())? <LBRACE>
        Statement()
    <RBRACE>
}

void FormalParemeterList() :
{}
{
    FormalParameter() (FormalParameterRest() )*
}

void FormalParameter() :
{}
{
    (TypingList())* Identifier()
}

void FormalParameterRest() :
{}
{
    <COMMA> FormalParameter()
}

void Instruction() :
{}
{
    (TypingList())* Identifier() <ASSIGN> Expression()
}

void Identifier() :
{}
{
    <IDENTIFIER>
}

void Expression() :
{}
{
    <MIX> Identifier() <WITH> Identifier() <FOR> <INTEGER_LITERAL>
}

这应该使我能够解析一个简单的程序,例如:

manifest itemOne
manifest itemTwo

instructions

function doThis(argument) : nat {
    temp = mix one with two for 3
}

two = mix item3 with item4

然而,当JavaCC在函数temp = mix...中看到doThis语句时,它声明它找到了一个标识符,但是期待其他任何东西: Exception in thread "main" parser.ParseException: Encountered " <IDENTIFIER> "temp "" at line x, column y. Was expecting one of: "for" ... "}" ...

但是,正如您所看到的,我的语法表明您可以使用标识符为其分配mix的值。但错误是说这是无效或不正确的。我尝试了几种变体,但似乎没有任何效果。

1 个答案:

答案 0 :(得分:2)

问题在于您告诉JavaCC只有一个Instruction() | BranchStatement()|WhileStatement()|Function()。因此,一旦解析器访问其中一个状态,就不能再在那里重新访问。

为了解决这个问题,请将Kleene Closure +放在Statement()转换周围,例如:

void Statement() :
{}
{
    (
    Instruction()
    |    BranchStatement()
    |    WhileStatement()
    |    Function()
    )+
}

+运算符告诉自动机必须至少访问此状态一次,但可以重复。