如何将基于文本的编程代码(存储在DB中)转换为实际的编程代码?

问题描述:

Ok, i have a need to store some simple programming code text in DB, & then my application will read these text & convert them into actual programming code.

A good example is sqlfiddle.com. This website allow you to put sql code into it website, u then click a button & u can see the table result of that sql code. Ofcourse sqlfiddle must store the Txt-based code that u input into its database.

Another example is w3schools.com. It allows user to submit html code & then users can see the result on the fly. Ex:http://www.w3schools.com/js/tryit.asp?filename=tryjs_events

In my case i just need to use some limited keywords such as (if, for, while, +, *, -, /...)

Ex, I have a table called OrderItem with 3 columns:

ItemID - Qantity -Cost
Item1 - 10 - 5 USD
Item2 - 12 - 2 USD
Item3 - 4 - 1 USD

I also have a table ProgrammingCode

ItemID - Code
Item1 - "if quantity > 2 then totalcost=10*5 USD else totalCost=10*4USD; return totalCost"
Item2 - "if time=9am then totalcost=12*2 USD else totalCost=12*1USD; return totalCost "

Note: since there are variety of calculating rules in the real world, the code should be able to depict the real world so If or loop & all arithmetic operators should be used.

This is my Pseudocodefunction but i don't think it works.

    public String covertCode(String textBasedCode){
        String[] eachWord=textBasedCode.split(" ");
        if(eachWord[0].equals("if")){
             //do a lot of checking. how to let the program to know this?
             if(eachWord[2]>2{
                 return 10*5;
             }
             else{
                 return 10*4;
              }
         }
      }

I used java in this example, but u can use C++, C# php or any programming language you want. I just want to know the logic.

So, How to convert Text-based programming code (stored in DB) into actual programming code?

好的,我需要在DB中存储一些简单的编程代码文本,& 然后我的应用程序将阅读这些文本& 将它们转换为实际的编程代码。 p>

一个很好的例子是sqlfiddle.com。 这个网站允许你把sql代码放入它的网站,你然后点击一个按钮& 你可以看到那个sql代码的表结果。 Ofcourse sqlfiddle必须存储你输入到其数据库中的基于Txt的代码。 p>

另一个例子是w3schools.com。 它允许用户提交HTML代码和 然后用户可以即时查看结果。 例如: http://www.w3schools.com/js/tryit.asp?filename = tryjs_events p>

在我的情况下,我只需要使用一些有限的关键字,如(if,for,while,+,*, - ,/ ...。)。 p>

例如,我有一个名为OrderItem的表,其中包含3列: p>

 
ItemID  -  Qantity -Cost 
Item1  -  10  -  5 USD 
Item2  -  12  -  2 USD 
Item3  -  4  -  1 USD 
  pre> 
 
 

我还有一个表ProgrammingCode p>

 
ItemID  -  Code 
Item1  - “if quantity&gt  ; 2然后totalcost = 10 * 5 USD其他totalCost = 10 * 4USD;返回totalCost“
Item2  - ”如果时间= 9am则totalcost = 12 * 2 USD else totalCost = 12 * 1USD; return totalCost“
  pre>  
 
 

注意:由于现实世界中存在各种各样的计算规则,因此代码应该能够描绘真实世界,因此如果或循环和 应该使用所有算术运算符。 p>

这是我的Pseudocodefunction,但我觉得它不起作用。 p>

  public String covertCode(String textBasedCode){
 String [  ] eachWord = textBasedCode.split(“”); 
 if(eachWord [0] .equals(“if”)){
 //做了很多检查。 如何让程序知道这个?
 if(eachWord [2]> 2 {
返回10 * 5; 
} 
其他{
返回10 * 4; 
} 
} 
  } 
  code>  pre> 
 
 

我在这个例子中使用了java,但你可以使用C ++,C#php或任何你想要的编程语言。我只想知道逻辑。 p>

那么,如何将基于文本的编程代码(存储在DB中)转换为实际的编程代码? p> div>

I think I found an elegant solution based on the suggestion of Interpreter Pattern that Touch suggested me. I didn't know Interpreter Pattern before but after reading it for 15 mins I could come up a cool solution. I never earned an accepted answer before so i hope my answer can earn it.

The logic is simple. We gotta use the "Reverse Polish Notation expressions" like:

a b +
a b c + -
a b + c a - -

& that is done. http://en.wikipedia.org/wiki/Interpreter_pattern

     interface Expression {
    public int interpret(Map<String,Expression> variables);
}

class Number implements Expression {
    private int number;
    public Number(int number)       { this.number = number; }
    public int interpret(Map<String,Expression> variables)  { return number; }
}

class Plus implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Plus(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return leftOperand.interpret(variables) + rightOperand.interpret(variables);
    }
}

class Minus implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Minus(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return leftOperand.interpret(variables) - rightOperand.interpret(variables);
    }
}
class Times implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Times(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return leftOperand.interpret(variables) * rightOperand.interpret(variables);
    }
} 

