Parsing 在JavaCC解析器/lexer代码中查找错误

Parsing 在JavaCC解析器/lexer代码中查找错误,parsing,compiler-construction,javacc,Parsing,Compiler Construction,Javacc,我正在编写一个JavaCC解析器/词法分析器,用于识别以下语言中的所有输入字符串: L中的字符串由几个由空格字符分隔的块组成。 必须至少存在一个块(即,不允许只包含一些空格的输入) 块是一个奇数长度的小写字母序列(A-z) 第一个块之前或最后一个块之后不允许有空格 块之间的空格数必须为奇数 I/O规范包括以下规范: 如果输入表示L中的字符串,则必须将单词YES打印到System.out,以下线字符结尾 如果输入不是L,则只有一行带有“无需”字样 要打印到System.out,也以下线字符结尾

我正在编写一个JavaCC解析器/词法分析器,用于识别以下语言中的所有输入字符串:

L中的字符串由几个由空格字符分隔的块组成。
必须至少存在一个块(即,不允许只包含一些空格的输入)

  • 块是一个奇数长度的小写字母序列(A-z)
  • 第一个块之前或最后一个块之后不允许有空格
  • 块之间的空格数必须为奇数
I/O规范包括以下规范:

如果输入表示L中的字符串,则必须将单词
YES
打印到System.out,以下线字符结尾

如果输入不是L,则只有一行带有“无需”字样 要打印到System.out,也以下线字符结尾。
此外,应在System.err上打印一条简短的错误消息,解释输入不在L中的原因

问题:

这是我当前的代码:

PARSER_BEGIN(Assignment)

  /** A parser which determines if user's input belongs to the langauge L. */
  public class Assignment {
    public static void main(String[] args) {
      try {
        Assignment parser = new Assignment(System.in);
        parser.Input();
        if(parser.Input()) {
          System.out.println("YES"); // If the user's input belongs to L, print YES.
        } else if(!(parser.Input())) {
          System.out.println("NO");
          System.out.println("Empty input");
        }
      } catch (ParseException e) {
        System.out.println("NO");  // If the user's input does not belong to L, print NO.       
      }
    }
  }

PARSER_END(Assignment)

//** A token which matches any lowercase letter from the English alphabet. */
TOKEN :
{
 < ID: (["a"-"z"]) >
}

//* A token which matches a single white space. */
TOKEN : 
{
  <WHITESPACE: " ">
}

/** This production is the basis for the construction of strings which belong to language L. */
boolean Input() :
{}
{
  <ID>(<ID><ID>)* ((<WHITESPACE>(<WHITESPACE><WHITESPACE>)*)<ID>(<ID><ID>)*)* ("\n"|"\r") <EOF>
  {      
    System.out.println("ABOUT TO RETURN TRUE");
    return true;    
  }

  |

  {    
    System.out.println("ABOUT TO RETURN FALSE");
    return false;
  }
}
PARSER\u开始(赋值)
/**确定用户输入是否属于语言的解析器*/
公共课堂作业{
公共静态void main(字符串[]args){
试一试{
赋值解析器=新赋值(System.in);
parser.Input();
if(parser.Input()){
System.out.println(“YES”);//如果用户的输入属于L,则打印YES。
}else if(!(parser.Input()){
系统输出打印项次(“否”);
System.out.println(“空输入”);
}
}捕获(解析异常){
System.out.println(“NO”);//如果用户的输入不属于L,则打印NO。
}
}
}
解析器_END(赋值)
//**与英语字母表中任何小写字母相匹配的标记*/
代币:
{

}
//*匹配单个空白的标记*/
代币:
{
}
/**这个结果是构造属于语言L的字符串的基础*/
布尔输入()
{}
{
()*((()*)()*)*(“\n”|“\r”)
{      
System.out.println(“即将返回TRUE”);
返回true;
}
|
{    
System.out.println(“即将返回FALSE”);
返回false;
}
}
我遇到的问题如下:

我正在尝试编写代码,以确保:

  • 如果用户输入为空,则将打印文本
    无空输入
  • 如果由于输入不符合上面L的描述而出现解析错误,则仅打印文本
    NO
此时,当我输入字符串“JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ。 我没想到会发生这种事

为了解决这个问题,我在我的作品中写了
…TRUE
…FALSE
打印语句(参见上面的代码)。 有趣的是,我发现当我输入相同的
j
s字符串时,终端会打印出
…TRUE
语句一次,紧接着出现两次
…FALSE
语句。
然后,像以前一样,打印出文本
无空输入

我还使用谷歌试图找出我是否在我的产品
Input()
中错误地使用了或符号
,或者我是否没有正确使用
return
关键字。然而,这并没有帮助


我能得到解决这个问题的提示吗?

当输入是
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj

  • 第一次,解析器使用所有输入并返回
    true
  • 第二次和第三次,所有输入都已被使用,解析器返回
    false

一旦输入被使用,lexer将继续返回
标记。

当输入是
jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj

  • 第一次,解析器使用所有输入并返回
    true
  • 第二次和第三次,所有输入都已被使用,解析器返回
    false

一旦输入被使用,lexer将继续返回
令牌。

您将调用
输入
方法三次。第一次从stdin读取,直到到达流的末尾。这将成功解析输入并返回true。另外两次,流将为空,因此它将失败并返回false

您不应该多次调用规则,除非您确实希望它被应用多次(只有当规则只使用部分输入而不是一直到流结束时才有意义)。相反,当您需要在多个位置获得结果时,只需调用该方法一次,并将结果存储在一个变量中

或者在您的情况下,您可以在
if
中调用它一次,甚至不需要变量:

Assignment parser = new Assignment(System.in);
if(parser.Input()) {
  System.out.println("YES"); // If the user's input belongs to L, print YES.
} else {
  System.out.println("NO");
  System.out.println("Empty input");
}

您正在调用
Input
方法三次。第一次从stdin读取,直到到达流的末尾。这将成功解析输入并返回true。另外两次,流将为空,因此它将失败并返回false

您不应该多次调用规则,除非您确实希望它被应用多次(只有当规则只使用部分输入而不是一直到流结束时才有意义)。相反,当您需要multip中的结果时