Комментарии 7
Я не буду вдаваться в подробности распределения памяти и способы интерпретации кода, а наоборот, хотелось бы поговорить о самом устройстве компилятора, а именно о лексическом анализаторе и попробовать реализовать его на языке C#.
Об этом было бы еще интересней узнать, поскольку материала по лексическому и синтаксическому анализу в целом больше.
Сама лексема будет в себе хранить ключ, с помощью которого будет определяться принадлежность к типу (служебные слова, операторы, идентификаторы, числа), id лексемы и само значение.
Как понимаю, это иммутабельный класс. Поэтому его поля и свойства должны быть readonly
. Ну и в C# принято обозначать локальные переменные без префиксов, а поля — с ними или без:
class Lex
{
public readonly int id;
public readonly int lex;
public readonly string val;
public Lex(int id, int lex, string val)
{
this.id = id;
this.lex = lex;
this.val = val;
}
}
private (int, string) SerchLex(string[] lexes)
Во-первых, здесь опечатка: SerchLex
-> SearchLex
. Во-вторых, обращаю внимание, что метод FindIndex
имеет линейную сложность. Так что если лексем будет много, то правильней использовать HashSet
или Dictionary
, поскольку они имеют константную сложность поиска.
private StringReader sr; // позволяет посимвольно считывать строку
А зачем тут дополнительная обертка, если можно просто по строке итерироваться?
Думаю использование StringReader
может снижать производительность.
if (sm[0] == ' ' || sm[0] == '\n' || sm[0] == '\t' || sm[0] == '\0' || sm[0] == '\r' )
В таких случаях нужно выносить одно и то же вычисление в отдельную переменную, т.е. sm0 = sm[0];
. Не факт, что компилятор его оптимизирует, ну и код так чище выглядит.
Особое внимание стоит уделить оператору присваивания ":=", который состоит из двух отдельных операторов.
Как вариант, при токенизации можно выбирать лексему с наибольшей длиной, тогда присваивание будет трактоваться именно как отдельный оператор.
Протестировать алгоритм можно по-разному: указать напрямую путь .pas файла, программно создать строку или любой другой удобный вариант. Так как мы пишем на C#, не составит труда добавить форму в приложение, на которой будет 2 textBox-а, первый для ввода кода программы, второй — выводит результат работы алгоритма.
Да можно сразу через консоль тестировать — это на самом деле легче и более
кроссплатформенно. А в идеале — юнит-тесты.
По нажатию кнопки будем запускать анализ текста, а полученный результат будем обрабатывать с помощью switch конструкции: дополнительно выведем к какому типу относится найденная лексема.
Ну этот код уже совсем не годиться — в нем много дублирования, а для соединения строк в цикле используется конкатенация. Первое плохо при исправлении кода, второе — с точки зрения производительности и потребления памяти — конкатенация всегда создает новый объект. Можно переписать этот код следующим образом:
private void button1_Click(object sender, EventArgs e)
{
textBox2.Clear();
TplMain tpl = new TplMain();
tpl.Analysis(textBox1.Text);
var result = new StringBuilder();
foreach(var lex in tpl.Lexemes)
{
string lexName = null;
switch (lex.id)
{
case 1:
lexName = " служебные слова ";
break;
case 2:
lexName = " ограничители ";
break;
case 3:
lexName = " числа ";
break;
case 4:
lexName = " идентификатор ";
break;
}
if (lexName != null)
{
result.Append("id: ");
result.Append(lex.id);
result.Append(" lex: ");
result.Append(lex.lex);
result.Append(" val: ");
result.Append(lex.val);
result.Append(" |");
result.AppendLine(lexName);
}
}
textBox2.Text = result.ToString();
}
С проектом можно ознакомиться по ссылке
А где ссылка то? :)
Ну и напоследок: почему вы не стали использовать генераторы лексических анализаторов типа ANTLR? Велосипед то — это неплохо, но еще лучше, когда написано почему.
Ну и напоследок: почему вы не стали использовать генераторы лексических анализаторов типа ANTLR?Я тоже задавался этим вопросом, почему ВСЕ разработчики серьезных компиляторов игнорируют АНТЛР.
Ответ отказался простым.
Лучше сразу предусматривать универсальную обработку лексем из нескольких служебных символов, чем каждый раз отдельно обрабатывать «особый случай».
Введение в теорию компиляторов: лексический анализ языка Pascal средствами C#