Я пишу компилятор для языка, похожего на javascript, для развлечения. ака я изучаю колесо, поэтому я делаю его для себя и пытаюсь узнать все, но теперь я застрял.
Я знаю, что алгоритм маневровой станции хорош при разборе простых инфиксных выражений. Мне удалось выяснить, как расширить этот алгоритм для префиксных и постфиксных операторов, а также разобрать простые функции.
Например: 2+3*a(3,5)+b(3,5)
превращается в 2 3 <G> 3 5 a () * + <G> 3 5 b () +
(<G>
— это защитный токен, который помещается в стек, в нем будет храниться адрес возврата и т. д. ()
— это команда вызова, которая вызывает функцию на вершине стека, которая выталкивает необходимое количество аргументов и отталкивает результат при возврате. .)
Если имя функции представляет собой всего лишь один токен, я могу просто пометить его как символ функции, если за ним непосредственно следует скобка. Если во время процесса я сталкиваюсь с символом функции, я помещаю его в стек операторов и извлекаю, когда закончу преобразование параметров.
Это работает до сих пор.
Но если я добавлю возможность иметь функции-члены, оператор .
. Все становится сложнее. Например, я хочу преобразовать a.b.c(12)+d.e.f(34)
. Я не могу пометить c и f как функции, потому что a.b.c
и d.e.f
являются функциями. Если я начну синтаксический анализатор с такого выражения, результат будет a b . <G> 12 c () . d e . <G> 34 f () .
, что явно неверно. Я хочу, чтобы это было <G> 12 a b . c . () <G> 34 d e . f. ()
, что кажется правильным. Но, черт возьми, я могу все усложнить, если добавлю скобки: (a.b.c)()
. Или я создаю функцию, которая возвращает функцию, которую я снова вызываю: f(a,b)(c,d)
.
Есть ли простой способ справиться с этими сложными ситуациями?