【问题标题】:Grammar to recognize unlimited '{' expr '}' next to each-other识别相邻的无限'{' expr '}' 的语法
【发布时间】:2015-12-23 18:08:57
【问题描述】:

我正在编写一个使用ANTLR4 的C# 应用程序来识别以下TeX'ish 风格:

{a}{x}+{b}{y}+{c}

我当前的语法总是采用 '{' expr '}' 的最后一个实例,然后忽略字符串的开头。以下是当前语法的一些输出结果(如下所述):

  • 输入: {a} 输出: a [通过]
  • 输入: {a}+{x} 输出: a + x [通过]
  • 输入: {a}{x} 输出: x [失败] 期望: 斧头
  • 输入: {a}{x}+{b} 输出: x + b [失败] 期望: ax + b
  • 输入: {a}{x}+{b}{y} 输出: y [失败] Desired: ax + by
  • 输入: {a}{x}+{b}{y}+{c} 输出: y + c [失败] 期望: ax + by + c
  • 输入: {a}{x}+{b}{y}+{c}{d} 输出: d [失败] 期望: ax + by + cd

关于如何解决这个问题的任何想法?

语法 MyGra.g4 文件:

/*
 * Parser Rules
 */
prog: expr+ ;

expr : '{' expr '}'                 # CB_Expr
     | expr op=('+'|'-') expr       # AddSub
     | '{' ID '}'                   # CB_ID
     | ID                           # ID
     ;

/*
 * Lexer Rules
 */
ID: ('a' .. 'z' | 'A' .. 'Z')+;
ADD : '+';
SUB : '-';
WS:   (' ' | '\r' | '\n') -> channel(HIDDEN);

MyGraVisitor.CS 文件:

 public override string VisitID(MyGraParser.IDContext context)
 {
      return context.ID().GetText();
 }

 public override string VisitAddSub(MyGraParser.AddSubContext context)
 {
     if (context.op.Type == MyGraParser.ADD)
     {
         return Visit(context.expr(0)) + " + " + Visit(context.expr(1));
     }
     else
     {
         return Visit(context.expr(0)) + " - " + Visit(context.expr(1));
     }
 }

 public override string VisitCB_Expr(MyGraParser.CB_ExprContext context)
 {
     return Visit(context.expr());
 }

 public override string VisitCB_ID(MyGraParser.CB_IDContext context)
 {
     return context.ID().GetText();
 }

更新 #1:

建议在

中加入语法规则
'{' expr '}{' expr '}'

但是,如果我有 {a}{b}{c}{d}+{e}{f}{g},我认为语法应该考虑递归版本“自身”通过解析树......那么如果我有 1000 个 {expr} 彼此相邻怎么办?那我需要多少规则?我认为这个建议是有效的,除了我不确定如何计算无限数量的 {expr} 彼此相邻?

我的另一个问题是:如何重复使用规则 CB_Expr

更新 #2:

我添加了规则:

| expr CB_Expr                  # CB_Expr2

与访客:

public override string VisitCB_Expr2(MyGra.CB_Expr2Context context)
{
    return Visit(context.expr()) + Visit(context.CB_Expr());
}

这没有帮助,我仍然在所有情况下得到相同的输出(如上所述)。

【问题讨论】:

  • c#跟它有什么关系
  • 您允许 {expr}{expr} 的规则在哪里? {a}{b} 应该如何解释?我发现您的语法缺失和我看到的失败似乎是相关的。
  • 谢谢@Patrick87,我已经更新了问题
  • 请将您的问题缩小到具体问题。这个问题有一种“为我做我的工作”的意味......
  • CB_ID 是多余的模棱两可。 {x} 的解析有两个可能的树:CB_Expr (ID)CB_ID

标签: c# antlr grammar antrl4


【解决方案1】:

你的语法模棱两可。例如:输入 {x} 可以有两个不同的解析树(如 Mephy 所说):

(CB_Expr { (expr (ID x)) })

(DB_ID {x})

删除 CB_ID 将解决此问题,而实际上不会做任何负面的事情。

对于您的实际问题,这应该可以解决 expr:

expr : left=id_expr op=('+' |'-') right=expr #AddSub
     | id_expr                               #ID_Expr
     ;

id_expr :
     | '{' ID '}' id_expr                    #ID_Ex
     | '{' ID '}'                            #ID
     ;

虽然我没有对此进行测试,也没有给你写任何访问者,但语法应该可以工作。

id_expr 规则以递归方式工作,因此您应该能够根据需要将任意数量的 {ID} 放在一起 - 不过至少一个,目前的语法方式。

【讨论】:

    猜你喜欢
    • 2020-12-18
    • 1970-01-01
    • 2021-03-02
    • 2021-07-15
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多