Advertisement
haqon

BZ Expression Parser

Jun 14th, 2019
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.16 KB | None | 0 0
  1.        //в этом списке будут лежать все арифметические выражения в матричном виде. одна строка на одно выражение.
  2.         public List<string> ExpMatrix { get; }
  3.  
  4.         private readonly Stack<ExpOperand> _operands;
  5.         private readonly Stack<Node> _operators;
  6.         private int _currentRuleId;
  7.  
  8. ......
  9.  
  10.        /// <summary>
  11.         /// Выполянет разбор афирметичскеого выражения.
  12.         /// </summary>
  13.         private void ParseExpression()
  14.         {
  15.             _currentRuleId = 1;
  16.  
  17.             _operators.Clear();
  18.             _operands.Clear();
  19.  
  20.             while (true)
  21.             {
  22.                 var inputToken = _currentToken;
  23.  
  24.                 if (IsOperand(inputToken)) AddNode();
  25.                 else
  26.                 {
  27.                     var currentOperation = _operators.Count > 0 ? _operators.Peek().Name : null;
  28.  
  29.                     if (!IsOperator(inputToken))
  30.                     {
  31.                         switch (currentOperation)
  32.                         {
  33.                             case null:
  34.                                 if (_operands.Count == 1)
  35.                                 {
  36.                                     var mainNode = _operands.Pop();
  37.                                     ExpMatrix.Add(mainNode.BuildMatrix());
  38.                                     _holder.Push(new Node(){Name = "Expression", Type = Type.Expression});
  39.                                     return;
  40.                                 }
  41.                                 else ThrowExpressionError("Ошибка в выражении.");
  42.                                 break;
  43.  
  44.                             case "(":
  45.                                 ThrowExpressionError("Не хватает закрывающей скобки.");
  46.                                 break;
  47.                             case "-":
  48.                             case "+":
  49.                             case "*":
  50.                             case "/":
  51.                                 ActionD4();
  52.                                 break;
  53.                         }
  54.                     }
  55.                     else
  56.                     {
  57.                         switch (inputToken.Name)
  58.                         {
  59.                             case "(":
  60.                                 ActionD1();
  61.                                 break;
  62.  
  63.                             case "-":
  64.                             case "+":
  65.  
  66.                                 switch (currentOperation)
  67.                                 {
  68.                                     case null:
  69.                                     case "(":
  70.                                         ActionD1();
  71.                                         break;
  72.  
  73.                                     case "+":
  74.                                     case "-":
  75.                                         ActionD2();
  76.                                         break;
  77.  
  78.                                     case "*":
  79.                                     case "/":
  80.                                         ActionD4();
  81.                                         break;
  82.                                 }
  83.                                 break;
  84.  
  85.                             case "*":
  86.                             case "/":
  87.  
  88.                                 switch (currentOperation)
  89.                                 {
  90.                                     case null:
  91.                                     case "(":
  92.                                     case "+":
  93.                                     case "-":
  94.                                         ActionD1();
  95.                                         break;
  96.                                     case "*":
  97.                                     case "/":
  98.                                         ActionD2();
  99.                                         break;
  100.                                 }
  101.                                 break;
  102.  
  103.                             case ")":
  104.                                 switch (currentOperation)
  105.                                 {
  106.                                     case null:
  107.                                         ThrowExpressionError("Не хватает открывающей скобки.");
  108.                                         break;
  109.  
  110.                                     case "(":
  111.                                         ActionD3();
  112.                                         break;
  113.  
  114.                                     case "+":
  115.                                     case "-":
  116.                                     case "*":
  117.                                     case "/":
  118.                                         ActionD4();
  119.                                         break;
  120.                                 }
  121.                                 break;
  122.                         }
  123.                     }
  124.                 }
  125.             }
  126.  
  127.  
  128.         }
  129.  
  130.         private void ActionD1()
  131.         {
  132.             _operators.Push(_currentToken);
  133.             ReadNext();
  134.         }
  135.  
  136.         private void ActionD2()
  137.         {
  138.             var op1 = _operators.Pop();
  139.             MakeNode(op1);
  140.  
  141.             _operators.Push(_currentToken);
  142.             ReadNext();
  143.         }
  144.  
  145.         private void ActionD3()
  146.         {
  147.             _operators.Pop();
  148.             ReadNext();
  149.         }
  150.  
  151.         private void ActionD4()
  152.         {
  153.             var op1 = _operators.Pop();
  154.             MakeNode(op1);
  155.         }
  156.  
  157.         /// <summary>
  158.         /// Создаёт новый узел на основе указанного оператора, а также двух первых операндов на вершине стека.
  159.         /// </summary>
  160.         /// <param name="oper"></param>
  161.         private void MakeNode(Node oper)
  162.         {
  163.             if (_operands.Count < 2) ThrowExpressionError("Пропущены операнды.");
  164.             var right = _operands.Pop();
  165.             var left = _operands.Pop();
  166.  
  167.             var n = new ExpOperand(oper, left, right, $"M{_currentRuleId++}");
  168.             _operands.Push(n);
  169.         }
  170.  
  171.         /// <summary>
  172.         /// Создаёт новый узел на основе текущего токена.
  173.         /// </summary>
  174.         private void AddNode()
  175.         {
  176.             var cur = _currentToken;
  177.  
  178.             Debug.Assert(IsOperand(cur));
  179.  
  180.             var node = new ExpOperand(cur, null, null);
  181.             _operands.Push(node);
  182.  
  183.             ReadNext();
  184.         }
  185.  
  186.         /// <summary>
  187.         /// Проверяет, являеся ли указанный токен операндом.
  188.         /// </summary>
  189.         /// <param name="token"></param>
  190.         /// <returns></returns>
  191.         private static bool IsOperand(Node token)
  192.         {
  193.             switch (token.Type)
  194.             {
  195.                 case Type.Literal:
  196.                 case Type.Identifier:
  197.                     return true;
  198.                 default:
  199.                     return false;
  200.             }
  201.         }
  202.  
  203.         /// <summary>
  204.         /// Проверяет, является ли указанный токен оператором.
  205.         /// </summary>
  206.         /// <param name="t"></param>
  207.         /// <returns></returns>
  208.         public static bool IsOperator(Node t)
  209.         {
  210.             switch (t.Name)
  211.             {
  212.                 case "-":
  213.                 case "+":
  214.                 case "/":
  215.                 case "(":
  216.                 case ")":
  217.                 case "*":
  218.                     return true;
  219.  
  220.                 default:
  221.                     return false;
  222.             }
  223.         }
  224.  
  225.         /// <summary>
  226.         /// Проверяет, является ли токен оператором или операндом.
  227.         /// </summary>
  228.         /// <param name="t"></param>
  229.         /// <returns></returns>
  230.         public static bool IsExpression(Node t) => IsOperand(t) || IsOperator(t);
  231.  
  232.         private static void ThrowExpressionError(string desc)
  233.         {
  234.             throw new Exception("Ошибка в арифметическом выражении!\n" +
  235.                                 $"Описание: {desc}");
  236.         }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement