//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); }