c# - Silverlight 中的 JavaScript 表达式解析器

标签 c# javascript silverlight parsing

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

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

谢谢,

弗拉基米尔

最佳答案

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

首先定义一个文法:

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);
    }
}

关于c# - Silverlight 中的 JavaScript 表达式解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4308653/

相关文章:

javascript - 在 javascript 函数中进行 2 次 xmlhttp.open 调用

c# - MD5 不存在于 System.Security.Cryptography 命名空间中

c# - 刚刚将 RavenDB 更新为 rev。 2230 从转。 960 和调用 session.SaveChanges() 我有 JsonSerialization 异常

c# - 如何确定一个对象是否是实现公共(public)接口(interface)的对象的集合

C# 林奇 : How is string ("[1, 2, 3]") parsed as an array?

c# - 使用 Automapper 从嵌套多层的列表中映射/转换为父属性

javascript - 在两个 ASP.NET 页面之间传递敏感数据

Javascript 获取正文 JSON 列表

silverlight - 在 silverlight 中验证颜色

c# - 适用于 Windows Mobile 的 Silverlight 中的 Storyboard.GetTarget