class Division implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Division(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return leftOperand.interpret(variables) / rightOperand.interpret(variables);
    }
}

class IfThen implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public IfThen(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return (leftOperand.interpret(variables)==1) ? rightOperand.interpret(variables) : 0;
    }
}

class GreaterThan implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public GreaterThan(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return (leftOperand.interpret(variables) > rightOperand.interpret(variables)) ? 1 : 0;
    }
}

class GreaterThanOrEqual implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public GreaterThanOrEqual(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return (leftOperand.interpret(variables) >= rightOperand.interpret(variables)) ? 1 : 0;
    }
}
class LessThan implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public LessThan(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return (leftOperand.interpret(variables) < rightOperand.interpret(variables)) ? 1 : 0;
    }
}

class LessThanOrEqual implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public LessThanOrEqual(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return (leftOperand.interpret(variables) <= rightOperand.interpret(variables)) ? 1 : 0;
    }
}

class Equal implements Expression {
    Expression leftOperand;
    Expression rightOperand;
    public Equal(Expression left, Expression right) { 
        leftOperand = left; 
        rightOperand = right;
    }

    public int interpret(Map<String,Expression> variables)  { 
        return (leftOperand.interpret(variables) == rightOperand.interpret(variables)) ? 1 : 0;
    }
}
class Variable implements Expression {
    private String name;
    public Variable(String name)       { this.name = name; }
    public int interpret(Map<String,Expression> variables)  { 
        if(null==variables.get(name)) return 0; //Either return new Number(0).
        return variables.get(name).interpret(variables); 
    }
}
class Evaluator implements Expression {
    private Expression syntaxTree;

    public Evaluator(String expression) {
        Stack<Expression> expressionStack = new Stack<Expression>();
        for (String token : expression.split(" ")) {
            if  (token.equals("+")) {
                Expression subExpression = new Plus(expressionStack.pop(), expressionStack.pop());
                expressionStack.push( subExpression );
            }
            else if (token.equals("-")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new Minus(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals("*")) {
                Expression subExpression = new Times(expressionStack.pop(), expressionStack.pop());
                expressionStack.push( subExpression );
            }
            else if  (token.equals("/")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new Division(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals("if-then")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new IfThen(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals(">")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new GreaterThan(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals(">=")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new GreaterThanOrEqual(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals("<")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new LessThan(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals("<=")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new LessThanOrEqual(left, right);
                expressionStack.push( subExpression );
            }
            else if  (token.equals("==")) {
                // it's necessary remove first the right operand from the stack
                Expression right = expressionStack.pop();
                // ..and after the left one
                Expression left = expressionStack.pop();
                Expression subExpression = new Equal(left, right);
                expressionStack.push( subExpression );
            }
            else                        
                expressionStack.push( new Variable(token) );
        }
        syntaxTree = expressionStack.pop();
    }

    public int interpret(Map<String,Expression> context) {
        return syntaxTree.interpret(context);
    }
}

& that's it. To call the the converting method we just need this. See this simple code:

    String expression = "w x == z if-then";
                //String expression = "w x - z +";
                Evaluator sentence = new Evaluator(expression);
                Map<String,Expression> variables = new HashMap<String,Expression>();
                variables.put("w", new Number(10));
                variables.put("x", new Number(5));
                variables.put("z", new Number(42));
                int result = sentence.interpret(variables);
                System.out.println(result);

& that done. But it has limit that it doesn't have a loop, but if then is quite enough for me.

Am i doing correctly?

The hard way is to interpret the code within the database, the easier way is to store c# code and runtime compile it with CodeDOM http://msdn.microsoft.com/en-us/library/y2k85ax6.aspx

Or take a look at Iron Python. http://ironpython.net/

You can use Microsoft.CSharp.CSharpCodeProvider to compile code on-the-fly. In particular, Check CompileAssemblyFromFile

You could create your own mini interpreter which will interpret the code. It shouldn't take a very long time since you want it be limited.

But since all it does is calculate values, I think you could just let them store the numbers and you do the math within your code following your rules. Most database come with plenty of functions builtin, so this can also be done from within the database.

I just don't see how "Text-based programming code" is different from "actual programming code".

So you can use the interpreter design pattern for this. There is probably other ways but this is my best guess. And you won't get code if that's what you looking for.

Check out the Roslyn project. It gives you the opportunity to use the compiler as a service to create plugins, code analyzers, etc.

http://msdn.microsoft.com/en-us/vstudio/hh500769.aspx

http://blog.filipekberg.se/2013/02/07/compilation-as-a-service-and-the-next-generation-plugins/