/// <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> /// 送り仮名を削除します。 /// </summary> /// <param name="name">名前。</param> /// <param name="isTrimAllHiragana">ひらがなを全て消すかどうか。消さない場合は末尾のひらがなを消す</param> /// <returns>送り仮名を削除した名前。</returns> public static string TrimOkurigana(string name, bool isTrimAllHiragana) { if (name == "") { return(""); } if (isTrimAllHiragana == true) { return(TrimOkurigana(name)); } else { // 1文字目がひらがななら省略を諦める if (NakoUtility.IsHiragana(name [0])) { return(name); } string result = ""; // 送りがなを省略する bool trimFlag = false; foreach (char c in name) { if (!NakoUtility.IsHiragana(c)) { result += c; trimFlag = false; } else if (trimFlag == false) { result += c; } } return(result); } }
/// <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> /// 送り仮名を削除します。 /// </summary> /// <param name="name">名前。</param> /// <returns>送り仮名を削除した名前。</returns> public static string TrimOkurigana(string name) { if (name == "") return ""; // 1文字目がひらがななら省略を諦める if (NakoUtility.IsHiragana(name[0])) { return name; } string result = ""; // 送りがなを省略する foreach (char c in name) { if (!NakoUtility.IsHiragana(c)) { result += c; } } return result; }
/// <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>助詞が存在する場合は true。それ以外の場合は false。</returns> /// <remarks> /// このメソッドは、助詞が存在する場合、助詞の文字数だけ位置を進めます。 /// </remarks> private bool CheckJosi(NakoToken token) { if (IsEOF) { return(false); } // 助詞はひらがななので if (!NakoUtility.IsHiragana(CurrentChar)) { return(false); } // 助詞を 1 つずつ調べる foreach (string josi in NakoJosi.Instance) { if (this.Equals(josi)) { token.Josi = josi; position += josi.Length; return(true); } } return(false); }
/// <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); }