gpt4 book ai didi

ANTLR - 允许不完整的语法

转载 作者:行者123 更新时间:2023-12-04 06:06:27 24 4
gpt4 key购买 nike

我正在使用 ANTLR 来解析数学表达式字符串并使用 MathML 标记它们。

现在我有下面的语法。现在我有三个问题:

  • 语法允许完整的表达式,如 2*(3+4) .我想要
    它也允许不完整的表达式,例如2*(3+ .成为一个
    ANTLR 的完全新手我不知道如何做到这一点。
    请指出正确的文件或举个例子。
  • 平方根法则的位置sqrt在原子之间似乎
    工作,但我很确定它应该在 exponent 中的某个地方
    规则?还是应该?
  • 如果我想扩展这个语法来实际执行
    计算,我可以以某种方式重用它还是必须复制和粘贴?

  • 对我的语法的任何其他评论或建议也很感激,因为我现在使用 ANTLR 的总经验大约是四个小时。
    grammar Expr;

    parse returns [String value]
    : stat+ {$value = $stat.value;}
    ;

    stat returns [String value]
    : exponent NEWLINE {$value = "<math>" + $exponent.value + "</math>";}
    | NEWLINE
    ;

    exponent returns [String value]
    : e=expr {$value = $e.value;}
    ( '^' e=expr {$value = "<msup><mrow>" + $value + "</mrow><mrow>" + $e.value + "</mrow></msup>";}
    )*
    ;

    expr returns [String value]
    : e=multExpr {$value = $e.value;}
    ( '+' e=multExpr {$value += "<mo>+</mo>" + $e.value;}
    | '-' e=multExpr {$value += "<mo>-</mo>" + $e.value;}
    )*
    ;

    multExpr returns [String value]
    : e=atom {$value = $e.value;}
    ( '*' e=atom {$value += "<mo>*</mo>" + $e.value;}
    | '/' e=atom {$value += "<mo>/</mo>" + $e.value;}
    )*
    ;

    atom returns [String value]
    : INT {$value = "<mn>" + $INT.text + "</mn>";}
    | '-' e=atom {$value = "<mo>-</mo>" + $e.value;}
    | 'sqrt[' exponent ']' {$value = "<msqrt><mrow>" + $exponent.value + "</mrow></msqrt>";}
    | '(' exponent ')' {$value = "<mo>(</mo>" + $exponent.value + "<mo>)</mo>";}
    ;

    INT : '0'..'9'+ ;
    NEWLINE:'\r'? '\n' ;
    WS : (' '|'\t')+ {skip();} ;

    最佳答案

    首先是关于你的语法的一些评论:

  • 您应该为左右手边的规则指定唯一标签( e1=atom ('*' e2=atom ... );
  • 您可能想要创建单独的 sqrt[ token 而不是 1 个 sqrt[ , 否则输入如 "sqrt [ 9 ]" ( sqrt[ 之间的空格)将无法正确处理;
  • 一元减法的优先级通常低于求幂。

  • rickythefox wrote:

    The location of the square root rule sqrt among the atomics seems to work but I'm pretty sure it should be somewhere in the exponent rule? Or should it?



    不,在那里很好:它应该具有最高优先级。谈到优先级,您的情况下通常的优先级表(从最低到最高)是:
  • 加减法;
  • 乘法和除法;
  • 一元减法;
  • 求幂;
  • 括号表达式(包括函数调用,如 sqrt[...] )。

  • rickythefox wrote:

    The grammar allows for complete expressions like 2*(3+4). I want it to also allow incomplete expressions, e.g. 2*(3+. Being a complete newbie at ANTLR I have no idea how to accomplish this. Please point me to the right document or give an example.



    这很棘手。

    我真的只看到一种方法:在你的 stat 规则中,你首先强制解析器在 token 流中向前看以检查是否真的存在 expr先。这可以使用 syntactic predicate 来完成。 .一旦解析器确定存在 expr ,然后才解析所述表达式。如果没有 expr ,尝试匹配一个 NEWLINE ,如果也没有 NEWLINE , 只需消耗除 NEWLINE 之外的单个 token (它必须是不完整表达式的一部分!)。 (我将在下面发布一个小演示)

    rickythefox wrote:

    If I want to extend this grammar to also actually perform the calculation, can I somehow reuse it or do I have to copy and paste?



    ANTLR 解析器规则可以返回多个对象。这当然不是真的,因为 Java 方法(本质上是解析器规则)只能返回单个对象。解析器规则返回一个对象,该对象包含对多个对象的引用。所以你可以这样做:
    stat returns [String str, double num]
    : ...
    ;

    一个演示

    考虑到我的所有提示,一个小的工作演示可能如下所示:

    grammar Expr;

    parse returns [String str, double num]
    @init{$str = "";}
    : (stat
    {
    $str += $stat.str;
    $num = $stat.num;
    if(!Double.isNaN($num)) {
    System.out.println($stat.text.trim() + " = " + $num);
    }
    })+
    ;

    stat returns [String str, double num]
    : (expr)=> expr NEWLINE {$str = "<math>" + $expr.str + "</math>"; $num = $expr.num;}
    | NEWLINE {$str = ""; $num = Double.NaN;}
    | ~NEWLINE {$str = ""; $num = Double.NaN; System.err.println("Ignoring: " + $text);}
    ;

    expr returns [String str, double num]
    : e1=multExpr {$str = $e1.str; $num = $e1.num;}
    ( '+' e2=multExpr {$str += "<mo>+</mo>" + $e2.str; $num += $e2.num;}
    | '-' e2=multExpr {$str += "<mo>-</mo>" + $e2.str; $num -= $e2.num;}
    )*
    ;

    multExpr returns [String str, double num]
    : e1=unaryExpr {$str = $e1.str; $num = $e1.num;}
    ( '*' e2=unaryExpr {$str += "<mo>*</mo>" + $e2.str; $num *= $e2.num;}
    | '/' e2=unaryExpr {$str += "<mo>/</mo>" + $e2.str; $num /= $e2.num;}
    )*
    ;

    unaryExpr returns [String str, double num]
    : '-' e=expExpr {$str = "<mo>-</mo>" + $e.str; $num = -1 * $e.num;}
    | e=expExpr {$str = $e.str; $num = $e.num;}
    ;

    expExpr returns [String str, double num]
    : e1=atom {$str = $e1.str; $num = $e1.num;}
    ( '^' e2=atom {$str = "<msup><mrow>" + $str + "</mrow><mrow>" + $e2.str + "</mrow></msup>"; $num = Math.pow($num, $e2.num);}
    )*
    ;

    atom returns [String str, double num]
    : INT {$str = "<mn>" + $INT.text + "</mn>"; $num = Double.valueOf($INT.text);}
    | 'sqrt' '[' expr ']' {$str = "<msqrt><mrow>" + $expr.str + "</mrow></msqrt>"; $num = Math.sqrt($expr.num);}
    | '(' expr ')' {$str = "<mo>(</mo>" + $expr.str + "<mo>)</mo>"; $num = $expr.num;}
    ;

    INT : '0'..'9'+;
    NEWLINE : '\r'? '\n';
    WS : (' '|'\t')+ {skip();};

    (注意 (...)=> 就是所谓的 句法谓词 )

    您可以使用以下类测试从上述语法生成的解析器:

    import org.antlr.runtime.*;

    public class Main {
    public static void main(String[] args) throws Exception {
    String src =
    "sqrt [ 9 ] \n" +
    "1+2*3 \n" +
    "2*(3+ \n" +
    "2*(3+42)^2 \n";
    ExprLexer lexer = new ExprLexer(new ANTLRStringStream(src));
    ExprParser parser = new ExprParser(new CommonTokenStream(lexer));
    ExprParser.parse_return returnValue = parser.parse();
    String mathML = returnValue.str;
    double eval = returnValue.num;
    // ...
    }
    }

    如果你现在运行上面的类,你会看到输入

    sqrt [ 9 ]
    1+2*3
    2*(3+
    2*(3+42)^2

    将产生以下输出:

    sqrt[9] = 3.0
    1+2*3 = 7.0
    Ignoring: 2
    Ignoring: *
    Ignoring: (
    Ignoring: 3
    Ignoring: +
    2*(3+42)^2 = 4050.0

    关于ANTLR - 允许不完整的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8299220/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com