Silverlight中的JavaScript表达式解析器

时间:2010-11-29 22:18:06

标签: c# javascript silverlight parsing

嘿大家好!我有一个需要帮助用户创建JavaScript逻辑表达式的Silverlight项目(例如“var1!= var2&& var3> = var4”)。非常简单。问题是我没有太多时间自己创建一个,因为调整转换表会耗费一些时间。

所以我在网上搜索一个,但我找到的只有几个类可以帮助你验证JavaScript,但是我需要一种方法来加载它,解析它然后再写回来。所以我想知道是否有人对如何做到这一点有任何想法。我假设它不需要太多代码,也不必是C#示例。如果你能用C ++甚至伪代码给我一些想法,那将会有很大的帮助。

谢谢,

弗拉基米尔

4 个答案:

答案 0 :(得分:2)

手动创建递归下降解析器。这很有趣!

首先定义一个语法:

Expression -> SimpleExpression ExpressionTail
              (Expression)
SimpleExpression -> Atom Inequality Atom
ExpressionTail -> && Expression |
                  || Expression |
                  e
Atom -> Variable | Literal
Inequality -> == | != | > | >= | < | <=

(这个语法不处理运算符优先级,但很容易编写一个语法。)

接下来,创建一个词法分析器,它将读取输入字符串并创建标记,因此字符串“var1!= 4.0”将被转换为{Variable,!=,Literal}列表。这可能会被黑客攻击,或者如果你想获得幻想,你可以使用有限状态机来分析字符串。

现在创建一个递归下降解析器,将令牌列表解析为表达式树。

public class Parser {

    public Parser() {
    }

    public Expression parse( LexicalAnalyzer lex) {
        lex.advance();
        return expression( lex);
    }

    private Expression expression( LexicalAnalyzer lex) {  

        switch( lex.current().type() ) {
            case Token.OpenParen:
                lex.advance();
                Expression expression = expression( lex);
                lex.eat( Token.CloseParen);
                return expression;
            case Token.Literal:
            case Token.Variable:
                return expressionTail( lex, simpleExpression(lex));
            default:
                throw new Exception( "ParseError: Expecting (, variable, or literal at character " + 
                                      lex.character());
        }
    }

    private SimpleExpression simpleExpression( LexicalAnalyzer lex) {

        Atom atom = atom( lex);
        switch( lex.current().type() ) {
            case Token.Equal:
                lex.advance();
                return new Equal( atom, atom(lex));
            case Token.NotEqual:
                lex.advance();
                return new NotEqual( atom, atom(lex));
            ...
            default:
                throw new Exception( "ParseError: Expecting ==, !=, <, <=, >, >= at" + 
                                     lex.character());
        }
     }

     private Expression expressionTail( LexicalAnalyzer lex, SimpleExpression expression) {

        switch( lex.current().type() ) {
            case Token.LogicalOr:
                lex.advance();
                return new OrExpression( expression, expression(lex) );
            case Token.LogicalAnd:
                lex.advance();
                return new AndExpression( expression, exptression(lex) );
            default:
                return expression;
        }
     }

     private Atom atom( LexicalAnalyzer lex) {
         switch( lex.current().type() ) {
             case Token.Literal:
                 Literal literal = new Literal( lex.current() );
                 lex.advance();
                 return literal;
             case Token.Variable:
                 Variable var = new Variable( lex.current() );
                 lex.advance();
                 return var;
             default:
                 throw new Exception("ParseError: ...");
          }
      }
}


public interface Expression {
    boolean evaluate( VariableValues values);
}

public interface SimpleExpression implements Expression {
}

public class Equal implements SimpleExpression {
    private final Atom left, right;
    public Equal( Atom left, Atom right) {
        this.left = left;
        this.right = right;
    }
    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) == right.evaluate(values);
    }
}
public class NotEqual implements SimpleExpression {
    private final Atom left, right;
    public NotEqual( Atom left, Atom right) {
        this.left = left;
        this.right = right;
    }
    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) != right.evaluate(values);
    }
}

public class OrExpression implements Expression {
    private final Expression left, right;

    public OrExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) || right.evaluate(values);
    }
}
public class AndExpression implements Expression {
    private final Expression left, right;

    public AndExpression( Expression left, Expression right) {
        this.left = left;
        this.right = right;
    }

    public boolean evaluate( VariableValues values) {
        return left.evaluate(values) && right.evaluate(values);
    }
}
public interface Atom {
    double evaluate( VariableValues values);
}
public class Literal implements Atom {
    private final double value;
    public Literal( double value) {
        this.value = value;
    }
    public double evaluate( VariableValues values) {
        return value;
    }
}
public class Variable implements Atom {
    private final String name;
    public Variable( String name) {
        this.name = name;
    }
    public double evaluate( VariableValues values) {
        return values.getValue( name);
    }
}

答案 1 :(得分:1)

以下是用JavaScript编写的:http://silentmatt.com/parser3.js(来自:Javascript parser for simple expression)。移植会很痛苦,但这是一个开始。

答案 2 :(得分:1)

C#here at CodeProject中提供了一个JavaScript子集的实现。

答案 3 :(得分:0)

我在flash / actionscrpt中做过类似的事情。我认为它在Silverlight中几乎相同。快速谷歌搜索后,我看到RegisterScriptableObject类似于ActionScript的ExternalInterface。无论如何,这是我的example

This Silverlight示例非常接近于做同样的事情。