(публикация результатов комментариев по запросу.)
Решение № 1 определенно некрасивое, сложное в реализации и ненужное, я согласен. Решение № 2 намного проще в реализации и понимании. Вы также можете разрешить настраиваемую ассоциативность и приоритет для операторов, если они известны статически. Главное, что эти факты известны во время разбора.
Что касается фактического синтаксического анализа, большинство синтаксических анализаторов будут работать просто отлично, поскольку любые два выражения, окружающие идентификатор, являются приложением пользовательского инфиксного оператора (это менее верно, если вы разрешите пользовательский приоритет и ассоциативность, в этом случае вам нужен алгоритм что позволяет определять их для каждого оператора во время разбора). В любом случае, мой личный фаворит - это «анализатор приоритета оператора сверху вниз» или анализатор Pratt. Я обнаружил, что следующие ресурсы (упорядоченные по полезности для меня, YMMV) достаточно хорошо описывают это:
Два свойства алгоритма очень хорошо подходят для этой задачи:
- Поиск ассоциативности («сила привязки») происходит динамически для каждого токена (что позволяет анализатору позволить пользователю определять приоритет для своих операторов).
- Это очень просто написать вручную [*], и вам, вероятно, придется сделать это, поскольку такая степень динамичности выходит за рамки большинства (по крайней мере, всех, что я знаю) генераторов синтаксических анализаторов.
[*] Я лично написал парсер для очень большого (не хватает только case
, многомерных массивов и, возможно, некоторых неясных тонкостей) подмножества Паскаля в 500 строк Python и 2-3 дня работы, остальные отсутствует только потому, что другие части программного обеспечения, в котором оно использовалось, были в то время более интересными, и у меня не было причин для реализации остальных.