Uma gramática é geralmente definida como uma gramática livre de contexto - uma definição precisa é dada na página da Wikipedia, mas funciona da mesma forma que no PLY, que é baseado no Bison , que por sua vez é baseado no yacc .
Diz aqui que PLY usa um analisador LALR . Este é essencialmente um analisador LR onde as tabelas de pesquisa são condensadas, possivelmente introduzindo conflitos de análise, reduzindo parte da expressividade de uma gramática LR (ou seja, uma gramática livre de contexto que um analisador LR pode analisar). Se você deseja conhecer as limitações desse ramo específico de analisadores e de outros analisadores, é apresentada aqui uma visão geral de todos os tipos de técnicas de análise (LL, LR e outras) .
Para responder sua pergunta: existem algoritmos de análise capazes de analisar qualquer linguagem sem contexto, mesmo que a linguagem seja ambígua (ou seja, há mais de uma maneira de interpretar a entrada):
O(n3|G|)n|G|
O(n3)O(n2)
Aqui você encontra um artigo discutindo uma implementação prática (uma adaptação) do algoritmo de Earley. Eles concluem: "Dada a generalidade da análise de Earley em comparação com a análise LALR (1) ((que é aproximadamente o que PLY faz)), e considerando que mesmo o pior momento dos PEP ((sua implementação do algoritmo de Earley)) não seria percebido por um usuário, este é um excelente resultado ".
O último tipo de analisador é o analisador GLR . Esta é uma versão generalizada da análise de LR, capaz de analisar qualquer linguagem sem contexto.
Uma implementação madura do GLR é ASF + SDF . O Bison também pode gerar um analisador GLR, embora suas implementações sejam ligeiramente diferentes do algoritmo GLR 'padrão'. O algoritmo Elkhound é um algoritmo híbrido GLR / LALR. Ele usa LALR quando possível e GLR quando necessário, para ser rápido e capaz de analisar qualquer gramática.
Além das gramáticas livres de contexto, existem gramáticas sensíveis ao contexto , mas geralmente são difíceis de analisar e não acrescentam muita expressividade: você pode fazer mais com elas, mas para a maioria dos aplicativos os usos extras não são relevantes, a menos que você esteja analisando uma linguagem natural.
Como etapa final, existem gramáticas irrestritas . Nesse ponto, a gramática está completa em Turing, portanto, não há limites quanto ao tempo necessário para analisar um idioma específico, o que é indesejável para a maioria dos aplicativos de análise. A energia extra quase nunca é necessária. Se você deseja usar todo esse poder, existe a máquina de idiomas disponível.
Por fim, implementar seu próprio analisador-gerador não é um assunto trivial, principalmente para que ele seja rápido. Pessoalmente, acabei de criar minha própria versão do flex (o gerador de lexer) e, embora isso parecesse um exercício de problemas algorítmicos relativamente simples, ficou bastante complexo acertar, principalmente quando tentei dar suporte ao Unicode. Considere usar uma implementação já existente em vez de escrever sua própria.