/// <summary> /// パース /// </summary> public void ParseOnlyValue() { var paser = new NakoParser(tokens); paser.ParseOnlyValue(); this.topNode = paser.topNode; }
private bool _minus_flag() { tok.MoveNext(); if (Accept(NakoTokenType.INT) || Accept(NakoTokenType.NUMBER)) { _const(); NakoNodeConst c = (NakoNodeConst)calcStack.Pop(); if (c.value is long) { c.value = ((long)(c.value) * -1); } else { c.value = ((double)(c.value) * -1); } calcStack.Push(c); lastNode = c; return(true); } NakoNodeCalc nc = new NakoNodeCalc(); nc.calc_type = CalcType.MUL; NakoNodeConst m1 = new NakoNodeConst(); m1.value = -1; m1.type = NakoNodeType.INT; NakoNode v = calcStack.Pop(); nc.nodeL = v; nc.nodeR = m1; calcStack.Push(nc); return(true); }
/// <summary> /// 状態をポップ /// </summary> protected void PopNodeState() { NakoParserNodeState s = stateStack.Pop(); this.lastNode = s.lastNode; this.parentNode = s.parentNode; }
private void _print(NakoNode node) { NakoNode v = node.Children[0]; Write_r(v); result.Add(new NakoILCode(NakoILType.PRINT, null)); }
/// <summary> /// 指定したリストを書く /// </summary> /// <param name="list"></param> protected void Write_list(NakoNodeList list) { for (int i = 0; i < list.Count; i++) { NakoNode node = list[i]; Write_r(node); } }
/// <summary> /// フレームの復元 /// </summary> protected void PopFrame() { NakoParserFrame f = frameStack.Pop(); lastNode = f.lastNode; parentNode = f.parentNode; localVar = f.localVar; }
/// <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; }
/// <summary> /// 中間コードを書き出す /// </summary> /// <param name="topNode"></param> public void Write(NakoNode topNode) { if (topNode != null) { this.topNode = topNode; } Write_r(this.topNode); FixLabel(); SetExceptionTables(); }
//> _callfunc : { [{_value}] FUNCTION_NAME } //> ; private bool _callfunc_stmt() { NakoToken startToken = tok.CurrentToken; TokenTry(); while (!tok.IsEOF()) { WriteLog(tok.CurrentToken.ToStringForDebug()); if (Accept(NakoTokenType.EOL)) { tok.MoveNext(); break; } if (!_value()) { TokenBack(); return(false); } } TokenFinally(); //TODO: _callfunc_stmt // 計算用スタックの管理 if (calcStack.Count > 0) { while (calcStack.Count > 0) { NakoNode n = calcStack.Shift(); if (!(n is NakoNodeCallFunction)) { // 余剰スタックの値を得る string r = ""; for (int i = 0; i < calcStack.Count; i++) { if (i != 0) { r += ","; } NakoNode n0 = calcStack[i]; r += n0.ToTypeString(); } throw new NakoParserException( "無効な式か値があります。(余剰スタックのチェック):" + r, startToken); } parentNode.AddChild(n); parentNode.AddChild(new NakoNodePop()); } } // ここで本来ならば // スタックを空にする or 余剰なスタックがあればエラーにするのが筋だが... // 連続関数呼び出しに対応するためエラーにしない return(true); }
/// <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> /// 値を1つだけ解析したい場合 /// </summary> /// <returns></returns> public bool ParseOnlyValue() { lastNode = null; if (tok.IsEOF()) { return(false); } if (!_value()) { return(false); } topNode.AddChild(lastNode); return(true); }
// 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; } } }
private void _let(NakoNodeLet node) { NakoNodeVariable varNode = node.VarNode; NakoNode valueNode = node.ValueNode; // 配列要素があるか確認 if (!varNode.useElement) { // + 要素なしの代入処理 // - 代入する値を書き込んで... Write_r(valueNode); // - セットする NakoILCode st = new NakoILCode(); st.value = varNode.varNo; st.type = (varNode.scope == NakoVariableScope.Global) ? NakoILType.ST_GLOBAL : NakoILType.ST_LOCAL; result.Add(st); } else // 配列要素があるとき { // + 配列への代入処理 // - 基本となる変数をセット NakoILCode ldvar = new NakoILCode(); ldvar.value = varNode.varNo; ldvar.type = (varNode.scope == NakoVariableScope.Global) ? NakoILType.LD_GLOBAL_REF : NakoILType.LD_LOCAL_REF; result.Add(ldvar); // - アクセス要素をセット int count = varNode.Children.Count; for (int i = 0; i < count; i++) { NakoNode n = varNode.Children[i]; Write_r(n); // ノードの値 if (i < count - 1) { result.Add(new NakoILCode(NakoILType.LD_ELEM_REF)); // 要素 } else { // 値ノード Write_r(valueNode); addNewILCode(NakoILType.ST_ELEM); } } } }
private bool _try_stmt() { if (!Accept(NakoTokenType.TRY)) { return(false); } tok.MoveNext(); // skip IF NakoNodeTry trynode = new NakoNodeTry(); NakoToken t = tok.CurrentToken; while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } // TRY trynode.nodeTry = _scope_or_statement(); while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } // CATCH //TODO ○○のエラーならば〜☆☆のエラーならば〜への対応 //TODO ○○や☆☆のエラーならばへの対応 while (Accept(NakoTokenType.CATCH)) { //TODO:catchの例外種別を取得 tok.MoveNext(); //skip catch while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } //while (calcStack.Count > 0) { // calcStack.Pop (); //} NakoNode nodeCatch = _scope_or_statement(); //TODO Add trynode.nodeCatch = nodeCatch; } //TODO set finally this.parentNode.AddChild(trynode); this.lastNode = trynode; return(true); }
// 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; } } }
//> _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); }
//> _scope_or_statement : _scope //> | _statement //> ; private NakoNode _scope_or_statement() { while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } this.PushNodeState(); NakoNode n = this.parentNode = this.lastNode = new NakoNode(); if (Accept(NakoTokenType.SCOPE_BEGIN)) { _scope(); } else { _statement(); } this.PopNodeState(); return(n); }
/// <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> /// constructor /// </summary> /// <param name="topNode"></param> public NakoILWriter(NakoNode topNode) { this.topNode = topNode; Init(); }