我正在编写一个JavaCC解析器/词法分析器,用于识别以下语言 L 中的所有输入字符串:
L 中的字符串由多个以空格字符分隔的块组成 必须至少存在一个块(即,不允许仅包含一定数量的空格的输入)。
I / O规范包括以下规范:
如果输入确实表示来自 L 的字符串,则必须将单词YES
打印到System.out,以EOL字符结尾。
如果输入不在 L 中,则只有一行带有单词NO 打印到System.out,也以EOL字符结尾 此外,应在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;
}
}
我遇到的问题如下:
我正在尝试编写代码以确保:
NO Empty input
。NO
。此刻,当我输入字符串"jjj jjj jjj"
时,根据定义,该字符串位于 L 中(我使用回车符和EOF [CTRL + D]进行此操作) ),打印出文本NO Empty input
。
我没想到会发生这种情况。
为了解决这个问题,我在我的作品中写了...TRUE
和...FALSE
印刷语句(参见上面的代码)。
有趣的是,我发现当我输入相同的j
字符串时,终端打印出...TRUE
语句一次,紧接着出现两次...FALSE
语句。
然后像以前一样打印出文本NO Empty input
。
我还使用Google尝试查看我是否错误地在制作|
中使用了OR符号Input()
,或者我是否正确使用了return
关键字,无论是。但是,这没有帮助。
我是否可以提示来解决此问题?
答案 0 :(得分:2)
当输入为jjj jjj jjj
后跟换行符或回车符(但不是两者)时,您的main
方法会调用Parser.Input
三次。
true
。false
。输入消耗后,词法分析器将继续返回<EOF>
个令牌。
答案 1 :(得分:2)
您正在调用Input
方法三次。它第一次从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");
}