В следующем коде вы увидите простой лексер, который соответствует следующему регулярному выражению:
\d*(\.\d*)?([eE]([+-]\d+|\d+))?
Если бы я использовал этот дизайн для чего-то более сложного, все анонимные делегаты были быкошмар, чтобы поддерживать.Самая большая проблема, с которой я сталкиваюсь, состоит в том, чтобы назвать методы, которые будут действовать как точки выбора в конечном автомате.В переменной exponentPart
последний анонимный делегат, переданный MatchOne
, решит, есть ли у нас целое число со знаком, целое число или ложное совпадение.Пожалуйста, напишите любые идеи о том, как я могу организовать такой проект, используя сложный язык с множеством общих символов.
static void Main(string[] args)
{
var exponentPart =
Lex.Start()
.MatchOne(s => s.Continue(s.Current == 'e' || s.Current == 'E'))
.MatchOne(
s => // What would I name this?
{
if (char.IsDigit(s.Current))
{
return Lex.Start().MatchZeroOrMore(s1 => s1.Continue(char.IsDigit(s1.Current)))(s.Continue(true));
}
else if (s.Current == '+' || s.Current == '-')
{
return Lex.Start().MatchOneOrMore(s1 => s1.Continue(char.IsDigit(s1.Current)))(s.Continue(true));
}
else
{
return s.RememberedState();
}
}
);
var fractionalPart =
Lex.Start()
.MatchOne(s => s.Continue(s.Current == '.'))
.MatchOneOrMore(s1 => s1.Continue(char.IsDigit(s1.Current)))
.Remember()
.MatchOne(exponentPart);
var decimalLiteral =
Lex.Start()
.MatchOneOrMore(s => s.Continue(char.IsDigit(s.Current)))
.Remember()
.MatchOne(
s => // What would I name this?
{
if (s.Current == '.')
{
return fractionalPart(s);
}
else if (s.Current == 'e' || s.Current == 'E')
{
return exponentPart(s);
}
else
{
return s.RememberedState();
}
}
);
var input = "999.999e+999";
var result = decimalLiteral(new LexState(input, 0, 0, 0, true));
Console.WriteLine(result.Value.Substring(result.StartIndex, result.EndIndex - result.StartIndex + 1));
Console.ReadLine();
}