Я пишу компилятор для языка, похожего на 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)
.
Есть ли простой способ справиться с такими хитрыми ситуациями?