/// <summary> /// ソース名とソースを指定して解析します。 /// </summary> /// <param name="name">ソース名</param> /// <param name="source">解析対象のソースコード</param> /// <returns></returns> private KecaknoahLexResult AnalyzeFromText(string name, string source) { var result = new KecaknoahLexResult(name); var line = 0; var col = 0; var cq = ""; Tuple<string, KecaknoahTokenType> kw; Match lm; KecaknoahError ei; while (source != "") { //空白論理行 if (source.StartsWith(Environment.NewLine)) { source = source.Substring(Environment.NewLine.Length); result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(line, col), TokenString = "<NewLine>", Type = KecaknoahTokenType.NewLine }); line++; col = 0; continue; } /* if (source.StartsWith(";")) { source = source.Substring(1); result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(line, col), TokenString = ";", Type = KecaknoahTokenType.Semicolon }); col++; continue; } */ Tuple<string, string> mcq = null; if ((mcq = MultilineCommentQuotations.FirstOrDefault(p => source.StartsWith(p.Item1))) != null) { source = source.Substring(mcq.Item1.Length); col += mcq.Item1.Length; var ce = source.IndexOf(mcq.Item2); var ecs = source.IndexOf(mcq.Item1); //不正な複数行コメント if ((ecs >= 0 && ecs < ce) || ce < 0) { ei = new KecaknoahError { Column = col, Line = line, Message = "不正な複数行コメントです。コメントが終了していないか、入れ子になっています。" }; result.Error = ei; result.Success = false; return result; } while (true) { ce = source.IndexOf(mcq.Item2); var cl = source.IndexOf(Environment.NewLine); if ((cl > 0 && ce < cl) || cl < 0) { source = source.Substring(ce + mcq.Item2.Length); col += ce + mcq.Item2.Length; break; } else { source = source.Substring(cl + Environment.NewLine.Length); line++; col = 0; } } continue; } //コメント if ((cq = LineCommentStart.FirstOrDefault(p => source.StartsWith(p))) != null) { source = source.Substring(cq.Length); col += cq.Length; var cl = source.IndexOf(Environment.NewLine); if (cl >= 0) { source = source.Substring(cl + Environment.NewLine.Length); line++; col = 0; } else { //ラストコメント source = ""; } continue; } //空白 if ((lm = WhitespacePattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; continue; } //演算子 if ((kw = Operators.FirstOrDefault(p => source.StartsWith(p.Item1))) != null) { source = source.Substring(kw.Item1.Length); col += kw.Item1.Length; result.AddToken(kw.CreateToken(col, line)); continue; } //識別子・キーワード if ((lm = IdentiferPattern.Match(source)).Success && lm.Index == 0) { if ((kw = Keywords.FirstOrDefault(p => lm.Value == p.Item1)) != null) { source = source.Substring(kw.Item1.Length); col += kw.Item1.Length; result.AddToken(kw.CreateToken(col, line)); } else { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsIdentifer(col, line)); } continue; } //リテラル if ((lm = BinaryNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsBinaryNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue; } if ((lm = OctadecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsOctadecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue; } if ((lm = HexadecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsHexadecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue; } if ((lm = HexatridecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsHexatridecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue; } if ((lm = DecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsDecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) continue; } if ((cq = StringQuotation.FirstOrDefault(p => source.StartsWith(p))) != null) { source = source.Substring(cq.Length); col += cq.Length; int qp = 0, eqp = 0, inp = 0; var ls = ""; do { eqp = source.IndexOf("\\" + cq); qp = source.IndexOf(cq); inp = source.IndexOf(Environment.NewLine); if (inp >= 0 && inp < qp) { ei = new KecaknoahError { Column = col, Line = line, Message = "文字列リテラル中に直接改行が含まれています。改行を表現したい場合、\\nを利用してください。" }; result.Error = ei; result.Success = false; return result; } if (qp < 0) { ei = new KecaknoahError { Column = col, Line = line, Message = "文字列リテラルが閉じていません。" }; result.Error = ei; result.Success = false; return result; } if (eqp >= 0 && qp - eqp == 1) { ls += source.Substring(0, qp + cq.Length); source = source.Substring(qp + cq.Length); col += qp + cq.Length - 1; continue; } else { ls += source.Substring(0, qp); source = source.Substring(qp + cq.Length); foreach (var i in StringLiteralEscapes) ls = ls.Replace(i.Item1, i.Item2); result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(col, line), TokenString = ls, Type = KecaknoahTokenType.StringLiteral }); col += qp + cq.Length; break; } } while (true); continue; } //不明 ei = new KecaknoahError { Column = col, Line = line, Message = "不正なトークンです。" }; result.Error = ei; result.Success = false; return result; } result.Success = true; return result; }
internal KecaknoahException(KecaknoahError err) : base($"解析中にエラーが発生しました: {err.Message}") { Error = err; }
/// <summary> /// ソース名とソースを指定して解析します。 /// </summary> /// <param name="name">ソース名</param> /// <param name="source">解析対象のソースコード</param> /// <returns></returns> private KecaknoahLexResult AnalyzeFromText(string name, string source) { var result = new KecaknoahLexResult(name); var line = 0; var col = 0; var cq = ""; Tuple <string, KecaknoahTokenType> kw; Match lm; KecaknoahError ei; while (source != "") { //空白論理行 if (source.StartsWith(Environment.NewLine)) { source = source.Substring(Environment.NewLine.Length); result.AddToken(new KecaknoahToken { Position = new Tuple <int, int>(line, col), TokenString = "<NewLine>", Type = KecaknoahTokenType.NewLine }); line++; col = 0; continue; } /* * if (source.StartsWith(";")) * { * source = source.Substring(1); * result.AddToken(new KecaknoahToken { Position = new Tuple<int, int>(line, col), TokenString = ";", Type = KecaknoahTokenType.Semicolon }); * col++; * continue; * } */ Tuple <string, string> mcq = null; if ((mcq = MultilineCommentQuotations.FirstOrDefault(p => source.StartsWith(p.Item1))) != null) { source = source.Substring(mcq.Item1.Length); col += mcq.Item1.Length; var ce = source.IndexOf(mcq.Item2); var ecs = source.IndexOf(mcq.Item1); //不正な複数行コメント if ((ecs >= 0 && ecs < ce) || ce < 0) { ei = new KecaknoahError { Column = col, Line = line, Message = "不正な複数行コメントです。コメントが終了していないか、入れ子になっています。" }; result.Error = ei; result.Success = false; return(result); } while (true) { ce = source.IndexOf(mcq.Item2); var cl = source.IndexOf(Environment.NewLine); if ((cl > 0 && ce < cl) || cl < 0) { source = source.Substring(ce + mcq.Item2.Length); col += ce + mcq.Item2.Length; break; } else { source = source.Substring(cl + Environment.NewLine.Length); line++; col = 0; } } continue; } //コメント if ((cq = LineCommentStart.FirstOrDefault(p => source.StartsWith(p))) != null) { source = source.Substring(cq.Length); col += cq.Length; var cl = source.IndexOf(Environment.NewLine); if (cl >= 0) { source = source.Substring(cl + Environment.NewLine.Length); line++; col = 0; } else { //ラストコメント source = ""; } continue; } //空白 if ((lm = WhitespacePattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; continue; } //演算子 if ((kw = Operators.FirstOrDefault(p => source.StartsWith(p.Item1))) != null) { source = source.Substring(kw.Item1.Length); col += kw.Item1.Length; result.AddToken(kw.CreateToken(col, line)); continue; } //識別子・キーワード if ((lm = IdentiferPattern.Match(source)).Success && lm.Index == 0) { if ((kw = Keywords.FirstOrDefault(p => lm.Value == p.Item1)) != null) { source = source.Substring(kw.Item1.Length); col += kw.Item1.Length; result.AddToken(kw.CreateToken(col, line)); } else { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsIdentifer(col, line)); } continue; } //リテラル if ((lm = BinaryNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsBinaryNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) { continue; } } if ((lm = OctadecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsOctadecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) { continue; } } if ((lm = HexadecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsHexadecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) { continue; } } if ((lm = HexatridecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsHexatridecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) { continue; } } if ((lm = DecimalNumberPattern.Match(source)).Success && lm.Index == 0) { source = source.Substring(lm.Length); col += lm.Length; result.AddToken(lm.Value.CreateTokenAsDecimalNumber(col, line)); if (!(lm = IdentiferPattern.Match(source)).Success || lm.Index != 0) { continue; } } if ((cq = StringQuotation.FirstOrDefault(p => source.StartsWith(p))) != null) { source = source.Substring(cq.Length); col += cq.Length; int qp = 0, eqp = 0, inp = 0; var ls = ""; do { eqp = source.IndexOf("\\" + cq); qp = source.IndexOf(cq); inp = source.IndexOf(Environment.NewLine); if (inp >= 0 && inp < qp) { ei = new KecaknoahError { Column = col, Line = line, Message = "文字列リテラル中に直接改行が含まれています。改行を表現したい場合、\\nを利用してください。" }; result.Error = ei; result.Success = false; return(result); } if (qp < 0) { ei = new KecaknoahError { Column = col, Line = line, Message = "文字列リテラルが閉じていません。" }; result.Error = ei; result.Success = false; return(result); } if (eqp >= 0 && qp - eqp == 1) { ls += source.Substring(0, qp + cq.Length); source = source.Substring(qp + cq.Length); col += qp + cq.Length - 1; continue; } else { ls += source.Substring(0, qp); source = source.Substring(qp + cq.Length); foreach (var i in StringLiteralEscapes) { ls = ls.Replace(i.Item1, i.Item2); } result.AddToken(new KecaknoahToken { Position = new Tuple <int, int>(col, line), TokenString = ls, Type = KecaknoahTokenType.StringLiteral }); col += qp + cq.Length; break; } } while (true); continue; } //不明 ei = new KecaknoahError { Column = col, Line = line, Message = "不正なトークンです。" }; result.Error = ei; result.Success = false; return(result); } result.Success = true; return(result); }
/// <summary> /// 規定 /// </summary> /// <param name="message">メッセージ</param> /// <param name="inner">内側</param> public KecaknoahParseException(string message, Exception inner) : base(message, inner) { Error = new KecaknoahError { Column = 0, Line = 0, Message = message }; }
/// <summary> /// 指定した<see cref="KecaknoahError"/>を格納して初期化します。 /// </summary> /// <param name="error">エラー情報</param> public KecaknoahParseException(KecaknoahError error) : base(error.Message) { Error = error; }
/// <summary> /// 規定のコンストラクター /// </summary> public KecaknoahParseException() { Error = new KecaknoahError { Column = 0, Line = 0, Message = "" }; }