//> _callfunc : FUNCTION_NAME //> | FUNCTION_NAME _arglist //> ; private bool _callfunc() { NakoToken t = tok.CurrentToken; if (!Accept(NakoTokenType.FUNCTION_NAME)) { return false; } tok.MoveNext(); // skip FUNCTION_NAME string fname = t.GetValueAsName(); NakoVariable var = globalVar.GetVar(fname); if (var == null) { throw new NakoParserException("関数『" + fname + "』が見あたりません。", t); } // NakoNodeCallFunction callNode = new NakoNodeCallFunction(); NakoFunc func = null; callNode.Token = t; if (var.Type == NakoVarType.SystemFunc) { int funcNo = (int)var.Body; func = NakoAPIFuncBank.Instance.FuncList[funcNo]; callNode.func = func; } else { NakoNodeDefFunction defNode = (NakoNodeDefFunction)var.Body; func = callNode.func = defNode.func; callNode.value = defNode; } // --------------------------------- if (Accept(NakoTokenType.PARENTHESES_L)) { _arglist(callNode); // TODO ここで引数の数をチェックする処理 } // 引数の数だけノードを取得 for (int i = 0; i < func.ArgCount; i++) { NakoFuncArg arg = func.args[func.ArgCount - i - 1]; NakoNode argNode; if (arg.defaultValue != null && calcStack.Count < (func.ArgCount - i)) {//初期値があって引数が無い場合に引数に初期値を与える argNode = new NakoNodeConst(); argNode.value = arg.defaultValue; if (arg.defaultValue is int) { argNode.type = NakoNodeType.INT; argNode.Token = new NakoToken (NakoTokenType.INT); } else if (arg.defaultValue is string) { argNode.type = NakoNodeType.STRING; argNode.Token = new NakoToken (NakoTokenType.STRING); } } else { argNode = calcStack.Pop (arg); } if (arg.varBy == VarByType.ByRef) { if (argNode.type == NakoNodeType.LD_VARIABLE) { ((NakoNodeVariable)argNode).varBy = VarByType.ByRef; } } callNode.AddChild(argNode); } // --------------------------------- // 計算スタックに関数の呼び出しを追加 calcStack.Push(callNode); this.lastNode = callNode; return true; }
private void _call_function(NakoNodeCallFunction node) { // push args values if (node.argNodes != null) { for (int i = 0; i < node.argNodes.Count; i++) { Write_r(node.argNodes[i]); } } NakoILCode code = new NakoILCode(); if (node.func.funcType == Function.NakoFuncType.SysCall) { // NakoAPIFunc f = (NakoAPIFunc)node.func; code.type = NakoILType.SYSCALL; code.value = node.func.varNo; result.Add(code); } else // UserCall { NakoILCode defLabel = ((NakoNodeDefFunction)node.value).defLabel; code.type = NakoILType.USRCALL; code.value = defLabel; if (code.value == null) { //一旦ラベルを設定出来なかったユーザー関数には定義のオブジェクトそのものを入れて、FixLabel内で設定しなおす code.value = node.value; } result.Add(code); } }
//> _arglist : '(' { _value } ')' //> ; private bool _arglist(NakoNodeCallFunction node) { NakoToken firstT = tok.CurrentToken; int nest = 0; // '(' から始まるかチェック if (!Accept(NakoTokenType.PARENTHESES_L)) { return false; } tok.MoveNext(); // skip '(' nest++; // '(' .. ')' の間を取りだして別トークンとする NakoTokenList par_list = new NakoTokenList(); while (!tok.IsEOF()) { if (Accept(NakoTokenType.PARENTHESES_R)) { nest--; if (nest == 0) { tok.MoveNext(); break; } } else if (Accept(NakoTokenType.PARENTHESES_L)) { nest++; } par_list.Add(tok.CurrentToken); tok.MoveNext(); } // 現在のトークン位置を保存 tok.Save(); NakoTokenList tmp_list = tok; tok = par_list; tok.MoveTop(); while (!tok.IsEOF()) { if (!_value()) { throw new NakoParserException("関数の引数の配置エラー。", firstT); } } // トークンリストを復元 tok = tmp_list; tok.Restore(); return true; }