Небольшое, но не совсем честное, изменение функций CheckTop и Compile в приведенном выше компиляторе позволит распознавать выражения с учетом приоритета операторов:
В отличие от предыдущего анализатора, который фиксировал ошибку при наличии выбора между переносом и сверткой, этот выполняет свертку только если перенос приведет к пустому состоянию (т.е. состоянию, не содержащему ни одного пункта).
Чтобы учитывать приоритеты операторов достаточно в файле c.def заменить правила для Expr и Op:
Правила для вызова функции теперь также можно упростить:
Измененный анализатор также может обходиться без синтаксического сахара. Можно исключить из грамматики (и из программ) точки с запятой, cлова is, then и do.
Если изменить правило для Expr следующим
выражения станут вычисляться справа налево, т.е. так, как они вычисляются языке Tiny Context.
Осталось добавить в функцию CheckTop проверку отсутствия конфликтов между переносом и сверткой. К сожалению после этого длина программы превысит тысячу строк:
Эти изменения в ряде случаев также позволят выбирать одну из нескольких сверток. Например, станет возможно внеся лишь незначительные изменения в исходный текст компилятора исключить введенные ранее терминальные символы type, var, array и fn соответствующими нетерминальными символами и правилами преобразования в них:
В новых действиях 270, 280, 290 и 300 нужно выполнять поиск имени в словаре и проверять, что символ name является тем, во что он будет преобразован. В частности, при попытке обратиться к простой переменной как к элементу массива должна фиксироваться ошибка.
За счет этого будет достигнуто разделение лексического и синтаксического анализаторов (лексическому анализатору более не нужен доступ к словарю).
На современных компьютерах это не очень заметно (а в эмуляторе DOSBox заметно), но приведенный компилятор работает медленно. Это связано с тем, что на каждом шаге он строит новое состояние. При каждой свертке часть построенных состояний уничтожается, затем они строятся вновь. Если построить множество состояний, таблицу переходов и сверток заранее, скорость работы компилятора станет стравнимой со скоростью работы компилятора, использующего метод рекурсивного спуска. Скорость можно увеличить еще если вместо перебора использовать какой-либо быстрый алгоритм поиска в словаре, например использовать хэш-таблицу.