private void BubblingProcessNode(SyntaxTreeNode node) { if (!node.HasNoChildren && node.Value is Nonterminal) { var nonterminal = node.Value as Nonterminal; if (nonterminal.Equals(MyNonterminals.FACTOR)) { if (node.ChildrenCount == 1 && node[0].Value is ConcreteTerminal) // F -> const { node.Value[LEXVAL_KEY] = ((ConcreteTerminal)node[0].Value).Token.Value; } else if (node.ChildrenCount == 3) // F -> ( E ) { node.Value[VAR_KEY] = node[1].Value[VAR_KEY]; } else if (node.ChildrenCount == 1 && node[0].Value is Nonterminal) // F -> FUNC_CALL { node.Value[VAR_KEY] = node[0].Value[VAR_KEY]; } } else if (nonterminal.Equals(MyNonterminals.TERM) || nonterminal.Equals(MyNonterminals.EXPRESSION)) { // T -> F T' // E -> T E' if (node[1].HasNoChildren) { if (node[0].Value[VAR_KEY] != null) { nonterminal[VAR_KEY] = node[0].Value[VAR_KEY]; } else { nonterminal[LEXVAL_KEY] = node[0].Value[LEXVAL_KEY]; } } else { nonterminal[VAR_KEY] = GetLexvalOrVarOperand(node[1]); // T' or E' } } else if (nonterminal.Equals(MyNonterminals.EXPRESSION_DASH) || nonterminal.Equals(MyNonterminals.TERM_DASH)) { // E' -> +- T E' // T' -> */ F T' Operand resultVar = _code.Helper.GetTempVariable(); Operand arg1 = GetLexvalOrVarOperand(node.LeftNode()); // T for E', F for T' Operand arg2 = node[2].HasNoChildren ? GetLexvalOrVarOperand(node[1]) : GetLexvalOrVarOperand(node[2]); nonterminal[VAR_KEY] = resultVar; OpCode opCode; if (node[0].Value.IsTerminalWithValue("+")) { opCode = OpCode.ADD; } else if (node[0].Value.IsTerminalWithValue("-")) { opCode = OpCode.SUB; } else if (node[0].Value.IsTerminalWithValue("*")) { opCode = OpCode.MULT; } else if (node[0].Value.IsTerminalWithValue("/")) { opCode = OpCode.DIV; } else { throw new Exception("Unknown operator"); } _code.Emit(new Instruction(opCode, arg1, arg2, resultVar)); } else if (nonterminal.Equals(MyNonterminals.PARAM)) { Operand param = GetLexvalOrVarOperand(node[0]); _code.Emit(new Instruction(OpCode.PARAM, param, null, null)); } else if (nonterminal.Equals(MyNonterminals.FUNCTION_CALL)) { Operand resultVar = _code.Helper.GetTempVariable(); Operand funcName = new Operand(((ConcreteTerminal)node[0].Value).Token.Value); nonterminal[VAR_KEY] = resultVar; _code.Emit(new Instruction(OpCode.CALL, funcName, null, resultVar)); } else if (nonterminal.Equals(MyNonterminals.ASSIGN_STATEMENT)) { int idChildNum = node.ChildrenCount == 3 ? 0 : 1; Operand resultVar = new Operand((node[idChildNum].Value as ConcreteTerminal).Token.Value); Operand value = GetLexvalOrVarOperand(node[MyNonterminals.EXPRESSION]); _code.Emit(new Instruction(OpCode.ASGN, value, null, resultVar)); } else if (nonterminal.Equals(MyNonterminals.THEN_BLOCK) || nonterminal.Equals(MyNonterminals.ELSE_BLOCK)) { var ifEndLabel = node.Parent.Value[IF_END_LABEL_KEY] as Operand; _code.Emit(new Instruction(OpCode.JMP, ifEndLabel, null, null)); } else if (nonterminal.Equals(MyNonterminals.IF_STATEMENT)) { var bool_expression = node[MyNonterminals.IF_BLOCK][MyNonterminals.BOOL_EXPRESSION]; Operand thenBlockLabel = node[MyNonterminals.THEN_BLOCK].Value[LABEL_KEY] as Operand; Operand elseBlockLabel = null; if (!node[MyNonterminals.ELSE_BLOCK].HasNoChildren) { elseBlockLabel = node[MyNonterminals.ELSE_BLOCK].Value[LABEL_KEY] as Operand; } Operand leftBoolPart = GetLexvalOrVarOperand(bool_expression[0]); Operand rightBoolPart = GetLexvalOrVarOperand(bool_expression[2]); OpCode opCode; if (bool_expression[1].Value.IsTerminalWithValue(">")) { opCode = OpCode.JGT; } else if (bool_expression[1].Value.IsTerminalWithValue("<")) { opCode = OpCode.JLT; } else if (bool_expression[1].Value.IsTerminalWithValue(">=")) { opCode = OpCode.JGE; } else if (bool_expression[1].Value.IsTerminalWithValue("<=")) { opCode = OpCode.JLE; } else if (bool_expression[1].Value.IsTerminalWithValue("==")) { opCode = OpCode.JEQ; } else if (bool_expression[1].Value.IsTerminalWithValue("!=")) { opCode = OpCode.JNEQ; } else { throw new Exception("Unknown boolean operator"); } _code.Emit(new Instruction(OpCode.LTRGT, node.Value[IF_BEGIN_LABEL_KEY] as Operand, null, null)); _code.Emit(new Instruction(opCode, leftBoolPart, rightBoolPart, thenBlockLabel)); if (elseBlockLabel != null) { _code.Emit(new Instruction(OpCode.JMP, elseBlockLabel, null, null)); } _code.Emit(new Instruction(OpCode.LTRGT, node.Value[IF_END_LABEL_KEY] as Operand, null, null)); } } }