【问题标题】:Convert a form of BNF grammar to g4 grammar将一种形式的 BNF 文法转换为 g4 文法
【发布时间】:2018-11-11 04:06:01
【问题描述】:

我试图隐藏这个 BNF 语法来验证当前在 Swift 中使用的布尔表达式。现在想用Java实现类似的解析器。我遇到了 Antlr4 lib,想用它来生成相同语法的解析器。我对antlr4不是很熟悉。有人可以给我一些指导吗?这是我目前所拥有的。

Expr                ::= <ConcatenationExpr>;
NonInfixExpr        ::= <BracketExpr>
                      | <Function>
                      | <Literal>
                      | <Accessor>;
BracketExpr         ::= '(' <Expr> ')';
Accessor            ::= ('$' <AccessorComponent> | <AccessorComponent>) ('.' <AccessorComponent> )*;
AccessorComponent   ::= 'Identifier' ':' 'Identifier' | 'Identifier';
Function            ::= 'Identifier' '(' ')' | ('Identifier' '(' <Expr> (',' <Expr>)* ')');
Literal             ::= 'True'
                     | 'False'
                     | 'Null'
                     | 'Number'
                     | 'Text';
ConcatenationExpr   ::= <AndExpr>
                     | <ConcatenationExpr> '&' <AndExpr>;
AndExpr             ::= <OrExpr>
                     | <AndExpr> '&&' <OrExpr>;
OrExpr              ::= <EqualityExpr>
                     | <OrExpr> '||' <EqualityExpr>;
EqualityExpr        ::= <ComparisonExpr>
                     | <EqualityExpr> ('==' | '=' | '!=' | '<>') <ComparisonExpr>;
ComparisonExpr      ::= <AddExpr>
                     | <AddExpr> ('<' | '<=' | '>' | '>=') <AddExpr>;
AddExpr             ::= <ExponentialExpr>
                     | <AddExpr> ('+' | '-') <ExponentialExpr>;
ExponentialExpr     ::= <MultExpr>
                     | <ExponentialExpr> '^' <MultExpr>;
MultExpr            ::= <NonInfixExpr>
                     | <MultExpr> ('*' | '/') <NonInfixExpr>;

我尝试转换为 g4,这就是它的样子。

grammar VALIDATE;

Expr
    : ConcatenationExpr ';'
    ;

NonInfixExpr
    : BracketExpr 
    | Function 
    | Literal 
    | Accessor
    ;

BracketExpr 
    : '(' Expr ')'
    ;

Accessor
    : ('$' AccessorComponent | AccessorComponent ) ('.' AccessorComponent )*
    ;

AccessorComponent
    : 'Identifier' ':' 'Identifier' | 'Identifier'
    ;

Function
    : 'Identifier' '(' ')' | ('Identifier' '(' Expr (',' Expr)* ')')
    ;

Literal
    : 'True' | 'False' | 'Null' | 'Number' | 'Text'
    ;

ConcatenationExpr
    : AndExpr 
    | ConcatenationExpr '&&' AndExpr
    ;

AndExpr
    : OrExpr | AndExpr '&&' OrExpr
    ;

OrExpr
    : EqualityExpr | OrExpr '||' EqualityExpr
    ;

EqualityExpr
    : ComparisonExpr | EqualityExpr ('==' | '=' | '!=' | '<>') ComparisonExpr
    ;

ComparisonExpr
    : AddExpr | AddExpr ('<' | '<=' | '>' | '>=') AddExpr
    ;

AddExpr
    : ExponentialExpr | AddExpr ('+' | '-') ExponentialExpr
    ;

ExponentialExpr
    : MultExpr | ExponentialExpr '^' MultExpr
    ;

MultExpr
    : NonInfixExpr | MultExpr ('*' | '/') NonInfixExpr
    ;

我卡在 antlr4 VALIDATE.g4 步骤。我不确定我的转换是否正确。

error(119): VALIDATE.g4::: The following sets of rules are mutually left-recursive [MultExpr] and [ExponentialExpr] and [AddExpr] and [EqualityExpr] and [OrExpr] and [AndExpr] and [ConcatenationExpr]
error(99): VALIDATE.g4::: grammar VALIDATE has no rules

【问题讨论】:

  • ANTLR 不支持跨多个规则的左递归。您需要将所有表达式规则组合成一个规则Expr,并按优先级排序;或者重写语法以去除左递归。
  • “谁能给我指导”“我被卡住了”不是问题。然而,当我搜索“antlr left recursion tutorial”时,谷歌确实为我找到了以下内容:theantlrguy.atlassian.net/wiki/spaces/ANTLR3/pages/2687334/…
  • @StephenC 请注意,此信息已过时。与 ANTLR3 不同,ANTLR4 确实支持在单个规则中进行左递归,因此解决 OP 问题的最简单方法实际上就是将所有内容放入一个表达式规则中。

标签: java parsing antlr4 parser-generator


【解决方案1】:

原始文法没有相互左递归 - 仅在转换后的版本中通过在 ConcatenationExpr 中使用 &amp;&amp; 引入,它应该读取 &amp;。一旦解决了这个问题,语法就只有 ANTLR 4 应该能够处理的直接左递归。

您甚至可以通过重写递归规则来完全删除左递归,例如ConcatenationExpr 会变成

ConcatenationExpr
     ::= AndExpr ( '&' AndExpr )*

如果对所有递归规则都这样做,则生成的文法为 LL(2)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 2015-05-11
    • 2020-11-21
    • 1970-01-01
    • 2021-05-13
    相关资源
    最近更新 更多