ArXen42

ArithmeticParserToTree

May 21st, 2016
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.01 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. namespace ArithmeticExpressionsTree
  6. {
  7.     public struct Operation
  8.     {
  9.         public Operation(String symbol, Int32 priority, Boolean isLeftAssociative,
  10.             Func<Double, Double, Double> calculationMethod)
  11.         {
  12.             Symbol = symbol;
  13.             Priority = priority;
  14.             IsLeftAssociative = isLeftAssociative;
  15.             CalculationMethod = calculationMethod;
  16.         }
  17.  
  18.         public readonly String Symbol;
  19.         public readonly Int32 Priority;
  20.         public readonly Boolean IsLeftAssociative;
  21.         public readonly Func<Double, Double, Double> CalculationMethod;
  22.     }
  23.  
  24.     internal static class Program
  25.     {
  26.         public static ArithmeticExpressionTree ParseExpression(String[] tokens)
  27.         {
  28.             var leveledTokens = new List<LeveledToken>();
  29.  
  30.             Int32 currentLevel = 0;
  31.             foreach (String token in tokens)
  32.             {
  33.                 if (IsOpeningBrace(token))
  34.                     currentLevel++;
  35.                 else if (IsClosingBrace(token))
  36.                     currentLevel--;
  37.                 else
  38.                     leveledTokens.Add(new LeveledToken(token, currentLevel));
  39.             }
  40.  
  41.             return ParseRecursvely(leveledTokens);
  42.         }
  43.  
  44.         private struct LeveledToken
  45.         {
  46.             public LeveledToken(String token, Int32 level)
  47.             {
  48.                 Token = token;
  49.                 Level = level;
  50.             }
  51.  
  52.             public readonly String Token;
  53.             public readonly Int32 Level;
  54.         }
  55.  
  56.         private static ArithmeticExpressionTree ParseRecursvely(List<LeveledToken> leveledTokens,
  57.             ArithmeticExpressionTree tree = null, Int32 parentNodeIndex = 0)
  58.         {
  59.             List<LeveledToken> operationsTokens = leveledTokens.FindAll(t => IsOperation(t.Token));
  60.             if (operationsTokens.Count == 0)
  61.             {
  62.                 if (tree == null)
  63.                     return new ArithmeticExpressionTree(leveledTokens[0].Token);
  64.                 else
  65.                 {
  66.                     tree.AddNode(parentNodeIndex, leveledTokens[0].Token);
  67.                     return tree;
  68.                 }
  69.             }
  70.  
  71.             Int32 lowestNestingLevel = operationsTokens.Min(t => t.Level);
  72.             Int32 lowestPriority =
  73.                 operationsTokens.FindAll(t => t.Level == lowestNestingLevel).Min(t => ArithmeticFunctions[t.Token].Priority);
  74.  
  75.             Int32 firstSuitableOperationIndex =
  76.                 leveledTokens.FindIndex(
  77.                     t =>
  78.                         (t.Level == lowestNestingLevel) && ArithmeticFunctions.ContainsKey(t.Token) &&
  79.                         (ArithmeticFunctions[t.Token].Priority == lowestPriority));
  80.  
  81.             List<LeveledToken> leftTokens = leveledTokens.GetRange(0, firstSuitableOperationIndex);
  82.             List<LeveledToken> rightTokens = leveledTokens.GetRange(firstSuitableOperationIndex + 1,
  83.                 leveledTokens.Count - firstSuitableOperationIndex - 1);
  84.  
  85.             Int32 newNodeIndex = 0;
  86.             if (tree == null)
  87.                 tree = new ArithmeticExpressionTree(leveledTokens[firstSuitableOperationIndex].Token);
  88.             else
  89.                 newNodeIndex = tree.AddNode(parentNodeIndex, leveledTokens[firstSuitableOperationIndex].Token);
  90.  
  91.             ParseRecursvely(leftTokens, tree, newNodeIndex);
  92.             ParseRecursvely(rightTokens, tree, newNodeIndex);
  93.  
  94.             return tree;
  95.         }
  96.  
  97.         private static readonly Dictionary<String, Operation> ArithmeticFunctions = new Dictionary<String, Operation>
  98.         {
  99.             {"+", new Operation("+", 0, true, (a, b) => a + b)},
  100.             {"-", new Operation("-", 0, true, (a, b) => a - b)},
  101.             {"*", new Operation("*", 1, true, (a, b) => a*b)},
  102.             {"/", new Operation("/", 1, true, (a, b) => a/b)},
  103.             {"^", new Operation("^", 2, false, Math.Pow)}
  104.         };
  105.  
  106.         public static void PrintTree(ArithmeticExpressionTree tree, Int32 nodeIndex, Int32 level = 1)
  107.         {
  108.             if (level == 1)
  109.                 Console.WriteLine(tree.Root.Value);
  110.  
  111.             foreach (Int32 childrenIndex in tree.GetAllChildrenIndexes(nodeIndex))
  112.             {
  113.                 Console.WriteLine(new String('  ', level) + tree.GetNode(childrenIndex).Value);
  114.                 PrintTree(tree, childrenIndex, level + 1);
  115.             }
  116.         }
  117.  
  118.         private static Boolean IsOperation(String lexem)
  119.         {
  120.             return ArithmeticFunctions.ContainsKey(lexem);
  121.         }
  122.  
  123.         private static Boolean IsOpeningBrace(String lexem)
  124.         {
  125.             return (lexem == "(");
  126.         }
  127.  
  128.         private static Boolean IsClosingBrace(String lexem)
  129.         {
  130.             return lexem == ")";
  131.         }
  132.  
  133.         private static void Main(String[] args)
  134.         {
  135.             PrintTree(
  136.                 ParseExpression(args[0].Split(' ')),
  137.                 0
  138.                 );
  139.         }
  140.     }
  141. }
Add Comment
Please, Sign In to add comment