/// <summary> /// 現在の位置から数字のトークンを 1 つ取得します。 /// </summary> /// <returns>取得した数字のトークン。</returns> /// <remarks> /// このメソッドは取得したトークンの文字数だけ位置を進めます。 /// </remarks> private NakoToken GetNumberToken() { var token = new NakoToken(NakoTokenType.INT, lineNo, indentLevel); string str = ""; for (; !IsEOF; position++) { char ch = CurrentChar; if (!NakoUtility.IsNumber(ch)) { break; } str += ch; } if (CurrentChar == '.' && NakoUtility.IsNumber(NextChar)) { str += CurrentChar; token.Type = NakoTokenType.NUMBER; position++; for (; !IsEOF; position++) { char ch = CurrentChar; if (!NakoUtility.IsNumber(ch)) { break; } str += ch; } } token.Value = str; CheckJosi(token); return(token); }
/// <summary> /// 現在の位置から記号以外のトークンを 1 つ取得します。 /// </summary> /// <returns>取得した記号以外のトークン。未定義の文字列が検出された場合は不明なトークン。</returns> /// <remarks> /// このメソッドは取得したトークンの文字数だけ位置を進めます。 /// </remarks> private NakoToken GetNotFlagToken() { char c = CurrentChar; // 数字の場合 if (NakoUtility.IsNumber(c)) { return(GetNumberToken()); } // 単語の場合 if (c > 0xFF || NakoUtility.IsAlpha(c) || c == '_') { return(GetWordToken()); } return(new NakoToken(NakoTokenType.UNKNOWN, lineNo, indentLevel)); }
/// <summary> /// 現在の位置から単語のトークンを 1 つ取得します。 /// </summary> /// <returns>取得した単語のトークン。</returns> /// <remarks> /// このメソッドは取得したトークンの文字数だけ位置を進めます。 /// </remarks> private NakoToken GetWordToken() { var token = new NakoToken(NakoTokenType.WORD, lineNo, indentLevel); var builder = new StringBuilder(); while (!IsEOF) { char c = CurrentChar; if (NakoUtility.IsAlpha(c) || NakoUtility.IsNumber(c) || c == '_' || c == '!' || c == '?') { builder.Append(c); position++; continue; } // 助詞なら区切る if (NakoUtility.IsHiragana(c)) { if (CheckJosi(token)) { break; } } // 全角文字なら読む if (c >= 0xFF) { builder.Append(c); position++; // 特別な予約語なら区切る if (builder.ToString() == "もし" || builder.ToString() == "ならば") { break; } continue; } break; } token.Value = builder.ToString(); return(token); }
/// <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); }