Compiler construction 使用ANTLR语法来识别不同的函数(函数可能具有相同的起始项,但中间有关键字)

Compiler construction 使用ANTLR语法来识别不同的函数(函数可能具有相同的起始项,但中间有关键字),compiler-construction,antlr,antlr3,antlr4,Compiler Construction,Antlr,Antlr3,Antlr4,我刚刚遇到了一件令人头痛的事 我尝试将语句拆分为不同的函数,就像我有一个示例语句一样 start n turnTo 's'. n terminate. end 这两个语句都以“n”开头,目前我正在写 statement : (turnTo_statment|terminate_statment)* ; turnTo_statment : variable 'turnTo' '\'' value '\'' '.' ; terminate_

我刚刚遇到了一件令人头痛的事

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

start
 n turnTo 's'.
 n terminate.
end
这两个语句都以“n”开头,目前我正在写

statement 
    :
    (turnTo_statment|terminate_statment)*
    ;

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

terminate_statment
    :
    variable 'terminate' '.'
    ;
但当lexer运行时,它无法确定哪个是哪个,因为两个子状态都以相同的“n”开头,编译器可以选择使用这些规则。如果下一个字符串与编译器使用的第一个规则不匹配,那么它将自动抛出不匹配错误

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

i、 e.antlr中是否有执行此操作的功能

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

您的语法不是LL(1)语法(因为,正如您所注意到的,
first(turnTo station)=first(terminate station)
)。但是,您可以通过以下方式将其转换为LL(1)语法:

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

您的语法不是LL(1)语法(因为,正如您所注意到的,
first(turnTo_station)=first(terminate_station)
)。但是,您可以通过以下方式将其转换为LL(1)语法:


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

首先,不要在解析器规则中使用“文本”。如果没有在ANTLR方面的丰富经验,这将给您带来麻烦。创建真正的lexer规则:

TURNTO: 'turnTo';
现在,您可能需要通读ANTLR wiki上的教程,研究可下载的示例并确保理解它们。编写好的语法似乎很容易,因为语法语言很容易学习,但实际上它需要相当多的知识。但是首先要认识到的是,lexer不知道解析器——它只是对输入流进行标记并将这些标记传递给解析器——因此lexer模式不能是模糊的——解析器规则可以处理潜在的差异

ANTLR可能可以处理您的语法,而无需将其转换为LL(1),因为ANTLR可以处理LL(k),并且通常在没有您帮助的情况下计算出k是什么。这是你的全部语法吗?但是,不管怎样,最好还是保留以下因素:

statement: var ( TURNTO {etc} | TERMINATE DOT )

首先,不要在解析器规则中使用“文本”。如果没有在ANTLR方面的丰富经验,这将给您带来麻烦。创建真正的lexer规则:

TURNTO: 'turnTo';
现在,您可能需要通读ANTLR wiki上的教程,研究可下载的示例并确保理解它们。编写好的语法似乎很容易,因为语法语言很容易学习,但实际上它需要相当多的知识。但是首先要认识到的是,lexer不知道解析器——它只是对输入流进行标记并将这些标记传递给解析器——因此lexer模式不能是模糊的——解析器规则可以处理潜在的差异

ANTLR可能可以处理您的语法,而无需将其转换为LL(1),因为ANTLR可以处理LL(k),并且通常在没有您帮助的情况下计算出k是什么。这是你的全部语法吗?但是,不管怎样,最好还是保留以下因素:

statement: var ( TURNTO {etc} | TERMINATE DOT )