1

我只是遇到了一件令人头疼的事情..

我尝试将语句拆分为不同的函数,就像我有一个示例语句

start
 n turnTo 's'.
 n terminate.
end

两个语句都以 'n' 开头,目前我正在写

statement 
    :
    (turnTo_statment|terminate_statment)*
    ;

turnTo_statment
    :
    variable 'turnTo' '\'' value '\'' '.'
    ;

terminate_statment
    :
    variable 'terminate' '.'
    ;

但是当词法分析器运行时,它无法确定哪个是哪个,因为两个子状态都以相同的东西'n'开头,编译器可以选择使用规则。如果下一个字符串与编译器使用的第一个规则不匹配,那么它将自动抛出一个不匹配的错误。

如果我遇到“x turnTo y”,我如何识别并告诉 ANTLR,然后使用规则 turnTo_statment,如果我遇到“x terminate”。然后使用规则 terminate_statment..

即在antlr中是否有任何功能可以做到这一点..

statement 
    :
    ((if statement contain_keywords 'turnTO') -> turnTo_statment
    |
    (if statement contain_keywords 'terminate') ->terminate_statment)*
    ;

谢谢..

4

2 回答 2

3

首先,不要在解析器规则中使用“文字”。如果没有大量的 ANTLR 经验,这会给你带来麻烦。创建真正的词法分析器规则:

TURNTO: 'turnTo';

现在,您可能需要通读 ANTLR wiki 上的教程并研究可下载的示例并确保您理解它们。写出好的语法似乎很容易,因为语法语言学起来很简单,但实际上它需要相当多的知识。首先要意识到的是,词法分析器不了解解析器——它只是对输入流进行标记并将这些标记传递给解析器——因此词法分析器模式不能模棱两可——解析器规则可以处理潜在的差异。

ANTLR 可能无需将其转换为 LL(1) 即可处理您的语法,因为 ANTLR 可以处理 LL(k) 并且通常无需您的帮助即可计算出 k 是什么。这是你的全部语法吗?但是,无论如何,最好保留因素:

statement: var ( TURNTO {etc} | TERMINATE DOT )
于 2012-12-10T04:35:21.927 回答
2

您的语法不是 LL(1) 语法(因为,正如您所注意到的,first(turnTo_statment) = first(terminate_statment))。但是,您可以通过左分解将其转换为 LL(1) 语法:

statement -> var_stmt statement
var_stmt -> variable turnto_stmt | variable terminate_stmt
turnto_stmt -> "turnTo" value
terminate_stmt -> "terminate."

我对ANTLR了解不多,但这是处理这类冲突的传统方式。

于 2012-12-09T13:02:37.890 回答