JavaCC - 将数学表达式解析为类结构

发布于 2024-07-20 01:05:37 字数 3057 浏览 8 评论 0原文

我正在使用这个语法来计算数学表达式:

    // Konfiguration (JavaCC-Manual konsultieren)
options {
    STATIC = true; // alle Parser-operationen sind static
    // verwende zwei Token um zu entscheiden, was passieren soll
    LOOKAHEAD = 2;
}

// hier beginnt unsere Parser Klasse ("MathParse")
PARSER_BEGIN(MathParse)
// hier kann ganz normaler Java-Code verwendet werden
public class MathParse {
    public static void main(String[] args) {
        // auch ein statischer Parser muss initiiert werden
        // - allerdings nur einmal
        MathParse parser = new MathParse(System.in);
        try {
            System.out.println(parser.parse());
        } catch(ParseException e) {
            e.printStackTrace();
        }
    }

    // die Parser-Methoden werden automatisch hinzugefügt
}
PARSER_END(MathParse)

// Diese Zeichen ignorieren wir
// SKIP : { $regex$ }
SKIP : { " " | "\t" }

// Jetzt definieren wir unsere Token

// TOKEN : { < $tokenname$ : $regex$ >}
// "NUMBER" entspricht einer unbegrenzten Anzahl (min. 1) an Zahlen
// (von 0 bis 9)
TOKEN : { < NUMBER : (["0"-"9"])+ ("." (["0"-"9"])+)? > }
TOKEN : { < EOL : "\n" > }

// Und fröhlich weiter mit der tatsächlichen Syntax
double parse() : {
    double value;
}
{
    value=expr()
    (<EOF> | <EOL>)     { return value; }
}

double expr() : {
    double x;
    double y;
}
{
    x=term()
    (
        "+" y=expr()    { x += y; }
    |
        "-" y=expr()    { x -= y; } 
    )*
    { return x; }
}

double term() : {
    double x;
    double y;
}
{
    x=value()
    (
        "*" y=term()    { x *= y; }
        |
        "/" y=term()    { x /= y; }
    )*
    { return x; }
}

double value() : {
    double value;
}
{
    "-" value=number()  { return -value; }
    |
    value=number()      { return value; }
}

double number() : {
    Token t;
    double value;
}
{
    t=<NUMBER>      { return Double.parseDouble(t.image); }
    |
    "(" value=expr() ")"    { return value; }
}

效果很好。 但现在我不想得到一个数字作为结果,而是一个代表该术语的类结构。 我想到了这样的事情:

public abstract class Expression {
    public abstract double calculate();
}

public class NumberExpression extends Expression {
    public double Value;

    public NumberExpression(double value) {
        this.Value = value;
    }

    public double calculate() {
        return this.Value;
    }
}

public class ComplexExpression extends Expression {
    public Operator Operator;
    public Vector SubExpressions;

    public double calculate() {
        double result = ((Expression)this.SubExpressions.elementAt(0)).calculate();

        for (int i = 1; i < this.SubExpressions.size(); ++i)
            result = this.Operator.calculate(result, ((Expression)this.SubExpressions.elementAt(i)).calculate());

        return result;
    }
}

public abstract class Operator {
    public abstract String getOperator();
    public abstract double calculate(double x, double y);
}

我与 Java 或 JavaCC 没有太多关系,所以你能告诉我如何为此编写语法吗?

PS:我使用的是Java ME。

I'm using this grammar to calculate math expressions:

    // Konfiguration (JavaCC-Manual konsultieren)
options {
    STATIC = true; // alle Parser-operationen sind static
    // verwende zwei Token um zu entscheiden, was passieren soll
    LOOKAHEAD = 2;
}

// hier beginnt unsere Parser Klasse ("MathParse")
PARSER_BEGIN(MathParse)
// hier kann ganz normaler Java-Code verwendet werden
public class MathParse {
    public static void main(String[] args) {
        // auch ein statischer Parser muss initiiert werden
        // - allerdings nur einmal
        MathParse parser = new MathParse(System.in);
        try {
            System.out.println(parser.parse());
        } catch(ParseException e) {
            e.printStackTrace();
        }
    }

    // die Parser-Methoden werden automatisch hinzugefügt
}
PARSER_END(MathParse)

// Diese Zeichen ignorieren wir
// SKIP : { $regex$ }
SKIP : { " " | "\t" }

// Jetzt definieren wir unsere Token

// TOKEN : { < $tokenname$ : $regex$ >}
// "NUMBER" entspricht einer unbegrenzten Anzahl (min. 1) an Zahlen
// (von 0 bis 9)
TOKEN : { < NUMBER : (["0"-"9"])+ ("." (["0"-"9"])+)? > }
TOKEN : { < EOL : "\n" > }

// Und fröhlich weiter mit der tatsächlichen Syntax
double parse() : {
    double value;
}
{
    value=expr()
    (<EOF> | <EOL>)     { return value; }
}

double expr() : {
    double x;
    double y;
}
{
    x=term()
    (
        "+" y=expr()    { x += y; }
    |
        "-" y=expr()    { x -= y; } 
    )*
    { return x; }
}

double term() : {
    double x;
    double y;
}
{
    x=value()
    (
        "*" y=term()    { x *= y; }
        |
        "/" y=term()    { x /= y; }
    )*
    { return x; }
}

double value() : {
    double value;
}
{
    "-" value=number()  { return -value; }
    |
    value=number()      { return value; }
}

double number() : {
    Token t;
    double value;
}
{
    t=<NUMBER>      { return Double.parseDouble(t.image); }
    |
    "(" value=expr() ")"    { return value; }
}

That works fine. But now I don't want to get a number as the result, but a class structure representing the term. I thought of something like this:

public abstract class Expression {
    public abstract double calculate();
}

public class NumberExpression extends Expression {
    public double Value;

    public NumberExpression(double value) {
        this.Value = value;
    }

    public double calculate() {
        return this.Value;
    }
}

public class ComplexExpression extends Expression {
    public Operator Operator;
    public Vector SubExpressions;

    public double calculate() {
        double result = ((Expression)this.SubExpressions.elementAt(0)).calculate();

        for (int i = 1; i < this.SubExpressions.size(); ++i)
            result = this.Operator.calculate(result, ((Expression)this.SubExpressions.elementAt(i)).calculate());

        return result;
    }
}

public abstract class Operator {
    public abstract String getOperator();
    public abstract double calculate(double x, double y);
}

I didn't have much to do with Java or JavaCC, so can you tell me how to write a grammar for that?

PS: I'm using Java ME.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

痴情换悲伤 2024-07-27 01:05:37

eWolf,

尝试使用 JJTree,它是 JavaCC 的预处理器,并自动引入为解析输入创建抽象语法树的 java 代码。

只需访问 https://javacc.dev.java.net/ 并找到 JJTree 手册。

eWolf,

Try using JJTree which is a preprocessor for JavaCC and automatically introduces java code that creates Abstract Syntax Trees for parsed input.

Just visit https://javacc.dev.java.net/ and find the JJTree manual.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文