/// <summary> /// 子ノードを追加 /// </summary> /// <param name="child"></param> public void AddChild(NakoNode child) { if (children == null) { children = new NakoNodeList(); } children.Add(child); }
/// <summary> /// コンストラクタ /// </summary> /// <param name="tokens"></param> public NakoParserBase(NakoTokenList tokens) { this.tok = tokens; tokens.MoveTop(); parentNode = topNode = new NakoNode(); frameStack = new Stack<NakoParserFrame>(); stateStack = new Stack<NakoParserNodeState>(); calcStack = new NakoNodeList(); calcStackCounters = new Stack<int>(); lastNode = null; localVar = new NakoVariableManager(NakoVariableScope.Local); }
/// <summary> /// 状態をポップ /// </summary> protected void PopNodeState() { NakoParserNodeState s = stateStack.Pop(); this.lastNode = s.lastNode; this.parentNode = s.parentNode; }
/// <summary> /// フレームの復元 /// </summary> protected void PopFrame() { NakoParserFrame f = frameStack.Pop(); lastNode = f.lastNode; parentNode = f.parentNode; localVar = f.localVar; }
/// <summary> /// 値を1つだけ解析したい場合 /// </summary> /// <returns></returns> public bool ParseOnlyValue() { lastNode = null; if (tok.IsEOF()) return false; if (!_value()) return false; topNode.AddChild(lastNode); return true; }
/// <summary> /// パース /// </summary> public void ParseOnlyValue() { var paser = new NakoParser(tokens); paser.ParseOnlyValue(); this.topNode = paser.topNode; }
/// <summary> /// トークンの分割が行われた Tokens に対して、構文解析を行う /// 結果は TopNode に得られる /// </summary> public void Parse() { NakoParser parser = new NakoParser(tokens); parser.DebugMode = this.DebugMode; parser.globalVar = this.GlobalVar; parser.Parse(); this.topNode = parser.topNode; }
private void _print(NakoNode node) { NakoNode v = node.Children[0]; Write_r(v); result.Add(new NakoILCode(NakoILType.PRINT, null)); }
// BREAK/CONTINUE文を解決する private void _loop_check_break_continue(NakoNode block, NakoILCode break_label, NakoILCode continue_label) { if (block == null) return; if (!block.hasChildren()) return; for (int i = 0; i < block.Children.Count; i++) { NakoNode item = block.Children[i]; switch (item.type) { case NakoNodeType.BREAK: item.type = NakoNodeType.JUMP; ((NakoNodeBreak)item).label = break_label; break; case NakoNodeType.CONTINUE: item.type = NakoNodeType.JUMP; ((NakoNodeContinue)item).label = continue_label; break; // ジャンプポイントが変わる構文があれば、その下層ブロックは処理しない case NakoNodeType.FOR: break; case NakoNodeType.WHILE: break; case NakoNodeType.REPEAT_TIMES: break; case NakoNodeType.FOREACH: break; case NakoNodeType.IF: NakoNodeIf ifnode = (NakoNodeIf)item; _loop_check_break_continue(ifnode.nodeTrue, break_label, continue_label); _loop_check_break_continue(ifnode.nodeFalse, break_label, continue_label); break; default: if (item.hasChildren()) { _loop_check_break_continue(item, break_label, continue_label); } break; } } }
// RETURN文を解決する private void _func_check_return(NakoNode block, NakoILCode return_label) { if (block == null) return; if (!block.hasChildren()) return; for (int i = 0; i < block.Children.Count; i++) { NakoNode item = block.Children[i]; switch (item.type) { case NakoNodeType.RETURN: item.type = NakoNodeType.JUMP; ((NakoNodeReturn)item).label = return_label; break; // ジャンプポイントが変わる構文があれば、その下層ブロックは処理しない case NakoNodeType.FOR: break; case NakoNodeType.WHILE: break; case NakoNodeType.REPEAT_TIMES: break; case NakoNodeType.FOREACH: break; case NakoNodeType.IF: NakoNodeIf ifnode = (NakoNodeIf)item; _func_check_return(ifnode.nodeTrue, return_label); _func_check_return(ifnode.nodeFalse, return_label); break; default: if (item.hasChildren()) { _func_check_return(item, return_label); } break; } } }
/// <summary> /// constructor /// </summary> /// <param name="topNode"></param> public NakoILWriter(NakoNode topNode) { this.topNode = topNode; Init(); }
/// <summary> /// 中間コードを書き出す /// </summary> /// <param name="node"></param> protected void Write_r(NakoNode node) { if (node == null) return; switch (node.type) { case NakoNodeType.NOP: result.Add(NakoILCode.newNop()); break; case NakoNodeType.CALC: newCalc((NakoNodeCalc)node); return; case NakoNodeType.INT: result.Add(new NakoILCode(NakoILType.LD_CONST_INT, node.value)); return; case NakoNodeType.NUMBER: result.Add(new NakoILCode(NakoILType.LD_CONST_REAL, node.value)); return; case NakoNodeType.STRING: result.Add(new NakoILCode(NakoILType.LD_CONST_STR, node.value)); return; case NakoNodeType.POP: result.Add(new NakoILCode(NakoILType.POP)); return; case NakoNodeType.PRINT: _print(node); return; case NakoNodeType.ST_VARIABLE: _setVariable((NakoNodeVariable)node); return; case NakoNodeType.LET: _let((NakoNodeLet)node); return; case NakoNodeType.LD_VARIABLE: _getVariable((NakoNodeVariable)node); return; case NakoNodeType.IF: _if((NakoNodeIf)node); return; case NakoNodeType.WHILE: _while((NakoNodeWhile)node); return; case NakoNodeType.FOR: _for((NakoNodeFor)node); return; case NakoNodeType.BREAK: addNewILCode(NakoILType.NOP, "BREAK"); return; case NakoNodeType.CONTINUE: addNewILCode(NakoILType.NOP, "CONTINUE"); return; case NakoNodeType.RETURN: addNewILCode(NakoILType.NOP, "RETURN"); return; case NakoNodeType.REPEAT_TIMES: _repeat_times((NakoNodeRepeatTimes)node); return; case NakoNodeType.FOREACH: _foreachUseIterator((NakoNodeForeach)node); //_foreach((NakoNodeForeach)node); return; case NakoNodeType.CALL_FUNCTION: _call_function((NakoNodeCallFunction)node); return; case NakoNodeType.DEF_FUNCTION: _def_function((NakoNodeDefFunction)node); return; case NakoNodeType.JUMP: _jump((NakoNodeJump)node); return; //TODO case NakoNodeType.LET_VALUE: addNewILCode(NakoILType.NOP, "LET_VALUE"); break; case NakoNodeType.TRY: _try((NakoNodeTry)node); return; case NakoNodeType.THROW: _throw((NakoNodeThrow)node); return; default: throw new NakoCompilerException("未定義のノードタイプ: " + node.type.ToString()); } // --- if (!node.hasChildren()) return; Write_list(node.Children); }
/// <summary> /// 中間コードを書き出す /// </summary> /// <param name="topNode"></param> public void Write(NakoNode topNode) { if (topNode != null) { this.topNode = topNode; } Write_r(this.topNode); FixLabel(); SetExceptionTables (); }
//> _print : PRINT _value private bool _print() { if (tok.CurrentTokenType != NakoTokenType.PRINT) { return false; } NakoNode n = new NakoNode(); n.Token = tok.CurrentToken; tok.MoveNext(); if (!_value()) { throw new NakoParserException("PRINT の後に値がありません。", n.Token); } n.type = NakoNodeType.PRINT; n.AddChild(calcStack.Pop()); lastNode = n; this.parentNode.AddChild(n); return true; }