Написание переводчика не обязательно является большой работой, но требует структурированного подхода и сильных навыков кодирования в целом.
Первый токенизация, составьте список всех компонентов кода, строки, ключевых слов, операторов и т. Д. Каждый занимает один слот, например:
- печать
- (
- "Hello \" world \ ""
- )
Это не должно быть слишком сложно.
Теперь проведите классификацию идентификаторов, в зависимости от их положения в коде и т. Д., Вы сможете определить, являются ли они вызовами функций, операторами, переменными или чем-то еще.
Теперь выполните сопоставление скобок, просмотрите список при обновлении стека несоответствующих открывающих скобок, всякий раз, когда сопоставляется скобка, удалите ее из стека и свяжите соответствующие скобки, указав каждому указатель на другой.
Ваш список должен быть превращен в дерево, теперь вы можете начинать блокировать вещи, каждая пара скобок образует блок, и в зависимости от языка другие конструкции могут составлять блок в виде скобок. (операторы начала и конца и тому подобное можно просто рассматривать как скобки). Такой блок вы просто превращаете в один элемент списка, содержащий список всех его подэлементов. Здесь и далее вы обходите дерево один раз для каждого уровня приоритета оператора и выполняете блокировку для этих операторов.
Теперь вы можете создавать списки всех переменных и функций, по одному для каждой области, и проверять отсутствие коллизий.
Для каждой области вы создаете упорядоченный список переменных, чтобы вы могли построить блок памяти и точно знать, куда каждая из них идет.
Заменить имена переменных и функций ссылками на расположение блоков памяти и объявления функций соответственно.
Теперь вы можете полностью скомпилировать программу или запустить ее в интерпретаторе.
Чтобы запустить его, создайте список стека вызовов и соответствующий список областей. Всякий раз, когда вызывается функция, запишите возвращаемую позицию в стеке вызовов и установите соответствующую область, когда она закончится, уничтожьте область и вернитесь в возвращаемую позицию.
Обычные языковые конструкции должны быть довольно просты в обращении, когда есть if
, вы знаете, что за ним следуют два блока, если первый блок оценивается как ложный, пропустите второй. Аналогично, циклы и другие конструкции обрабатываются тривиально, если вы рассматриваете их как состоящие из фиксированного числа блоков с некоторыми тривиальными правилами, определяющими, когда выполнять каждый из них.
Я сейчас дал вам структурированный подход, умение его реализовать я не могу гарантировать. Существует бесчисленное множество возможных изменений производительности, и многое из того, что я не сказал явно, как реализовать, вам придется понять.