private void _if(NakoNodeIf node) { int labelId = GetLableId(); // (1) 条件文をコードにする Write_r(node.nodeCond); // (2) コードの結果により分岐する // 分岐先をラベルとして作成 NakoILCode label_endif = createLABEL("ENDIF" + labelId.ToString()); NakoILCode label_else = createLABEL("ELSE" + labelId.ToString()); result.Add(new NakoILCode(NakoILType.BRANCH_FALSE, label_else)); // (3) TRUE if (node.nodeTrue != null) { Write_r(node.nodeTrue); result.Add(createJUMP(label_endif)); } // (4) FALSE result.Add(label_else); if (node.nodeFalse != null) { Write_r(node.nodeFalse); } result.Add(label_endif); }
// 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; } } }
//> _if_stmt : IF _value THEN [EOL] _scope_or_statement [ ELSE _scope_or_statement ] //> ; private bool _if_stmt() { if (!Accept(NakoTokenType.IF)) { return(false); } tok.MoveNext(); // skip IF NakoNodeIf ifnode = new NakoNodeIf(); // _value NakoToken t = tok.CurrentToken; if (!_value()) { throw new NakoParserException("もし文で比較式がありません。", t); } ifnode.nodeCond = calcStack.Pop(); // THEN (日本語では、助詞なのでたぶんないはずだが...) if (Accept(NakoTokenType.THEN)) { tok.MoveNext(); } while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } // TRUE ifnode.nodeTrue = _scope_or_statement(); while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } // FALSE if (Accept(NakoTokenType.ELSE)) { tok.MoveNext(); // skip ELSE while (Accept(NakoTokenType.EOL)) { tok.MoveNext(); } ifnode.nodeFalse = _scope_or_statement(); } this.parentNode.AddChild(ifnode); this.lastNode = ifnode; 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; } } }