Estou trabalhando em um analisador para uma linguagem no estilo C e, para esse analisador, preciso da expressão regular que corresponda ao estilo C / ** / comentários. Agora, encontrei esta expressão na web:
/\*([^\*]*\*+[^\*/])*([^\*]*\*+|[^\*]*\*/
No entanto, como você pode ver, essa é uma expressão bastante confusa e não tenho idéia se ela realmente corresponde exatamente ao que eu quero que ela corresponda.
Existe uma maneira diferente de definir (rigorosamente) expressões regulares que são fáceis de verificar manualmente que elas estão realmente corretas e depois são conversíveis ('compiláveis') para a expressão regular acima?
compilers
parsers
regular-languages
Alex ten Brink
fonte
fonte
(!\*)
planejados? Você quer dizer a notação mais comum[^*]
? E o que(!*|!/)
?Respostas:
Eu posso pensar em quatro maneiras:
Defina um autômato para o idioma de seu interesse. Converta a expressão regular em um autômato (usando os derivados de Brzozowski). Verifique se os dois autômatos aceitam o mesmo idioma (determine e minimize ou use um argumento de bisimulação).
Escreva vários casos de teste e aplique sua expressão regular a eles.
Converta o autômato definido no ponto 1 em uma expressão regular, usando técnicas padrão.
Uma combinação dos anteriores.
fonte
Se você quiser ter certeza de que está analisando comentários em C, precisará confrontar seu modelo com a especificação C. C99 §6.4.9 define a sintaxe dos comentários da seguinte maneira:
Esta é uma prosa inglesa, não uma definição formal, mas há uma interpretação razoavelmente clara em termos de um autômato finito não determinístico (NFA) que consome um comentário:
/
seguido por*
entra no estado de comentário em várias linhas e/
seguido por/
entra no estado de comentário em linha única.*
seguido de/
entra no estado de pós-comentário.Observe que, para saber se o estado inicial se aplica, é necessário executar um pouco mais de análise para detectar cadeias de caracteres e literais de caracteres.
Depois de ter um NFA, você pode usar técnicas padrão para criar uma expressão regular (não as vejo nos artigos da Wikipedia, mas elas devem ser discutidas nos livros didáticos).
Se você já possui uma expressão regular e deseja testá-la, pode comparar sua linguagem gerada com a linguagem NFA deduzida da especificação de linguagem: a igualdade de linguagens regulares é decidível. Uma maneira de decidir a igualdade é construir um autômato determinístico mínimo para cada um; se os idiomas forem equivalentes, os DFAs mínimos serão isomórficos.
fonte
Se você estiver escrevendo um analisador, esse tipo de material é tratado pelo analisador lexical. E aí você pode expressar isso com expressões regulares, ou (como os
flex
exemplos que eu vi mostrar) apenas "escape para a linguagem subjacente" e finalize o trabalho lá. Ou seja, vendo/*
apenas pular adiante até encontrar*/
(um DFA para isso é fácil de construir e, a partir daí, um fragmento C é simples de escrever).fonte