JavaCC 没有期望也没有发现

JavaCC expects nothing and found nothing

我试图找出解析器问题的根源,但首先,我想知道为什么会这样:

Encountered "" at line 1, column 1.
Was expecting one of:

这是导致问题的语法子集:

options {
  STATIC = false;
  DEBUG_PARSER = true;
  DEBUG_LOOKAHEAD = true;
  LOOKAHEAD = 64;
}

PARSER_BEGIN(MyParser)
package myparser;
public class MyParser {
}
PARSER_END(MyParser)

/* skip whitespace */
SKIP : {
  " "
  | "\t"
  | "\n"
  | "\r"
}

/* other symbols */
TOKEN : {
  < COMMA: "," >
| < SEMICOLON: ";" >
| < LEFT_PAREN: "(" >
| < RIGHT_PAREN: ")" >
| < LEFT_BRACKET: "[" >
| < RIGHT_BRACKET: "]" >
| < LEFT_BRACE: "{" >
| < RIGHT_BRACE: "}" >
}

/* type specifiers */
TOKEN : {
  < TYPE_SPECIFIER:
      "void"
    | "int"
    | "float"
  >
}

/* identifiers */
TOKEN [IGNORE_CASE] : {
  <IDENTIFIER: ["_","a"-"z"] (["_","a"-"z","0"-"9"])* >
}

SimpleNode Start() : {}
{
  /* begin here */
  Declaration()
  { return jjtThis; }
}

void Declaration() : {}
{
  FunctionPrototype() <SEMICOLON>
| InitDeclaratorList() <SEMICOLON>
}

void FunctionPrototype() : {}
{
  FunctionDeclarator() <RIGHT_PAREN>
}

void FunctionDeclarator() : {}
{
  FunctionHeaderWithParameters()
| FunctionHeader()
}

void FunctionHeaderWithParameters() : {}
{
/* recursive version:
  FunctionHeader() ParameterDeclaration()
  FunctionHeaderWithParameters() <COMMA> ParameterDeclaration()
*/
  FunctionHeader() ParameterDeclaration() [FunctionHeaderWithParametersPrime()]
}

void FunctionHeaderWithParametersPrime() : {}
{
  <COMMA> ParameterDeclaration() [FunctionHeaderWithParametersPrime()]
}

void FunctionHeader() : {}
{
  FullySpecifiedType() <IDENTIFIER> <LEFT_PAREN>
}

void FullySpecifiedType() : {}
{
  TypeSpecifier()
}

void TypeSpecifier() : {}
{
  TypeSpecifierNonArray() [ArraySpecifier()]
}

void ArraySpecifier() : {}
{
/* recursive version:
  <LEFT_BRACKET> <RIGHT_BRACKET>
| <LEFT_BRACKET> ConstantExpression() <RIGHT_BRACKET>
| ArraySpecifier() <LEFT_BRACKET> <RIGHT_BRACKET>
| ArraySpecifier() <LEFT_BRACKET> ConstantExpression() <RIGHT_BRACKET>
*/
  <LEFT_BRACKET> <RIGHT_BRACKET> [ArraySpecifierPrime()]
}

void ArraySpecifierPrime() : {}
{
  <LEFT_BRACKET> <RIGHT_BRACKET> [ArraySpecifierPrime()]
}

void TypeSpecifierNonArray() : {}
{
  <TYPE_SPECIFIER>
| TypeName()
}

void TypeName() : {}
{ /* user defined type e.g struct or typedef */
  <IDENTIFIER>
}

void ParameterDeclaration() : {}
{
  ParameterDeclarator()
| ParameterTypeSpecifier()
}

void ParameterTypeSpecifier() : {}
{
  TypeSpecifier()
}

void ParameterDeclarator() : {}
{
  TypeSpecifier() <IDENTIFIER>
| TypeSpecifier() <IDENTIFIER> ArraySpecifier()
}

void InitDeclaratorList() : {}
{
/* recursive version:
  SingleDeclaration()
| InitDeclaratorList() <COMMA> <IDENTIFIER>
| InitDeclaratorList() <COMMA> <IDENTIFIER> ArraySpecifier()
| InitDeclaratorList() <COMMA> <IDENTIFIER> ArraySpecifier() <EQUAL> Initializer()
| InitDeclaratorList() <COMMA> <IDENTIFIER> <EQUAL> Initializer()
*/
  SingleDeclaration() [InitDeclaratorListPrime()]
}

void InitDeclaratorListPrime() : {}
{
  <COMMA> <IDENTIFIER> [InitDeclaratorListPrime()]
| <COMMA> <IDENTIFIER> ArraySpecifier() [InitDeclaratorListPrime()]
}

void SingleDeclaration() : {}
{
  FullySpecifiedType()
| FullySpecifiedType() <IDENTIFIER>
| FullySpecifiedType() <IDENTIFIER> ArraySpecifier()
}

函数声明工作正常

void main(int a, int b);

但是在完整语法中进入函数体的声明语句不起作用

float myvar;

这个错误示例的解析器和前瞻的调试输出如下

