Por que a flexibilidade de Forth torna uma gramática inadequada?

10

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?

Christian Dean
fonte
1
"Inadequado" é uma palavra forte neste contexto. Uma palavra melhor provavelmente seria "desnecessária".
Robert Harvey
1
Ah, tudo bem, @RobertHarvery. No entanto, se fosse esse o caso, o trecho que citei parece se aplicar à maioria dos idiomas. Tecnicamente, uma gramática nunca é necessária , mas é bom ter uma - especialmente quando analisadores de escrita à mão.
Christian Dean
Mas na maioria dos idiomas, o analisador não é uma biblioteca de tempo de execução simples que pode ser alterada pelo código do usuário, afetando como a próxima linha é analisada.
Jörg W Mittag

Respostas:

10

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.

Jerry Coffin
fonte
2
Você tem certeza de que essa propriedade de Forth realmente altera a gramática e não apenas a semântica?
Doc Brown
@DocBrown: A maioria das pessoas que usam o Forth gosta bastante, então geralmente fazem apenas as alterações mínimas necessárias para a tarefa em questão. Alguém que fosse ambicioso (e louco) o suficiente poderia mudar completamente a sintaxe se quisesse - como usar notação infix em vez de postfix, se quisesse o suficiente.
Jerry Coffin
@DocBrown Que tipo de gramática você poderia escrever que me permitisse escrever um intérprete C em Forth e depois mudar repentinamente para C no meio do programa?
user253751
@immibis: bem, minha pergunta é - Forth realmente permite algo assim? A partir desse artigo vinculado, isso não é inerentemente claro para mim.
Doc Brown
@DocBrown Sim, sim. Você pode executar seu código em tempo de compilação, ou seja, se você quiser, pode assumir o controle completamente do compilador. Basicamente, você pode executar seu compilador / intérprete C no meio do quarto compilador / intérprete. (se você quer, eventualmente, voltar para Forth ou não é com você)
user253751
3

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 escrever MY_PRINT Hello ; world! "e sua gramática precisa ser capaz de analisá-la. Boa sorte com isso.

user253751
fonte