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;
}
}