Call:   Start
  Call:   Declaration
    Call:   FunctionPrototype(LOOKING AHEAD...)
      Call:   FunctionDeclarator(LOOKING AHEAD...)
        Call:   FunctionHeaderWithParameters(LOOKING AHEAD...)
          Call:   FunctionHeader(LOOKING AHEAD...)
            Call:   FullySpecifiedType(LOOKING AHEAD...)
              Call:   TypeSpecifier(LOOKING AHEAD...)
                Call:   TypeSpecifierNonArray(LOOKING AHEAD...)
                  Visited token: <<TYPE_SPECIFIER>: "float" at line 1 column 1>; Expected token: <<TYPE_SPECIFIER>>
                Return: TypeSpecifierNonArray(LOOKAHEAD SUCCEEDED)
                Call:   ArraySpecifier(LOOKING AHEAD...)
                  Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <"[">
                Return: ArraySpecifier(LOOKAHEAD FAILED)
              Return: TypeSpecifier(LOOKAHEAD SUCCEEDED)
            Return: FullySpecifiedType(LOOKAHEAD SUCCEEDED)
            Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <<IDENTIFIER>>
            Visited token: <";" at line 1 column 12>; Expected token: <"(">
          Return: FunctionHeader(LOOKAHEAD FAILED)
        Return: FunctionHeaderWithParameters(LOOKAHEAD FAILED)
        Call:   FunctionHeader(LOOKING AHEAD...)
          Call:   FullySpecifiedType(LOOKING AHEAD...)
            Call:   TypeSpecifier(LOOKING AHEAD...)
              Call:   TypeSpecifierNonArray(LOOKING AHEAD...)
                Visited token: <<TYPE_SPECIFIER>: "float" at line 1 column 1>; Expected token: <<TYPE_SPECIFIER>>
              Return: TypeSpecifierNonArray(LOOKAHEAD SUCCEEDED)
              Call:   ArraySpecifier(LOOKING AHEAD...)
                Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <"[">
              Return: ArraySpecifier(LOOKAHEAD FAILED)
            Return: TypeSpecifier(LOOKAHEAD SUCCEEDED)
          Return: FullySpecifiedType(LOOKAHEAD SUCCEEDED)
          Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <<IDENTIFIER>>
          Visited token: <";" at line 1 column 12>; Expected token: <"(">
        Return: FunctionHeader(LOOKAHEAD FAILED)
      Return: FunctionDeclarator(LOOKAHEAD FAILED)
    Return: FunctionPrototype(LOOKAHEAD FAILED)
    Call:   InitDeclaratorList(LOOKING AHEAD...)
      Call:   SingleDeclaration(LOOKING AHEAD...)
        Call:   FullySpecifiedType(LOOKING AHEAD...)
          Call:   TypeSpecifier(LOOKING AHEAD...)
            Call:   TypeSpecifierNonArray(LOOKING AHEAD...)
              Visited token: <<TYPE_SPECIFIER>: "float" at line 1 column 1>; Expected token: <<TYPE_SPECIFIER>>
            Return: TypeSpecifierNonArray(LOOKAHEAD SUCCEEDED)
            Call:   ArraySpecifier(LOOKING AHEAD...)
              Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <"[">
            Return: ArraySpecifier(LOOKAHEAD FAILED)
          Return: TypeSpecifier(LOOKAHEAD SUCCEEDED)
        Return: FullySpecifiedType(LOOKAHEAD SUCCEEDED)
      Return: SingleDeclaration(LOOKAHEAD SUCCEEDED)
      Call:   InitDeclaratorListPrime(LOOKING AHEAD...)
        Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <",">
        Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <",">
      Return: InitDeclaratorListPrime(LOOKAHEAD FAILED)
    Return: InitDeclaratorList(LOOKAHEAD SUCCEEDED)
    Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <";">
  Return: Declaration
Return: Start
Encountered "" at line 1, column 1.
Was expecting one of:

问题似乎出在 SingleDeclaration 生产中,它预期

  FullySpecifiedType()
| FullySpecifiedType() <IDENTIFIER>

其中 FullySpecifiedType 是类型常量 (void, int, float) 或另一个标识符(以方便用户定义类型)。

如果我交换这些行,它会显示

  FullySpecifiedType() <IDENTIFIER>
| FullySpecifiedType()

然后它按预期运行。为什么顺序会有所不同?

首先将 LOOAHEAD 选项设置为 1,这样 JavaCC 就会警告您前瞻冲突。

你的语法有先行冲突。 JavaCC 处理器应该将这些报告为警告。您应该注意这些警告。

默认情况下,JavaCC 使用输入的下一个标记来进行选择。有关详细信息,请参阅 documentation and the FAQ。拿

void SingleDeclaration() : {}
{
  FullySpecifiedType()
| FullySpecifiedType() <IDENTIFIER>
| FullySpecifiedType() <IDENTIFIER> ArraySpecifier()
}

举个例子。有一个三向选择。显然不能根据下一个令牌的种类来做出选择,因为任何可以启动第一个选择的令牌也可以启动第二个或第三个。

有两种方法可以解决这个问题。最好的,通常是重写语法。

void SingleDeclaration() : {}
{
  FullySpecifiedType()
  [
     <IDENTIFIER>
     [
        ArraySpecifier()
     ]
  ]
}

第二种是使用前瞻规范。

void SingleDeclaration() : {}
{   
  LOOKAHEAD(FullySpecifiedType() <IDENTIFIER> "[") 
  FullySpecifiedType() <IDENTIFIER> ArraySpecifier()
| 
  LOOKAHEAD(FullySpecifiedType() <IDENTIFIER>) 
  FullySpecifiedType() <IDENTIFIER>
|
  FullySpecifiedType()
}

还有一件事,你的开始制作应该是这样的:

SimpleNode Start() : {}
{
  /* begin here */
  Declaration() <EOF>
  { return jjtThis; }
}