将表达式解析为其组件和子组件

时间:2013-08-07 17:53:58

标签: java parsing abstract-machine

我需要解析一个表达式,例如:neg(and(X,Y))

我需要它来提出抽象堆栈机器代码,例如上面的例子:

LOAD X;
LOAD Y;
EXEC and;
EXEC neg;

但是现在机器代码不是问题,我怎样才能将表达式的输入字符串解析/拆分成所有子表达式?

我试图找到第一个括号,然后从那个连接到最后一个括号,但如果你有一个内部表达式则会给出isuess?

我尝试过的代码:(请不要它仍处于开发阶段)

private boolean evaluateExpression(String expression) {

    int brackets = 0;
    int beginIndex = -1;
    int endIndex = -1;

    for (int i = 0; i < expression.length(); i++) {
        if (expression.charAt(i) == '(') {
            brackets++;

            if (brackets == 0) {
                endIndex = i;
                System.out.println("the first expression ends at " + i);
            }
        }
        if (expression.charAt(i) == ')') {
            brackets--;

            if (brackets == 0) {
                endIndex = i;
                System.out.println("the first expression ends at " + i);
            }
        }
    }
    // Check for 1st bracket
    for (int i = 0; i < expression.length(); i++) {
        if (expression.charAt(i) == '(') {
            beginIndex = i;
            break;
        }
    }

    String subExpression = expression.substring(beginIndex, endIndex);
    System.out.println("Sub expression: " + subExpression);

    evaluateExpression(subExpression);

    return false;

}

我只是在寻找一个基本的解决方案,它只需要:和,或者,否则

3 个答案:

答案 0 :(得分:1)

您尝试解析的表达式实际上是Context Free Language,可以表示为Context Free Grammer

您可以创建一个表示该表达式语言的无上下文语法,并使用CFG解析器来解析它。

一个现有的java工具(以及更多)是JavaCC,尽管这可能是一种过度杀伤力。
另一种使用CFG解析句子的算法是CYK,它很容易编程和使用。


在这里,表示可用表达式的CFG是:

S -> or(S,S)
S -> and(S,S)
S -> not(S)
S -> x | for each variable x

请注意,虽然这是相对简单的CFG - 它描述的语言是不规则的,所以如果你希望使用正则表达式 - 它可能不是那种方法。

答案 1 :(得分:0)

实际上,如果你希望你的解析器足够强大以处理大多数情况,你想使用一个tokenizer(java有一个已实现的tokenizer类)来首先标记字符串,然后尝试识别每个表达式,存储操作数和树结构中的运算符,然后递归地计算它们。

如果你只想处理一些简单的情况,记得使用递归,这是核心部分〜

答案 2 :(得分:0)

解析这样的事情通常是使用语法树完成的,使用某种类型的优先级来操作顺序。您发布的内容的示例如下:

Processing items left to right the tree would be populated like this

1arg_fcall(neg)
        2arg_fcall(and)
            Load Y                      
            Load X

Now we can recursively visit this tree bottom to top to get
Load X
Load Y
EXEC and //on X and Y
EXEC neg //on result of and