Desejo analisar idiomas específicos do domínio definido pelo usuário. Essas linguagens são tipicamente próximas de notações matemáticas (não estou analisando uma linguagem natural). Os usuários definem sua DSL em uma notação BNF, assim:
expr ::= LiteralInteger
| ( expr )
| expr + expr
| expr * expr
O tipo de entrada 1 + ( 2 * 3 )
deve ser aceito, enquanto o tipo de entrada 1 +
deve ser rejeitado como incorreto e o tipo de entrada 1 + 2 * 3
deve ser rejeitado como ambíguo.
Uma dificuldade central aqui é lidar com gramáticas ambíguas de uma maneira fácil de usar. Restringir que a gramática seja inequívoca não é uma opção: é assim que a linguagem é - a idéia é que os escritores preferem omitir parênteses quando não são necessários para evitar ambiguidade. Desde que uma expressão não seja ambígua, preciso analisá-la e, se não for, preciso rejeitá-la.
Meu analisador deve trabalhar com qualquer gramática livre de contexto, mesmo ambígua, e deve aceitar todas as informações inequívocas. Eu preciso da árvore de análise para todas as entradas aceitas. Para entradas inválidas ou ambíguas, idealmente, quero boas mensagens de erro, mas, para começar, aceitarei o que conseguir.
Normalmente invocarei o analisador em entradas relativamente curtas, com as entradas mais longas ocasionais. Portanto, o algoritmo assintoticamente mais rápido pode não ser a melhor escolha. Eu gostaria de otimizar para uma distribuição de cerca de 80% de entradas com menos de 20 símbolos, 19% entre 20 e 50 símbolos e 1% de entradas mais raras. A velocidade de entradas inválidas não é uma grande preocupação. Além disso, espero uma modificação do DSL em torno de cada 1000 a 100000 entradas; Posso passar alguns segundos processando minha gramática, e não alguns minutos.
Quais algoritmos de análise devo investigar, dados meus tamanhos de entrada típicos? O relatório de erros deve ser um fator na minha seleção ou devo me concentrar na análise de entradas não ambíguas e possivelmente executar um analisador mais lento e completamente separado para fornecer feedback de erro?
(No projeto em que eu precisava disso (um tempo atrás), usei o CYK , que não era muito difícil de implementar e funcionou adequadamente para meus tamanhos de entrada, mas não produziu erros muito agradáveis.)
x+y+z
.
+
, portanto x+y+z
é realmente ambíguo, portanto, errôneo.