Ouvi um tempo atrás que costumava haver um compilador que tentava corrigir erros de sintaxe analisando o contexto e inferindo o que era pretendido.
Esse compilador realmente existe? Obviamente, ele tem pouco valor prático, mas seria muito interessante para brincar e aprender.
Respostas:
Em certo sentido, o ato de compilar está inferindo o que determinada sintaxe deve fazer e, portanto, um erro de sintaxe ocorre quando o compilador não é capaz de descobrir isso. Você pode adicionar mais "suposições" para que o compilador deduza outras coisas e seja mais flexível com a sintaxe, mas isso deve ser inferido por um conjunto específico de regras. E essas regras tornam-se parte da linguagem e não são mais erros.
Então, não, não existem tais compiladores, realmente, porque a pergunta não faz sentido. Adivinhar o que os erros de sintaxe devem fazer de acordo com algum conjunto de regras se torna parte da sintaxe.
Nesse sentido, há um bom exemplo de um compilador que faz isso: Qualquer compilador C. Eles geralmente imprimem um aviso de algo que não é como deveria ser e assumem que você quis dizer X e continuam. Na verdade, isso é "adivinhar" um código pouco claro (embora na maioria das vezes não seja sintaxe), algo que também poderia ter interrompido a compilação com um erro e, portanto, qualificado como um erro.
fonte
Parece realmente perigoso. Se um compilador tentar inferir sua intenção, inferir errado, corrigir o código e depois não informar (ou avisar em algum aviso que você, como todo mundo, ignora), você está prestes a executar um código que pode seriamente causar algum dano.
Um compilador como esse é provavelmente algo que intencionalmente NÃO foi criado.
fonte
O IDE para uma linguagem de programação normalmente hoje em dia tem um compilador sendo executado em segundo plano de alguma forma, para que ele possa fornecer serviços de análise como sintaxe de cores, IntelliSense, erros e assim por diante. Obviamente, esse compilador precisa ser capaz de entender o código profundamente quebrado; Na maioria das vezes, ao editar, o código não está correto. Mas ainda temos que entender isso.
No entanto, geralmente o recurso de recuperação de erros é usado apenas durante a edição; não faz muito sentido permitir isso para compilação real em cenários "principais".
Curiosamente, criamos esse recurso no compilador JScript.NET; basicamente, é possível colocar o compilador em um modo em que permitimos que o compilador prossiga mesmo se um erro for encontrado, se o IDE tivesse se recuperado dele. Você pode digitar o código do Visual Basic , executar o compilador JScript.NET nele e ter uma chance razoável de um programa de trabalho sair do outro lado!
Esta é uma demonstração divertida, mas acaba não sendo um recurso muito bom para cenários "principais" por vários motivos. Uma explicação completa seria bastante longa; a breve explicação é que ela cria programas que funcionam imprevisivelmente e por acidente e dificulta a execução do mesmo código por meio de vários compiladores ou de várias versões do mesmo compilador. As grandes despesas adicionadas pelo recurso não são justificadas pelos pequenos benefícios.
Peter Torr, que gerenciou o recurso de volta no dia, discute brevemente neste post de 2003 .
Embora exponha esse recurso por meio das APIs de hospedagem de scripts do mecanismo JScript .NET, não conheço nenhum cliente real que já o tenha usado.
fonte
A primeira coisa que me vem à mente é a inserção automática de ponto e vírgula do Javascript . Um recurso horrível e horrível que nunca deveria ter chegado ao idioma.
Isso não quer dizer que não poderia ter feito um trabalho melhor. Se ele olhou para a frente no seguinte a linha, então ele pode ser capaz de fazer uma estimativa melhor como a intenção do programador, mas no final do dia, se há múltiplas maneiras válidas a sintaxe poderia ter ido, então não há realmente nenhum substituto para o programador ser explícito.
fonte
Parece-me que, se um compilador puder corrigir uma sintaxe incorreta, essa sintaxe deverá ser documentada no idioma.
O motivo dos erros de sintaxe é porque um analisador não pôde criar a árvore de sintaxe abstrata fora do programa. Isso acontece quando um token está fora do lugar. Para adivinhar onde esse token deve estar, se deve ser removido ou se algum outro token deve ser adicionado para corrigir o erro, você precisará de algum tipo de computador que possa adivinhar a intenção de um programador. Como uma máquina poderia adivinhar isso:
Era suposto ser:
Ele poderia facilmente ser qualquer um dos seguintes:
56
,5 - 6
,5 & 6
. Não há como um compilador saber.Essa tecnologia ainda não existe.
fonte
Embora não seja exatamente a mesma coisa, é por isso que o HTML se transformou no desastre. Os navegadores toleraram a marcação incorreta e, em seguida, o navegador A não conseguiu renderizar da mesma maneira que o navegador B (sim, existem outros motivos, mas esse foi um dos poucos mais importantes, especialmente cerca de 10 anos atrás, antes que algumas regras de folga se tornassem convenções )
Como Eric Lippert deduz, muitas dessas coisas são melhor tratadas pelo IDE, não pelo compilador. Vamos ver o que os bits automáticos estão tentando estragar para você.
A estratégia que acho predominante agora é o aprimoramento contínuo da linguagem, em vez de afrouxar o compilador: se realmente é algo que o compilador pode descobrir automaticamente, introduza uma construção de linguagem bem definida em torno dele.
O exemplo imediato que vem à mente são as propriedades automáticas em C # (não o único idioma que possui algo semelhante): dado que a maioria dos getters / setters em qualquer aplicativo são realmente apenas invólucros em torno de um campo, permita ao desenvolvedor indicar seus intenção e deixe o compilador injetar o resto.
O que me leva a pensar: a maioria das linguagens no estilo C já faz isso em certa medida. Para coisas que podem ser descobertas automaticamente, basta refinar a sintaxe:
Pode ser reduzido para:
No final, acho que tudo se resume a isso: a tendência é que você não torne o compilador "mais inteligente" ou "mais flexível". É a linguagem que se torna mais inteligente ou mais flexível.
Além disso, muita "ajuda" pode ser perigosa, como o bug clássico "se":
fonte
if (x && y) dothis(); else dothat();
ficaria um pouco melhor.true
oufalse
.Quando eu estava codificando FORTRAN e PL / I no final dos anos 80 e início dos anos 90 nos sistemas de minicomputadores e mainframe DEC e IBM, pareço lembrar que os compiladores efetuavam logoff regularmente de mensagens como "erro blá blá; assumindo blá blá e continuando .." . " Naquela época, esse era um legado dos dias (ainda antes, antes do meu tempo) de processamento em lote e cartões perfurados, quando havia provavelmente uma enorme espera entre o envio do código para execução e a recuperação dos resultados. Portanto, fazia muito sentido que os compiladores tentassem adivinhar o programador e continuar, em vez de abortar, o primeiro erro encontrado. Veja bem, não me lembro das "correções" serem particularmente sofisticadas. Quando finalmente mudei para estações de trabalho Unix interativas (Sun, SGI, etc.),
fonte
O objetivo de um compilador é produzir executáveis que se comportem conforme desejado. Se um programador escreve algo inválido, mesmo que o compilador consiga adivinhar com 90% de probabilidade o que foi planejado, geralmente é melhor exigir que o programador conserte o programa para esclarecer a intenção do que fazer com que o compilador vá em frente e produza um executável o que teria uma chance significativa de ocultar um bug.
Obviamente, as linguagens geralmente devem ser projetadas para que o código que expressa claramente a intenção seja legal, e o código que não expressa claramente a intenção seja proibido, mas isso não significa que seja. Considere o seguinte código [Java ou C #]
Ter um compilador adicionando uma conversão de texto implícita para a atribuição
f1
seria útil, pois há apenas uma coisa lógica que o programador pode quererf1
conter (ofloat
valor mais próximo de 1/10). Porém, em vez de incentivar os compiladores a aceitar programas impróprios, seria melhor para as especificações permitirem conversões implícitas de duplo para flutuar em alguns contextos. Por outro lado, a atribuição ded1
pode ou não ser o que o programador realmente pretendia, mas não há nenhuma regra de idioma que o proíba.Os piores tipos de regras de linguagem são aqueles em que os compiladores farão inferências nos casos em que algo não poderia ser legitimamente compilado de outra forma, mas onde um programa pode "acidentalmente" ser válido no caso em que a inferência foi planejada. Muitas situações envolvendo final de declaração implícito se enquadram nessa categoria. Se um programador que pretende escrever duas instruções separadas omitir um terminador de instruções, um compilador geralmente consegue inferir o limite da instrução, mas ocasionalmente pode considerar uma instrução como algo que deveria ser processado como duas.
fonte
Os erros de sintaxe são especialmente difíceis de corrigir. Tome o caso de um direito que falta
)
: sabemos que podemos reparar o código inserindo um, mas geralmente há muitos lugares onde podemos inserir um e obter um programa sintaticamente correto.Um ponto muito mais fácil são os identificadores com erros ortográficos (mas observe que não são erros de sintaxe). Pode-se calcular a distância de edição entre o identificador não resolvível e todos os identificadores no escopo e, substituindo a palavra não resolvível pela que o usuário provavelmente quis dizer, seria possível criar um programa correto em muitos casos. Entretanto, ainda é melhor sinalizar o erro e permitir que o IDE sugira substituições válidas.
fonte
Um compilador desse tipo seria simplesmente uma implementação descontraída e não padrão de qualquer linguagem que esteja compilando.
fonte
Foi testado várias vezes, mas muitas vezes não alcançou o efeito desejado: pense no HAL 9000 ou no GlaDOS.
fonte
Em C, você não pode passar matrizes por valor, mas o compilador permite que você escreva:
que é reescrito silenciosamente como:
Quão estúpido é isso? Eu preferiria um erro grave aqui em vez de reescrever silenciosamente, porque essa regra especial levou muitos programadores a acreditar que matrizes e ponteiros são basicamente a mesma coisa. Eles não são.
fonte