Exemple #1
0
        //public const byte ConnectCharDosCode = 0xB3,
        //MiddleNodeCharDosCode = 0xC3,
        //LastNodeCharDosCode = 0xC0;

        //static AstNodePrinter()
        //{
        //    Encoding dosEncoding = null;
        //    try
        //    {
        //        dosEncoding = Encoding.GetEncoding("cp866");
        //    }
        //    catch { }
        //    if (dosEncoding != null)
        //    {
        //        ConnectChar = dosEncoding.GetChars(
        //        new byte[] { ConnectCharDosCode })[0];
        //        MiddleNodeChar = dosEncoding.GetChars(
        //        new byte[] { MiddleNodeCharDosCode })[0];
        //        LastNodeChar = dosEncoding.GetChars(
        //        new byte[] { LastNodeCharDosCode })[0];
        //    }
        //}

        private static string GetStringSubTree(AstNode node, string indent, bool root)
        {
            if (node == null)
            {
                return("");
            }
            string result = indent;

            if (!root)
            {
                if (node.Index < node.Parent.ChildCount - 1)
                {
                    result += MiddleNodeChar + " ";
                    indent += ConnectChar + " ";
                }
                else
                {
                    result += LastNodeChar + " ";
                    indent += " ";
                }
            }
            result += node + "\n";
            for (int i = 0; i < node.ChildCount; i++)
            {
                result += GetStringSubTree(node.GetChild(i), indent, false);
            }
            return(result);
        }
    private static string getStringSubTree(AstNode node, string indent, bool root) {
      if (node == null)
        return "";

      string result = indent;
      if (!root)
        if(node.Index < node.Parent.ChildCount - 1) {
          result += MiddleNodeChar + " ";
          indent += ConnectChar + " ";
        }
        else {
          result += LastNodeChar + " ";
          indent += "  ";
        }
      result += node + "\n";
      for(int i = 0; i < node.ChildCount; i++)
        result += getStringSubTree(node.GetChild(i), indent, false);

      return result;
    }
        // рекурсивный метод, который вызывается для каждого узла дерева
        private string GenerateNode(AstNode node, int lvl, string s)
        {
            switch (node.Type)
            {
            case AstNodeType.UNKNOWN:
                throw new IntepreterException("Неопределенный тип узла AST-дерева");

            case AstNodeType.NUMBER:
                return("LOAD =" + node.Text);

            case AstNodeType.IDENT:
                return("LOAD " + node.Text);

            case AstNodeType.TRUE:
                return("LOAD  " + 1);

            case AstNodeType.FALSE:
                return("LOAD " + 0);

            case AstNodeType.ADD:
                return(GenerateNode(node.GetChild(1), lvl, s) + Environment.NewLine + "STORE ~" + (++lvl).ToString() + Environment.NewLine + GenerateNode(node.GetChild(0), lvl, s) + Environment.NewLine + "ADD ~" + (lvl--).ToString());

            case AstNodeType.SUB:
                return(GenerateNode(node.GetChild(1), lvl, s) + Environment.NewLine + "STORE ~" + (++lvl).ToString() + Environment.NewLine + GenerateNode(node.GetChild(0), lvl, s) + Environment.NewLine + "SUB ~" + (lvl--).ToString());

            case AstNodeType.MPY:
                return(GenerateNode(node.GetChild(1), lvl, s) + Environment.NewLine + "STORE ~" + (++lvl).ToString() + Environment.NewLine + GenerateNode(node.GetChild(0), lvl, s) + Environment.NewLine + "MPY ~" + (lvl--).ToString());

            case AstNodeType.DIV:
                return(GenerateNode(node.GetChild(1), lvl, s) + Environment.NewLine + "STORE ~" + (++lvl).ToString() + Environment.NewLine + GenerateNode(node.GetChild(0), lvl, s) + Environment.NewLine + "DIV ~" + (lvl--).ToString());

            case AstNodeType.ASSIGN:
                return(GenerateNode(node.GetChild(1), lvl, s) + Environment.NewLine + "STORE " + node.GetChild(0).Text + Environment.NewLine + Environment.NewLine);

            case AstNodeType.BLOCK:
            case AstNodeType.PROGRAM:
                for (int i = 0; i < node.ChildCount; i++)
                {
                    s += GenerateNode(node.GetChild(i), lvl, s);
                }
                return(s);

            default:
                throw new IntepreterException("Неизвестный тип узла AST-дерева");
            }
        }
    private double ExecuteNode(AstNode node) {
      switch (node.Type) {
        case AstNodeType.UNKNOWN:
          throw new IntepreterException("Неопределенный тип узла AST-дерева");

        case AstNodeType.NUMBER:
          return double.Parse(node.Text, NFI);

        case AstNodeType.IDENT:
          if (varTable.ContainsKey(node.Text))
            return varTable[node.Text];
          else
            throw new ParserBaseException(string.Format("Значение {0} не определено", node.Text));

        case AstNodeType.ADD:
          return ExecuteNode(node.GetChild(0)) + ExecuteNode(node.GetChild(1));

        case AstNodeType.SUB:
          return ExecuteNode(node.GetChild(0)) - ExecuteNode(node.GetChild(1));

        case AstNodeType.MUL:
          return ExecuteNode(node.GetChild(0)) * ExecuteNode(node.GetChild(1));

        case AstNodeType.DIV:
          return ExecuteNode(node.GetChild(0)) / ExecuteNode(node.GetChild(1));

        case AstNodeType.ASSIGN:
          varTable[node.GetChild(0).Text] = ExecuteNode(node.GetChild(1));
          break;

        case AstNodeType.INPUT:
          Console.Write("input {0}: ", node.GetChild(0).Text);
          varTable[node.GetChild(0).Text] = double.Parse(Console.ReadLine(), NFI);
          break;

        case AstNodeType.PRINT:
          Console.WriteLine(ExecuteNode(node.GetChild(0)).ToString(NFI));
          break;

        case AstNodeType.IF:
          if (double.Parse(ExecuteNode(node.GetChild(0)).ToString(NFI)) > 0
              || double.Parse(ExecuteNode(node.GetChild(0)).ToString(NFI)) < 0)
          {
              Console.WriteLine(ExecuteNode(node.GetChild(1)).ToString(NFI));
          }
          else if (double.Parse(ExecuteNode(node.GetChild(0)).ToString(NFI)) == 0)
          {
              Console.WriteLine(ExecuteNode(node.GetChild(2)).ToString(NFI));
          }
          break;
        
        
        case AstNodeType.WHILE:
          if (double.Parse(ExecuteNode(node.GetChild(0)).ToString(NFI)) > 0
              || double.Parse(ExecuteNode(node.GetChild(0)).ToString(NFI)) < 0)
          {
              Console.WriteLine(ExecuteNode(node.GetChild(1)).ToString(NFI));
          }
         
          break;
       
        case AstNodeType.BLOCK:
        case AstNodeType.PROGRAM:
          for (int i = 0; i < node.ChildCount; i++)
            ExecuteNode(node.GetChild(i));
          break;
        /*
        default:
          throw new IntepreterException("Неизвестный тип узла AST-дерева");
        */
      }

      return 0;
    }
        // рекурсивный метод, который вызывается для каждого узла дерева
        private double ExecuteNode(AstNode node)
        {
            switch (node.Type)
            {
            case AstNodeType.UNKNOWN:
                throw new IntepreterException(
                          "Неопределенный тип узла AST-дерева");

            case AstNodeType.NUMBER:
                return(double.Parse(node.Text, NFI));

            case AstNodeType.IDENT:
                if (varTable.ContainsKey(node.Text))
                {
                    return(varTable[node.Text]);
                }
                else
                {
                    throw new ParserBaseException(string.Format(
                                                      "Значение {0} не определено", node.Text));
                }

            case AstNodeType.ADD:
                return(ExecuteNode(node.GetChild(0)) + ExecuteNode(node.GetChild(1)));

            case AstNodeType.SUB:
                return(ExecuteNode(node.GetChild(0)) - ExecuteNode(node.GetChild(1)));

            case AstNodeType.MUL:
                return(ExecuteNode(node.GetChild(0)) * ExecuteNode(node.GetChild(1)));

            case AstNodeType.DIV:
                return(ExecuteNode(node.GetChild(0)) / ExecuteNode(node.GetChild(1)));

            case AstNodeType.ASSIGN:
                varTable[node.GetChild(0).Text] = ExecuteNode(node.GetChild(1));
                break;

            case AstNodeType.INPUT:
                Console.Write("input {0}: ", node.GetChild(0).Text);
                varTable[node.GetChild(0).Text] = double.Parse(Console.ReadLine(), NFI);
                break;

            case AstNodeType.PRINT:
                Console.WriteLine(ExecuteNode(node.GetChild(0)).ToString(NFI));
                break;

            case AstNodeType.BLOCK:
            case AstNodeType.PROGRAM:
                for (int i = 0; i < node.ChildCount; i++)
                {
                    ExecuteNode(node.GetChild(i));
                }
                break;

            default:
                throw new IntepreterException("Неизвестный тип узла AST-дерева");
            }
            return(0);
        }