/// <summary> /// トークンに区切ります。 /// </summary> private void SplitToToken() { // 最初にインデントを数える indentCount = CountIndent(); indentLevel = 0; // 繰り返しトークンを取得する while (!IsEOF) { var token = GetToken(); if (token == null) { lastTokenType = NakoTokenType.EOL; continue; } lastTokenType = token.Type; // 展開あり文字列をここで展開 if (token.Type == NakoTokenType.STRING_EX) { foreach (var extractToken in StringTokenExtract(token)) { tokens.Add(extractToken); } } else { tokens.Add(token); } } // レベルが合うまで SCOPE_END を追加する CheckScope(); }
/// <summary> /// NakoToken クラスの新しいインスタンスを、指定した種類、行番号、インデントレベル、値を使用して初期化します。 /// </summary> /// <param name="type">種類。</param> /// <param name="lineNo">行番号。</param> /// <param name="indentLevel">インデントレベル。</param> /// <param name="value">値。</param> public NakoToken(NakoTokenType type, int lineNo, int indentLevel, string value) { Type = type; LineNo = lineNo; IndentLevel = indentLevel; Value = value; Josi = ""; }
/// <summary> /// 現在のカーソル位置から keytype のトークンがないか調べる (EOLStop=trueのときはEOLまで) /// </summary> /// <param name="keytype"></param> /// <param name="EOLStop"></param> /// <returns></returns> public bool SearchToken(NakoTokenType keytype, bool EOLStop) { int i = cur; NakoToken t; int par_nest = 0; int bla_nest = 0; while (i < this.Count) { t = this[i]; // break? if (t.Type == keytype) { return(true); } if (EOLStop) { if (t.Type == NakoTokenType.EOL) { break; } } // --- // nest check if (t.Type == NakoTokenType.BRACKETS_L) { bla_nest++; } if (t.Type == NakoTokenType.BRACKETS_R) { bla_nest--; if (bla_nest < 0) { return(false); // tokenが見つかる前に角カッコの不整合を見つけた } } // --- if (t.Type == NakoTokenType.PARENTHESES_L) { par_nest++; } if (t.Type == NakoTokenType.PARENTHESES_R) { par_nest--; if (par_nest < 0) { return(false); // tokenが見つかる前に丸カッコの不整合を見つけた } } i++; } return(false); }
/// <summary> /// 指定したソースコードからトークンに区切るだけの解析をします。文法を一切考慮しません。 /// </summary> /// <param name="source">解析するソースコード。</param> /// <param name="lineNo">開始する行番号。</param> /// <param name="indentLevel">開始するインデントレベル。</param> /// <returns>指定したソースコードから解析した、トークン一覧。</returns> public NakoTokenList TokenizeSplitOnly(string source, int lineNo, int indentLevel) { Initialization(); this.source = source; this.indentLevel = indentLevel; this.lineNo = lineNo; // 繰り返しトークンを取得する while (!IsEOF) { var token = GetToken(); if (token == null) { continue; } lastTokenType = token.Type; tokens.Add(token); } return(tokens); }
/// <summary> /// 現在のトークンが指定したタイプと合致しているか /// </summary> /// <param name="type"></param> /// <returns></returns> protected bool Accept(NakoTokenType type) { return (tok.CurrentTokenType == type); }
/// <summary> /// 現在のトークンが指定したタイプと合致しているか /// </summary> /// <param name="type"></param> /// <returns></returns> protected bool Accept(NakoTokenType type) { return(tok.CurrentTokenType == type); }
/// <summary> /// 現在のトークンが、指定したトークンタイプtと合致するか /// </summary> /// <param name="t"></param> /// <returns></returns> public bool Accept(NakoTokenType t) { return(t == CurrentTokenType); }
/// <summary> /// トークンを探す /// </summary> /// <param name="keytype"></param> /// <returns></returns> public bool SearchToken(NakoTokenType keytype) { return(SearchToken(keytype, false)); }
/// <summary> /// 現在の位置からトークンを 1 つ取得します。 /// </summary> /// <returns>取得したトークン。位置がソースコードの終端に達している場合は null。</returns> /// <remarks> /// このメソッドは取得したトークンの文字数だけ位置を進めます。 /// </remarks> private NakoToken GetToken() { if (IsEOF) { return(null); } var token = new NakoToken(NakoTokenType.UNKNOWN, lineNo, indentLevel); char nc; switch (CurrentChar) { // BOM かどうか確認 case (char)0xFEFF: position++; return(null); // 行末かどうか確認 case '\r': position++; return(null); case '\n': token.Type = NakoTokenType.EOL; lastTokenType = NakoTokenType.EOL; position++; lineNo++; tokens.Add(token); CheckScope(); return(null); // インデントかどうか確認 case ' ': case '\t': position++; // skip return(null); // 句読点かどうか確認 case ';': token.Type = NakoTokenType.EOL; // 明確な区切り lastTokenType = NakoTokenType.EOL; position++; return(token); case ',': position++; return(null); // 記号かどうか確認 case '=': nc = NextChar; if (nc == '=') { position += 2; token.Type = NakoTokenType.EQ_EQ; } else { position++; token.Type = NakoTokenType.EQ; } return(token); case '&': nc = NextChar; if (nc == '&') { position += 2; token.Type = NakoTokenType.AND_AND; } else { position++; token.Type = NakoTokenType.AND; } return(token); case '|': nc = NextChar; if (nc == '|') { position += 2; token.Type = NakoTokenType.OR_OR; } else { position++; token.Type = NakoTokenType.OR; } return(token); case '<': nc = NextChar; if (nc == '=') { position += 2; token.Type = NakoTokenType.LT_EQ; } else if (nc == '>') { position += 2; token.Type = NakoTokenType.NOT_EQ; } else { position++; token.Type = NakoTokenType.LT; } return(token); case '>': nc = NextChar; if (nc == '=') { position += 2; token.Type = NakoTokenType.GT_EQ; } else if (nc == '<') { position += 2; token.Type = NakoTokenType.NOT_EQ; } else { position++; token.Type = NakoTokenType.GT; } return(token); case '!': nc = NextChar; if (nc == '=') { position += 2; token.Type = NakoTokenType.NOT_EQ; } else { position++; token.Type = NakoTokenType.NOT; } return(token); case '「': case '『': case '"': case '`': return(GetStringToken()); case '+': token.Type = NakoTokenType.PLUS; position++; return(token); case '-': token.Type = NakoTokenType.MINUS; position++; return(token); case '*': if (lastTokenType == NakoTokenType.EOL || lastTokenType == NakoTokenType.UNKNOWN) { token.Type = NakoTokenType.DEF_FUNCTION; } else { token.Type = NakoTokenType.MUL; } position++; return(token); case '/': // コメントかどうか確認 nc = NextChar; if (nc == '*') { return(GetRangeCommentToken()); } if (nc == '/') { return(GetLineCommentToken()); } // 割り算かどうか確認 token.Type = NakoTokenType.DIV; position++; return(token); case '%': token.Type = NakoTokenType.MOD; position++; return(token); case '^': token.Type = NakoTokenType.POWER; position++; return(token); case '(': token.Type = NakoTokenType.PARENTHESES_L; position++; return(token); case ')': token.Type = NakoTokenType.PARENTHESES_R; position++; CheckJosi(token); return(token); case '{': token.Type = NakoTokenType.BRACES_L; position++; return(token); case '}': token.Type = NakoTokenType.BRACES_R; position++; CheckJosi(token); return(token); case '[': token.Type = NakoTokenType.BRACKETS_L; position++; return(token); case ']': token.Type = NakoTokenType.BRACKETS_R; position++; CheckJosi(token); return(token); case '\\': token.Type = NakoTokenType.YEN; position++; return(token); case '#': return(GetLineCommentToken()); default: token = GetNotFlagToken(); if (token.Type == NakoTokenType.UNKNOWN) { char ch = CurrentChar; string msg = "未定義の文字列: " + (ch < 0x20 ? String.Format("0x{0,0:X2}", (int)ch) : "`" + ch + "`"); throw new NakoTokenizerException(msg, token); } return(token); } }
/// <summary> /// NakoToken クラスの新しいインスタンスを、指定した種類、行番号、インデントレベルを使用して初期化します。 /// </summary> /// <param name="type">種類。</param> /// <param name="lineNo">行番号。</param> /// <param name="indentLevel">インデントレベル。</param> public NakoToken(NakoTokenType type, int lineNo, int indentLevel) : this(type, lineNo, indentLevel, "") { }
/// <summary> /// NakoToken クラスの新しいインスタンスを、指定した種類を使用して初期化します。 /// </summary> /// <param name="type">種類。</param> public NakoToken(NakoTokenType type) : this(type, 0, 0) { }
/// <summary> /// 指定したソースコードからトークンに区切るだけの解析をします。文法を一切考慮しません。 /// </summary> /// <param name="source">解析するソースコード。</param> /// <param name="lineNo">開始する行番号。</param> /// <param name="indentLevel">開始するインデントレベル。</param> /// <returns>指定したソースコードから解析した、トークン一覧。</returns> public NakoTokenList TokenizeSplitOnly(string source, int lineNo, int indentLevel) { Initialization(); this.source = source; this.indentLevel = indentLevel; this.lineNo = lineNo; // 繰り返しトークンを取得する while (!IsEOF) { var token = GetToken(); if (token == null) { continue; } lastTokenType = token.Type; tokens.Add(token); } return tokens; }
/// <summary> /// トークンに区切ります。 /// </summary> private void SplitToToken() { // 最初にインデントを数える indentCount = CountIndent(); indentLevel = 0; // 繰り返しトークンを取得する while (!IsEOF) { var token = GetToken(); if (token == null) { lastTokenType = NakoTokenType.EOL; continue; } lastTokenType = token.Type; // 展開あり文字列をここで展開 if (token.Type == NakoTokenType.STRING_EX) { foreach (var extractToken in StringTokenExtract(token)) { tokens.Add(extractToken); } } else tokens.Add(token); } // レベルが合うまで SCOPE_END を追加する CheckScope(); }