Недавно я взял на себя задачу написания стекового языка программирования. Однако прежде чем приступить к разработке своего языка, я подумал, что было бы неплохо прочитать и поэкспериментировать с существующими языками, основанными на стеке.
Это подводит меня к теме этого поста. Я читал статью в Википедии о Forth , основанном на стеке языке, который использует выражения в стиле постфикса. В статье я увидел следующее утверждение:
Гибкость Forth делает статическую грамматику BNF неуместной, и у нее нет монолитного компилятора. Расширение компилятора требует только написания нового слова вместо изменения грамматики и изменения базовой реализации.
Насколько я понимаю, в «Forth lingo» термин «слово» кажется синонимом «подпрограммы». Учитывая это, приведенное выше утверждение кажется странным. Почему именно способность создавать новые функции в Forth делает формальную грамматику для Forth неуместной? Зачем вам нужно переписывать грамматику для каждой новой подпрограммы, которую вы определяете? Как написание нового слова в среде означает расширение компилятора? Вышеприведенное утверждение похоже на то, что формальная грамматика не подходит для Python, потому что вы можете определять новые функции.
Фактически, я решил попытаться написать грамматику стиля BNF для простого подмножества Forth ниже:
program ::= stmt+
stmt ::= func | expr
func ::= ':' expr+ ';'
expr ::= INTEGER | word
word ::= ('+' | '-' | '*' | '/' )
Вышеприведенная грамматика, по-видимому, охватывает действительное подмножество операторов Forth, и, кажется, не так сложно расширить ее, чтобы охватить все действительные операторы на языке Forth. Кроме того, если синтаксический анализатор компилятора реализует вышеуказанную грамматику, я не вижу, как компилятор будет расширяться. Компилятор просто добавит любые новые слова в свою среду . Только среда изменилась. Кажется, что приведенный выше фрагмент из Википедии объединяет подчеркивающий код, который составляет компилятор (который не изменяется), со средой компилятора (которая действительно изменяется).
Итак, почему аблиции Форта для определения новых слов (подпрограмм) делают неуместными для письменной грамматики?
Ответы:
«Нормальное» слово - это просто подпрограмма.
... но вы можете написать определяемое пользователем слово , которое изменит работу компилятора. Например, определение обычно начинается с двоеточия (":") и заканчивается точкой с запятой (";"). Но если вы хотите, вы можете (например) изменить то, что делает двоеточие, и в процессе изменить то, как определение слова «скомпилировано», тем самым изменив работу компилятора и изменив грамматику распознаваемого языка.
Вот почему говорится, что грамматика неуместна - грамматика может буквально меняться от одной части программы к другой. Загрузка словаря может изменить не только подпрограммы, имена которых в настоящее время распознаются, но и грамматику, которая анализируется при определении нового слова.
источник
В Forth вы можете запускать код во время компиляции.
В частности, вы можете запустить код, который потребляет слова из ввода. Например, вы можете написать компилятор C на Forth, а затем вызвать его во время компиляции, а затем написать остальную часть вашей программы на C.
Чаще всего вы можете определить слова, которые читают аргументы из исходного кода. Традиционно вы должны читать слова так же, как это делает компилятор, но это не обязательно.
Например,
."
слово (которое печатает строку) не читается до следующего пробела, оно читается до следующего"
. Если вы попытаетесь проанализировать код: PRINTHELLO ." Hello ; : func2 world!" ;
без особого случая."
, вы обнаружите, что он не был проанализирован правильно.Вы , конечно , можете добавить специальный случай для
."
к вашей грамматике, но грамматика все равно будет неверной , если программист определяет свое собственное слово , как."
- например , вот один:: MY_PRINT POSTPONE ." ; IMMEDIATE
. Это слово эквивалентно."
; Я могу написать,MY_PRINT Hello ; world! "
и ваша грамматика должна быть в состоянии разобрать ее. Удачи с этим.источник