//> _def_function_args : empty //> | '(' { WORD } ')' FUNCTION_NAME //> | { WORD } FUNCTION_NAME //> | FUNCTION_NAME '(' { WORD } ')' //> ; private bool _def_function_args(NakoFunc func) { NakoToken firstT = tok.CurrentToken; NakoTokenList argTokens = new NakoTokenList(); bool argMode = false; NakoToken funcName = null; // 関数の引数宣言を取得する while (!tok.IsEOF()) { // '(' .. ')' の中は全部、関数の引数です if (argMode) { if (Accept(NakoTokenType.PARENTHESES_R)) { argMode = false; tok.MoveNext(); continue; } argTokens.Add(tok.CurrentToken); tok.MoveNext(); continue; } if (Accept(NakoTokenType.PARENTHESES_L)) { tok.MoveNext(); argMode = true; continue; } if (Accept(NakoTokenType.SCOPE_BEGIN)) { break; } if (Accept(NakoTokenType.FUNCTION_NAME)) { funcName = tok.CurrentToken; tok.MoveNext(); continue; } argTokens.Add(tok.CurrentToken); tok.MoveNext(); } if (funcName == null) { throw new NakoParserException("関数名がありません。", firstT); } func.name = funcName.GetValueAsName(); //TODO: check namespace and class name func.args.analizeArgTokens(argTokens); return(true); }
//> _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); }
//> _def_variable : WORD (DIM_VARIABLE|DIM_NUMBER|DIM_INT|DIM_STRING|DIM_ARRAY) [=_value] //> ; private bool _def_variable() { if (!Accept(NakoTokenType.WORD)) { return(false); } NakoVarType st = NakoVarType.Object; switch (tok.NextTokenType) { case NakoTokenType.DIM_VARIABLE: st = NakoVarType.Object; break; case NakoTokenType.DIM_NUMBER: st = NakoVarType.Double; break; case NakoTokenType.DIM_INT: st = NakoVarType.Int; break; case NakoTokenType.DIM_STRING: st = NakoVarType.String; break; case NakoTokenType.DIM_ARRAY: st = NakoVarType.Array; break; default: return(false); } NakoToken t = tok.CurrentToken; int varNo = localVar.CreateVar(t.GetValueAsName()); NakoVariable v = localVar.GetVar(varNo); v.SetBody(null, st); tok.MoveNext(); // skip WORD tok.MoveNext(); // skip DIM_xxx // 変数の初期化があるか? if (!Accept(NakoTokenType.EQ)) { return(true); // なければ正常値として戻る } tok.MoveNext(); // skip EQ if (!_value()) { throw new NakoParserException("変数の初期化文でエラー。", t); } // 代入文を作る NakoNodeLet let = new NakoNodeLet(); let.VarNode = new NakoNodeVariable(); let.VarNode.varNo = varNo; let.VarNode.scope = NakoVariableScope.Local; let.ValueNode.AddChild(calcStack.Pop()); this.parentNode.AddChild(let); return(true); }