Java CC 问题 - "Expansion within "(...) *"can be matched by empty string"

标签 java compiler-construction javacc

我们已经获得了使用 Java CC 进行修补和解析的语法。它的问题之一是“(...)*”内的扩展可以与空字符串匹配。我理解这个错误是因为某些东西可以在可以匹配零次或多次的东西内部匹配零次或多次而引起的。

我不明白的是如何解决它。 (我们的老师并没有说太多,“你必须小心你的措辞。”

语法的问题区域及其相关的 Java CC 代码如下所示。任何想法或建议将不胜感激。

program := ( decl )*
           ( function ) *
           main_prog

decl := ( var_decl | const_decl )*

var_decl := var ident_list : type ( , ident_list : type)* ;

const_decl := const identifier : type = expression ( , identifier : type = expression)* ;

function :=
            type identifier ( param_list)
            ( decl )*
            ( statement ; )*
            return ( expression | e ); //e is greek epsilon character

main_prog := 
            main
            ( decl ) *
            (statement ; )*

我认为问题在于 decl 的声明方式。它在实际的 Java CC 代码中声明如下:

void decl():{}
{
( var_decl() | const_decl())*
}

如果我将上面的 Kleene 闭包更改为 + ,由此引起的所有其他错误都会消失。然而教练说星星应该保留,我们需要小心措辞。我发现了很多关于左分解、左递归删除等的资源,但关于这个特定问题的资源却很少。上面的代码实际上在 Java CC 中并没有错误,但会导致以下进一步的错误:

void program():{}
{
( decl() )* //error here - Expansion within "(...)*" can be matched by empty string
( function() )*
main_prog()
}

void main_prog(): {}
{
< MAIN >
( decl() )* //same error on this line
(statement() < SCOLON >)*
}

void function(): {}
{
type() < ID > <LPARENT > param_list() < RPARENT >
( decl() )* //same error on this line
( statement() < SCOLON > )*
< RET> ( expression() | {} ) <SCOLON > // {} is epsilon
}

任何有关如何解决此问题的想法将不胜感激。

最佳答案

就目前情况而言,你的语法不明确 - 它说 decl表示零个或多个声明,并且有很多地方允许零个或多个 decl s。你不需要*在这两个地方,只需选择一个或另一个,任何一种方法都会解析相同的程序,但它们在概念上略有不同。

您可以取出*decl :

decl := ( var_decl | const_decl )

program := ( decl )*
           ( function ) *
           main_prog

所以decl代表一个单个声明,以及 program 可能decl 序列开头但不必这样做。或者,您可以保留 *decl但从引用它的地方取出它:

decl := ( var_decl | const_decl )*

program := decl
           ( function ) *
           main_prog

现在decl代表类似于“声明 block ”而不是单个声明 - 每个 program 必须以声明 block 开头,但该 block 本身允许为空。

关于Java CC 问题 - "Expansion within "(...) *"can be matched by empty string",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20283556/

相关文章:

compiler-construction - 一种语言的编译器如何用该语言编写?

JAVACC && JJTree (.jjt) 插入 ||解析两个标记时将符号放入树中

Javacc 包问题

java - 正则表达式中的警告 - JavaCC

java - MongoDB Java : Finding objects in Mongo using QueryBuilder $in operator returns nothing

java - 如何创建仅包含子文件夹内容的 java jar 文件?

java - Eclipse 被导入混淆了 ("accessible from more than one module")

java - 外部类成员变量null转内部类

parsing - 左递归和右递归是否产生相同的解析树?

compiler-construction - 在 JDK 1.6 编译器中, "-source 1.6"启用什么(如果有)?