Advertisement
Guest User

SimplyExpress first release code

a guest
Jun 13th, 2012
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.63 KB | None | 0 0
  1. Example code:
  2.  
  3.  
  4.  
  5. /*
  6. <Copyright Header>
  7. Copyright (c) 2012 Jordan "Earlz/hckr83" Earls  <http://lastyearswishes.com>
  8. All rights reserved.
  9.  
  10. Redistribution and use in source and binary forms, with or without
  11. modification, are permitted provided that the following conditions
  12. are met:
  13.  
  14. 1. Redistributions of source code must retain the above copyright
  15.    notice, this list of conditions and the following disclaimer.
  16. 2. Redistributions in binary form must reproduce the above copyright
  17.    notice, this list of conditions and the following disclaimer in the
  18.    documentation and/or other materials provided with the distribution.
  19. 3. The name of the author may not be used to endorse or promote products
  20.    derived from this software without specific prior written permission.
  21.    
  22. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  23. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  24. AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
  25. THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  28. OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  30. OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  31. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32.  
  33. </Copyright Header>
  34. */
  35. using System;
  36. using System.Collections.Generic;
  37.  
  38. namespace SimplyExpress
  39. {
  40.     class MainClass
  41.     {
  42.         public static void Main (string[] args)
  43.         {
  44.             List<ExpressionToken> tokens=new List<ExpressionToken>();
  45.             ExpressionToken t=new ExpressionToken();
  46.            
  47.             t.IsOperation=true;
  48.             t.Op=new IncrementOperation();
  49.             tokens.Add(t);
  50.             t=new ExpressionToken();
  51.             t.IsOperation=false;
  52.             t.Value=new MyValue(){Value=5};
  53.             tokens.Add(t);
  54.             t=new ExpressionToken();
  55.             t.IsOperation=true;
  56.             t.Op=new AddOperation();
  57.             tokens.Add(t);
  58.             t=new ExpressionToken();
  59.             t.IsOperation=false;
  60.             t.Value=new MyValue(){Value=10};
  61.             tokens.Add(t);
  62.             t=new ExpressionToken();
  63.             t.IsOperation=true;
  64.             t.Op=new MultiplyOperation();
  65.             tokens.Add(t);
  66.             t=new ExpressionToken();
  67.             t.IsOperation=false;
  68.             t.Value=new MyValue(){Value=2};
  69.             tokens.Add(t);
  70.             t=new ExpressionToken();
  71.            
  72.             List<Associativity> map=new List<Associativity>();
  73.             map.Add(Associativity.LeftToRight); //not used
  74.             map.Add(Associativity.LeftToRight); //not used
  75.             map.Add(Associativity.RightToLeft);
  76.             map.Add(Associativity.LeftToRight);
  77.             map.Add(Associativity.LeftToRight);
  78.             var express=new SimplyExpress(map);
  79.            
  80.             MyValue tmp=(MyValue)express.Evaluate(tokens);
  81.             System.Console.WriteLine("tmp is "+tmp.Value.ToString());
  82.         }
  83.  
  84.        
  85.     }
  86.     class MyValue : ExpressionValue
  87.     {
  88.         public int Value;
  89.     }
  90.     class AddOperation : Operation{
  91.         public AddOperation(){
  92.             Name="Binary Addition";
  93.             OpType=OperationType.LeftRightOp;
  94.             Precedence=4;
  95.         }
  96.         public override ExpressionValue Execute (ExpressionValue left, ExpressionValue right)
  97.         {
  98.             var l=(MyValue)left;
  99.             var r=(MyValue)right;
  100.             var res=new MyValue();
  101.             res.Value=l.Value+r.Value;
  102.             return res;
  103.         }
  104.     }
  105.     class SubtractOperation : Operation{
  106.         public SubtractOperation(){
  107.             Name="Binary Subtraction";
  108.             OpType=OperationType.LeftRightOp;
  109.             Precedence=4;
  110.         }
  111.         public override ExpressionValue Execute (ExpressionValue left, ExpressionValue right)
  112.         {
  113.             var l=(MyValue)left;
  114.             var r=(MyValue)right;
  115.             var res=new MyValue();
  116.             res.Value=l.Value-r.Value;
  117.             return res;
  118.         }
  119.     }
  120.     class MultiplyOperation : Operation{
  121.         public MultiplyOperation(){
  122.             Name="Binary Multiplication";
  123.             OpType=OperationType.LeftRightOp;
  124.             Precedence=3;
  125.         }
  126.         public override ExpressionValue Execute (ExpressionValue left, ExpressionValue right)
  127.         {
  128.             var l=(MyValue)left;
  129.             var r=(MyValue)right;
  130.             var res=new MyValue();
  131.             res.Value=l.Value*r.Value;
  132.             return res;
  133.         }
  134.     }
  135.     class IncrementOperation : Operation{
  136.         public IncrementOperation(){
  137.             Name="Prefix Increment";
  138.             OpType=OperationType.RightOp;
  139.             Precedence=2;
  140.         }
  141.         public override ExpressionValue Execute (ExpressionValue left, ExpressionValue right)
  142.         {
  143.             var r=(MyValue)right;
  144.             var res=new MyValue();
  145.             res.Value=++r.Value;
  146.             return res;
  147.         }
  148.     }
  149.     class MinusOperation : Operation{
  150.         public MinusOperation(){
  151.             Name="Unary Minus";
  152.             OpType=OperationType.RightOp;
  153.             Precedence=2;
  154.         }
  155.         public override ExpressionValue Execute (ExpressionValue left, ExpressionValue right)
  156.         {
  157.             var r=(MyValue)right;
  158.             var res=new MyValue();
  159.             res.Value=-r.Value;
  160.             return res;
  161.         }
  162.     }
  163.    
  164.    
  165.    
  166. }
  167.  
  168.  
  169. SimplyExpress class code:
  170.  
  171.  
  172. /*
  173. <Copyright Header>
  174. Copyright (c) 2012 Jordan "Earlz/hckr83" Earls  <http://lastyearswishes.com>
  175. All rights reserved.
  176.  
  177. Redistribution and use in source and binary forms, with or without
  178. modification, are permitted provided that the following conditions
  179. are met:
  180.  
  181. 1. Redistributions of source code must retain the above copyright
  182.    notice, this list of conditions and the following disclaimer.
  183. 2. Redistributions in binary form must reproduce the above copyright
  184.    notice, this list of conditions and the following disclaimer in the
  185.    documentation and/or other materials provided with the distribution.
  186. 3. The name of the author may not be used to endorse or promote products
  187.    derived from this software without specific prior written permission.
  188.    
  189. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  190. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  191. AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
  192. THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  193. EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  194. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  195. OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  196. WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  197. OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  198. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  199.  
  200. </Copyright Header>
  201. */
  202. using System;
  203. using System.Collections.Generic;
  204. using System.Diagnostics;
  205.  
  206. namespace SimplyExpress
  207. {
  208.     public class SimplyExpress
  209.     {
  210.         List<Associativity> PrecedenceMap;
  211.         public SimplyExpress (List<Associativity> map)
  212.         {
  213.             PrecedenceMap=map;
  214.         }
  215.         protected List<Node> ParseToTree(List<ExpressionToken> tokens){
  216.             List<Node> tree=new List<Node>();
  217.             for(int i=0;i<tokens.Count;i++){
  218.                 var token=tokens[i];
  219.                 if(token.IsOperation){
  220.                     var op =new OperationNode();
  221.                     op.Op=token.Op;
  222.                     tree.Add(op);
  223.                 }else{
  224.                     var val=new ValueNode();
  225.                     val.Value=token.Value;
  226.                     tree.Add(val);
  227.                 }
  228.             }
  229.             //now hook up left and right
  230.             Node last=null;
  231.             for(int i=0;i<tree.Count;i++){
  232.                 var node=tree[i];
  233.                
  234.                 if(node is OperationNode){
  235.                     var op=node as OperationNode;
  236.                     if(last==null){
  237.                         if(op.Op.OpType==OperationType.LeftOp || op.Op.OpType==OperationType.LeftRightOp){
  238.                             throw new ApplicationException("parse error");
  239.                         }
  240.                     }
  241.                     if(op.Op.OpType==OperationType.LeftRightOp && last is OperationNode){
  242.                         //is this ok?
  243.                         //throw new ApplicationException("parse exception");
  244.                     }
  245.                     op.Left=last;
  246.                     if(last!=null){
  247.                         last.Right=op;
  248.                     }
  249.                 }else if(node is ValueNode){
  250.                     if(last!=null && last is ValueNode){
  251.                         throw new ApplicationException("parse error");
  252.                     }
  253.                     if(last !=null){
  254.                         var oplast=last as OperationNode;
  255.                         oplast.Right=node;
  256.                         node.Left=oplast;
  257.                     }
  258.                    
  259.                 }else{
  260.                     throw new NotSupportedException();
  261.                 }
  262.                 last=node;
  263.             }
  264.            
  265.             return tree;
  266.         }
  267.         public ExpressionValue Evaluate(List<ExpressionToken> tokens){
  268.             List<Node> tree=ParseToTree(tokens);
  269.             for(int i=0;i<PrecedenceMap.Count;i++){
  270.                 ReduceTree(i,ref tree);
  271.             }
  272.             if(tree.Count>1){
  273.                 throw new ApplicationException("Tree not completely reduced! more than 1 node");
  274.             }
  275.             Debug.Assert(tree.Count!=0);
  276.             return ((ValueNode)tree[0]).Value;
  277.         }
  278.         void ReduceTree(int precedence, ref List<Node> tree){
  279.             bool end=false;
  280.             int i;
  281.             if(PrecedenceMap[precedence]==Associativity.LeftToRight){
  282.                 i=0;   
  283.             }else{
  284.                 i=tree.Count-1;
  285.             }
  286.             while(!end){
  287.                 Node n=tree[i];
  288.                 if(n is OperationNode && ((OperationNode)n).Op.Precedence==precedence){
  289.                     OperationNode op=n as OperationNode;
  290.                     if(op.Op.OpType==OperationType.LeftOp){
  291.                         var temp=new ValueNode();
  292.                         if(op.Left==null || !(op.Left is ValueNode)){
  293.                             throw new ApplicationException("Parse error. No left value");
  294.                         }
  295.                         temp.Value=op.Op.Execute(((ValueNode)op.Left).Value, null);
  296.                         op.Right.Left=temp; //set to new result
  297.                         tree[i]=temp;
  298.                         if(i==0){
  299.                             throw new ApplicationException("syntax/parse error. no left value(internal)");
  300.                         }
  301.                         if(tree[i-1].Left!=null){
  302.                             tree[i-1].Left.Right=temp;
  303.                         }
  304.                         tree.RemoveAt(i-1);
  305.                     }else if(op.Op.OpType == OperationType.RightOp){
  306.                         var temp=new ValueNode();
  307.                         if(op.Right==null || !(op.Right is ValueNode)){
  308.                             throw new ApplicationException("Parse error. No right value");
  309.                         }
  310.                         temp.Value=op.Op.Execute(null,((ValueNode)op.Right).Value);
  311.                         if(op.Left!=null){
  312.                             op.Left.Right=temp;
  313.                         }
  314.                         tree[i]=temp;
  315.                         if(i==tree.Count){
  316.                             throw new ApplicationException("syntax/parse error. no right value(internal)");
  317.                         }
  318.                         if(tree[i+1].Right!=null){
  319.                             tree[i+1].Right.Left=temp;
  320.                         }
  321.                         tree.RemoveAt(i+1);
  322.                     }else if(op.Op.OpType == OperationType.LeftRightOp){
  323.                         var temp=new ValueNode();
  324.                         if(op.Right==null || !(op.Right is ValueNode)){
  325.                             throw new ApplicationException("Parse error. No right value");
  326.                         }
  327.                         if(op.Left==null || !(op.Left is ValueNode)){
  328.                             throw new ApplicationException("Parse error. No left value");
  329.                         }
  330.                         temp.Value=op.Op.Execute(((ValueNode)op.Left).Value,((ValueNode)op.Right).Value);
  331.                         if(op.Left.Left!=null){
  332.                             op.Left.Left.Right=temp;
  333.                         }
  334.                         if(op.Right.Right!=null){
  335.                             op.Right.Right.Left=temp;
  336.                         }
  337.                         if(i==0){
  338.                             throw new ApplicationException("syntax/parse error. no left value(internal)");
  339.                         }
  340.                         if(i==tree.Count){
  341.                             throw new ApplicationException("syntax/parse error. no right value(internal)");
  342.                         }
  343.                         tree[i]=temp;
  344.                         tree.RemoveAt(i+1);
  345.                         tree.RemoveAt(i-1);
  346.                     }else{
  347.                         throw new ApplicationException();
  348.                     }
  349.                        
  350.                        
  351.                 }
  352.                 if(PrecedenceMap[precedence]==Associativity.LeftToRight){
  353.                     i=i+1;
  354.                     if(i>=tree.Count){
  355.                         end=true;
  356.                     }
  357.                    
  358.                 }else{
  359.                     if(i<=0){
  360.                         end=true;
  361.                     }
  362.                     i=i-1;
  363.                 }
  364.             }
  365.            
  366.         }
  367.         protected class OperationNode : Node
  368.         {
  369.             public Operation Op;
  370.            
  371.         }
  372.         protected class Node{
  373.             public Node Left;
  374.             public Node Right;
  375.         }
  376.         protected class ValueNode : Node
  377.         {
  378.             public ExpressionValue Value;
  379.         }
  380.     }
  381.     public class ExpressionToken{
  382.         public bool IsOperation;
  383.         public ExpressionValue Value;
  384.         public Operation Op;
  385.     }
  386.     public enum OperationType{
  387.         Value,
  388.         LeftOp,
  389.         RightOp,
  390.         LeftRightOp
  391.     };
  392.     public enum Associativity{
  393.         RightToLeft,
  394.         LeftToRight
  395.     };
  396.     public abstract class Operation
  397.     {
  398.         public OperationType OpType;
  399.         public string Name;
  400.         public int Precedence; //lower precendences are executed first
  401.         public abstract ExpressionValue Execute(ExpressionValue left, ExpressionValue right);
  402.     }
  403.    
  404.  
  405.     public abstract class ExpressionValue
  406.     {
  407.     }
  408.    
  409.    
  410. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement