如何处理'扩展内“(...)*”可以匹配空字符串'?

时间:2016-04-05 15:58:07

标签: compiler-construction javacc formal-languages

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

L0
来自L0的字符串由几个由空格字符分隔的块组成。 必须至少存在一个块(即,不允许仅包含一定数量的空格的输入)。

  • 一个块是一个奇数长度的小写字母序列(a-z)。
  • 在第一个区块之前或最后一个区块之后不允许有空格。
  • 块之间的空格数必须为奇数。

L1
L1中的字符串由多个由空格字符分隔的块组成。 必须至少有一个街区。

  • 有两种块。必须是第一类的 偶数长度的大写字母序列value_vars。一块 第二种必须具有(A-Z)形状,其中<2U>. . .</2U>代表 来自L0的任何字符串。
  • 在第一个区块之前或最后一个区块之后不允许有空格。
  • 块之间的空格数必须为奇数。

到目前为止,这是我的代码:

. . .

问题: 我遇到的问题是,当我在PARSER_BEGIN(Assignment) /** A parser which determines if user's input belongs to L0 or L1. */ public class Assignment { public static void main(String[] args) { String returnString = null; boolean toPrintEmptyInput = false; try { Assignment parser = new Assignment(System.in); if(parser.Input()) { System.out.println("YES"); // If the user's input belongs to L0, print YES. } else { System.out.println("NO"); } } catch (ParseException e) { System.out.println("NO"); // If the user's input does not belong to L0, print NO. } } } PARSER_END(Assignment) //** A token which matches any lowercase letter from the English alphabet. */ TOKEN : { < IDLOWER: (["a"-"z"]) > } //* A token which matches any uppercase letter from the English alphabet. */ TOKEN: { < IDUPPER: (["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 L0. */ boolean Input() : {} { <IDLOWER>(<IDLOWER><IDLOWER>)* ((<WHITESPACE>(<WHITESPACE><WHITESPACE>)*)<IDLOWER>(<IDLOWER><IDLOWER>)*)* ("\n"|"\r") <EOF> { return true; } | { return false; } } /** This production is the basis for the construction of strings which belong to language L1. */ void Input2() : {} { Input() ((<WHITESPACE> Input())* (<WHITESPACE> (<IDUPPER><IDUPPER>)+)*)* ("\n"|"\r") <EOF> | (<IDUPPER><IDUPPER>)+ ((<WHITESPACE> (<IDUPPER><IDUPPER>)+)* (<WHITESPACE> Input())*)* ("\n"|"\r") <EOF> } 上运行javacc时,终端上会打印出以下内容:Assignment.jj我查看了以下链接,以便尝试为了更好地理解这个错误:

  • Link 1(我觉得这没有用)。
  • Link 2(我觉得这很有用)。

第二个链接建议修改扩展中的Expansion within "(. . .)*" can be matched by empty string.,使其无法与零匹配。但是,我仍在努力做到这一点,同时仍然有一个接受L1中的字符串的生产。

我希望提示更正

1 个答案:

答案 0 :(得分:2)

Input2()的规则中,(...)*中包含的模式位于:

((<WHITESPACE> Input())* (<WHITESPACE> (<IDUPPER><IDUPPER>)+)*)*

可以与空字符串匹配。

您可以将展开缩小为(A* B*)*格式,其中A<WHITESPACE> Input()B<WHITESPACE> (<IDUPPER><IDUPPER>)+A* B*可以匹配空字符串,无论AB是什么。

如果封闭的表达式可以匹配空字符串,那么JavaCC不允许(...)*扩展,这就是错误消息试图告诉您的内容。

合理的替代方案可能是:

(A | B)*

由于在这种情况下,AB都以<WHITESPACE>开头,因此有必要将其考虑在内:

(<WHITESPACE> ( Input() | (<IDUPPER><IDUPPER>)+ ) )*