Павиа написал(а):Оптимальный, но не в смысле скорости, а в смысле человеко понятности выдаваемого кода. Таблицы и перебор оно гораздо понятнее. Только не надо доводить до предела. Когда табличка трёх-этажная и без бутылке не разберёшь, что и куда.
Для повышения удобочитаемости кода я выделил некоторые распространенные в ЯП грамматические конструкции в виде отдельных процедур. Например
1. Список с разделителями.
list(item : TNodeAST_Parser, separator : TSymbol)
Данная конструкция немного облегчает код и значительно упрощает процесс восстановления в случае ошибки.
2. Список с разделителями и явным окончанием
closed_list(item : TNodeAST_Parser, separator : TSymbol, close_sym: TSymbol)
3. Список с разделителями, с явным началом и окончанием
delimed_list(item : TNodeAST_Parser, separator : TSymbol, open_sym: TSymbol, close_sym: TSymbol)
4. Заключение в скобки
delimed(body : TNodeAST_Parser, open_sym: TSymbol, close_sym: TSymbol)
Для разбора конструкций вида: <open_sym> <body> <close_sym>
5. Разбор бинарных операций с учетом приоритета
binop(value: TNodeAST_Parser, operations : TMap <TSymbol, integer>)
operations - асоц. массив, где ключ - символ операции а значение ее приоритет.
6. Разбор атрибутов
attributes(attrib_map : TMap <TSymbol, integer>)
attrib_map - асоц. массив, где ключ - символ (лексема) обозначающая атрибут а значение битовая маска соответствующая данному атрибуту.
7. Условное вхождение со значением по умолчанию.
optional(rule: TNodeAST_Parser, default_value : TNodeAST)
Тогда ваш пример описания грамматики примет вот такой вид: