/// <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> /// コンストラクタ /// </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); }
//> _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); }
/// <summary> /// 引数の定義文字列を読んで、関数の引数として登録する /// </summary> public void analizeArgTokens(NakoTokenList tokens) { bool optMode = false; ArgOpt argOpt = new ArgOpt(); for (int i = 0; i < tokens.Count; i++) { NakoToken tok = tokens[i]; NakoFuncArg arg = null; // オプション指定モード(optMode) の on/off if (tok.Type == NakoTokenType.BRACES_L) { // オプションの初期化 optMode = true; argOpt.Init(); continue; } if (tok.Type == NakoTokenType.BRACES_R) { optMode = false; continue; } if (optMode) { if (tok.Type == NakoTokenType.WORD) { string opt = (string)tok.Value; if (opt == "参照渡し") { argOpt.varBy = VarByType.ByRef; } if (opt == "整数") //TODO:数値 { NakoToken checkToken = tokens [i + 1]; if (checkToken.Type == NakoTokenType.EQ) { checkToken = tokens [i + 2]; if (checkToken.Type == NakoTokenType.INT) { argOpt.defaultValue = int.Parse(checkToken.Value); } } } if (opt == "文字列") { NakoToken checkToken = tokens [i + 1]; if (checkToken.Type == NakoTokenType.EQ) { checkToken = tokens [i + 2]; if (checkToken.Type == NakoTokenType.STRING || checkToken.Type == NakoTokenType.STRING_EX || checkToken.Type == NakoTokenType.WORD) { argOpt.defaultValue = (string)checkToken.Value; } } } } else { //find type string type = (string)tok.Value; int index = NakoAPIFuncBank.Instance.FuncList.FindIndex(delegate(NakoAPIFunc obj) { return(obj.PluginInstance.Name == type); }); if (index > 0) { argOpt.type = type; } } continue; } // WORD if (tok.Type == NakoTokenType.WORD) { int idx = indexOfName(tok.Value); if (idx < 0) { arg = new NakoFuncArg(); arg.name = tok.Value; arg.varBy = argOpt.varBy; arg.defaultValue = argOpt.defaultValue; arg.type = argOpt.type; arg.AddJosi(tok.Josi); this.Add(arg); argOpt.Init(); } else { arg = this[idx]; arg.AddJosi(tok.Josi); } } if (tok.Type == NakoTokenType.OR || tok.Type == NakoTokenType.OR_OR) { continue; } } }
/// <summary> /// 引数の定義文字列を読んで、関数の引数として登録する /// </summary> /// <param name="str"></param> public void analizeArgStr(string str) { NakoTokenList tokens = NakoTokenization.TokenizeSplitOnly(str); analizeArgTokens(tokens); }
/// <summary> /// 字句解析(トークンの分割)を行う /// 結果は Tokens で得られる /// </summary> public void Tokenize() { tokens = NakoTokenization.Tokenize(source, TokenDic); }
/// <summary> /// 引数の定義文字列を読んで、関数の引数として登録する /// </summary> public void analizeArgTokens(NakoTokenList tokens) { bool optMode = false; ArgOpt argOpt = new ArgOpt(); for (int i = 0; i < tokens.Count; i++) { NakoToken tok = tokens[i]; NakoFuncArg arg = null; // オプション指定モード(optMode) の on/off if (tok.Type == NakoTokenType.BRACES_L) { // オプションの初期化 optMode = true; argOpt.Init(); continue; } if (tok.Type == NakoTokenType.BRACES_R) { optMode = false; continue; } if (optMode) { if (tok.Type == NakoTokenType.DIM_INT) //ユーザー定義関数の「整数」はDIM INTと判定されるので、WORDに直す { tok.Type = NakoTokenType.WORD; } if (tok.Type == NakoTokenType.WORD) { string opt = (string)tok.Value; if (opt == "参照渡し") { argOpt.varBy = VarByType.ByRef; } if (opt == "整数") //TODO:数値 { NakoToken checkToken = tokens [i + 1]; if (checkToken.Type == NakoTokenType.EQ) { checkToken = tokens [i + 2]; if (checkToken.Type == NakoTokenType.INT) { argOpt.defaultValue = int.Parse(checkToken.Value); } } } if (opt == "文字列") { NakoToken checkToken = tokens [i + 1]; if (checkToken.Type == NakoTokenType.EQ) { checkToken = tokens [i + 2]; if (checkToken.Type == NakoTokenType.STRING || checkToken.Type == NakoTokenType.STRING_EX || checkToken.Type == NakoTokenType.WORD) { argOpt.defaultValue = (string)checkToken.Value; } } } if (opt == "関数") //関数定義が引数の場合。{関数(2)}とか表記(n)はn個引数があるという意味。初期値は無いはずなので、引数の個数をdefaultValueプロパティに入れているが、その点は修正の必要があるかもしれない。 { argOpt.defaultValue = 0; argOpt.type = NakoFuncType.UserCall.ToString(); for (int j = i + 1; j < tokens.Count; j++) { if (tokens [j].Type == NakoTokenType.PARENTHESES_L) { j++; NakoToken argCountToken = tokens [j]; argOpt.defaultValue = int.Parse(argCountToken.Value); j++; } if (tokens [j].Type == NakoTokenType.BRACES_R) { break; } } } } else { //find type string type = (string)tok.Value; int index = NakoAPIFuncBank.Instance.FuncList.FindIndex(delegate(NakoAPIFunc obj) { return(obj.PluginInstance.Name == type); }); if (index > 0) { argOpt.type = type; } } continue; } // WORD if (tok.Type == NakoTokenType.WORD) { int idx = indexOfName(tok.Value); if (idx < 0) { arg = new NakoFuncArg(); arg.name = tok.Value; arg.varBy = argOpt.varBy; arg.defaultValue = argOpt.defaultValue; arg.type = argOpt.type; arg.AddJosi(tok.Josi); this.Add(arg); argOpt.Init(); } else { arg = this[idx]; arg.AddJosi(tok.Josi); } } if (tok.Type == NakoTokenType.OR || tok.Type == NakoTokenType.OR_OR) { continue; } } }
//> _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; }
/// <summary> /// 構文解析器のコンストラクタ /// </summary> /// <param name="tokens"></param> public NakoParser(NakoTokenList tokens) : base(tokens) { }
//> _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> /// NakoTokenizer クラスの新しいインスタンスを初期化します。 /// </summary> public NakoTokenizer() { tokens = new NakoTokenList(); indentStack = new Stack<int>(); }
/// <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; }