【问题标题】:JavaScript expression parser in SilverlightSilverlight 中的 JavaScript 表达式解析器
【发布时间】:2010-11-29 22:18:05
【问题描述】:

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

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

谢谢,

弗拉基米尔

【问题讨论】:

    标签: c# javascript silverlight parsing


    【解决方案1】:

    手动创建递归下降解析器。很好玩!

    首先定义一个语法:

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        在 C# here at CodeProject 中有一个 JavaScript 子集的实现。

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-07-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-17
            相关资源
            最近更新 更多