Recentemente, assumi a tarefa de escrever uma linguagem de programação baseada em pilha. Antes de começar a projetar meu idioma, pensei que seria uma boa ideia ler e experimentar idiomas existentes baseados em pilha.
Isso me leva ao tópico deste post. Eu estava lendo o artigo da Wikipedia sobre Forth , uma linguagem baseada em pilha que usa expressões de estilo postfix. No artigo, vi a seguinte declaração:
A flexibilidade de Forth torna inadequada uma gramática estática de BNF e não possui um compilador monolítico. Estender o compilador requer apenas escrever uma nova palavra, em vez de modificar uma gramática e alterar a implementação subjacente.
No meu entender, no quarto idioma, o termo "palavra" parece ser basicamente sinônimo de "sub-rotina". Diante disso, a afirmação acima parece estranha. Por que exatamente a capacidade de criar novas funções no Forth tornaria inadequada uma gramática formal do Forth? Por que você precisaria reescrever a gramática para cada nova sub-rotina definida? Como escrever uma nova palavra no ambiente constitui estender o compilador? A declaração acima parece semelhante a dizer que uma gramática formal é inadequada para o Python porque você pode definir novas funções.
Na verdade, eu decidi tentar escrever uma gramática no estilo BNF para um subconjunto simples de Forth abaixo:
program ::= stmt+
stmt ::= func | expr
func ::= ':' expr+ ';'
expr ::= INTEGER | word
word ::= ('+' | '-' | '*' | '/' )
A gramática acima parece cobrir um subconjunto válido de declarações anteriores, e não parece tão difícil de estender para cobrir todas as declarações válidas no idioma anterior. Além disso, se o analisador de um compilador implementa a gramática acima, não consigo ver como o compilador seria estendido. O compilador simplesmente adiciona novas palavras ao seu ambiente . Somente o ambiente é alterado. Quase parece que o trecho acima da Wikipedia está confundindo o código subjacente que compõe o compilador (que não muda) com o ambiente do compilador (que muda).
Em resumo, por que a habilidade de Forth em definir novas palavras (sub-rotinas) torna inadequado para uma gramática escrita?
Respostas:
Uma palavra "normal" é basicamente apenas uma sub-rotina.
... mas você pode escrever uma palavra definidora definida pelo usuário , que altera o funcionamento do compilador. Por exemplo, uma definição normalmente começa com dois pontos (":") e termina com ponto e vírgula (";"). Mas se você quiser, pode (por exemplo) alterar o que os dois pontos fazem e, no processo, alterar como uma definição de palavra é "compilada", alterando assim o funcionamento do compilador e alterando a gramática do idioma que está sendo reconhecido.
É por isso que está dizendo que uma gramática é inadequada - a gramática pode literalmente mudar de uma parte do programa para outra. O carregamento de um dicionário pode alterar não apenas as sub-rotinas cujos nomes são reconhecidos atualmente, mas também a gramática analisada quando você define uma nova palavra.
fonte
Em diante, você pode executar código em tempo de compilação.
Em particular, você pode executar um código que consome palavras da entrada. Por exemplo, você pode escrever um compilador C em Forth, chamá-lo em tempo de compilação e, em seguida, escrever o restante do seu programa em C.
Mais comumente, você pode definir palavras que leem argumentos do código-fonte. Tradicionalmente, você lia as palavras da mesma forma que o compilador, mas não é necessário.
Por exemplo, a
."
palavra (que imprime uma string) não é lida até o próximo espaço, é lida até o próximo"
. Se você tentar analisar o código: PRINTHELLO ." Hello ; : func2 world!" ;
sem um caso especial."
, descobrirá que ele não foi analisado corretamente.Você certamente pode adicionar um caso especial para
."
a sua gramática, mas a gramática ainda vai estar incorreta se o programador define a sua própria palavra como."
- por exemplo, aqui está um:: MY_PRINT POSTPONE ." ; IMMEDIATE
. Esta palavra é equivalente a."
; Eu sei escreverMY_PRINT Hello ; world! "
e sua gramática precisa ser capaz de analisá-la. Boa sorte com isso.fonte