//> _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); }
//> _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); }
//> _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; }
//> _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; }
/// <summary> /// 展開あり文字列トークンを再帰的に展開します。 /// </summary> /// <param name="token">展開あり文字列トークン。</param> /// <returns>再帰的に展開したトークン一覧。</returns> private static NakoTokenList StringTokenExtract(NakoToken token) { var tokens = new NakoTokenList(); string tmp = ""; string str = token.Value; int i = 0; bool isFirst = true; while (i < str.Length) { char ch = str[i]; if (ch == '{' || ch == '{') { if (isFirst) { isFirst = false; } else { // "&" トークンを追加 tokens.Add(new NakoToken(NakoTokenType.AND, token.LineNo, token.IndentLevel)); } i++; // 展開する文字列 ("{" と "}" との間) を取得する string exString = ""; { char end = (ch == '{') ? '}' : '}'; for (; i < str.Length; i++) { if (str[i] == end) { i++; break; } exString += str[i]; } } // 文字列展開だけの特殊メソッド ('\' メソッド) if (exString.Length > 0 && exString[0] == '\\') { if (exString == "\\t") { // \t の場合 tmp += '\t'; exString = ""; } else if (exString == "\\r") { // \r の場合 tmp += '\r'; exString = ""; } else if (exString == "\\n") { // \n の場合 tmp += '\n'; exString = ""; } else if (NakoUtility.IsNumber(exString[1])) { // \0 のような場合 exString = exString.Substring(1); tmp += (char)int.Parse(exString); exString = ""; } else if (exString[1] == '$') { // \$00 のような場合 exString = "0x" + exString.Substring(2); tmp += (char)int.Parse(exString); exString = ""; } else { new NakoTokenizerException("展開あり文字列内の利用できない`\\'メソッド:" + exString, token); } } // 文字列展開だけの特殊メソッド ('~' メソッド) else if (exString.Length == 1 && exString[0] == '~') { tmp += "\r\n"; exString = ""; } // 文字列トークンを追加 tokens.Add(new NakoToken(NakoTokenType.STRING, token.LineNo, token.IndentLevel, tmp)); tmp = ""; if (exString != "") { // "&" トークンを追加 tokens.Add(new NakoToken(NakoTokenType.AND, token.LineNo, token.IndentLevel)); // "(" トークンを追加 tokens.Add(new NakoToken(NakoTokenType.PARENTHESES_L, token.LineNo, token.IndentLevel)); // 再帰的にトークンを解析 var innerTokens = new NakoTokenizer().TokenizeSplitOnly(exString, token.LineNo, token.IndentLevel); // とりあえず区切るだけ foreach (var innerToken in innerTokens) { tokens.Add(innerToken); } // ")" トークンを追加 tokens.Add(new NakoToken(NakoTokenType.PARENTHESES_R, token.LineNo, token.IndentLevel)); } continue; } tmp += ch; i++; } if (tmp != "") { if (!isFirst) { // "&" トークンを追加 tokens.Add(new NakoToken(NakoTokenType.AND, token.LineNo, token.IndentLevel)); } // 文字列トークンを追加 tokens.Add(new NakoToken(NakoTokenType.STRING, token.LineNo, token.IndentLevel, tmp)); } else { // 必要なら空文字列トークンを追加 if (isFirst) { tokens.Add(new NakoToken(NakoTokenType.STRING, token.LineNo, token.IndentLevel, "")); } } // 助詞をコピー tokens[tokens.Count - 1].Josi = token.Josi; return tokens; }