Derivando a expressão regular para estilo C / ** / comentários


8

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?


2
Observe que essa abordagem evitará comentários aninhados. Se você estiver criando um analisador completo de qualquer maneira, considere analisar os comentários do bloco "corretamente". além de ser mais claro, você também pode ler meta-dados estruturados dos comentários, se desejar.
Raphael

Os fragmentos foram (!\*)planejados? Você quer dizer a notação mais comum [^*]? E o que (!*|!/)?
Gilles 'SO- stop be evil'

@ Gilles: eu atualizei a expressão. (! * |! /) pretende ser algo que não é * ou /.
Alex-Brink

@ Rafael, em comentários C não aninhar .
vonbrand

@ vonbrand: "C-style" não é muito específico, portanto, mencionar que um "aprimoramento natural" não é possível é um ponto válido.
frafl

Respostas:


6

Eu posso pensar em quatro maneiras:

  1. 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).

  2. Escreva vários casos de teste e aplique sua expressão regular a eles.

  3. Converta o autômato definido no ponto 1 em uma expressão regular, usando técnicas padrão.

  4. Uma combinação dos anteriores.


5

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:

1. Exceto dentro de uma constante de caractere, uma string literal ou um comentário, os caracteres /* introduzem um comentário. O conteúdo desse comentário é examinado apenas para identificar caracteres multibyte e encontrar os caracteres */que o encerram.

2. Exceto dentro de uma constante de caractere, uma string literal ou um comentário, os caracteres //introduzem um comentário que inclui todos os caracteres multibyte, até, mas não incluindo, o próximo caractere de nova linha. O conteúdo desse comentário é examinado apenas para identificar caracteres multibyte e encontrar o caractere de nova linha final.

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:

  • No estado inicial, /seguido por *entra no estado de comentário em várias linhas e /seguido por /entra no estado de comentário em linha única.
  • No estado de comentário em várias linhas, *seguido de /entra no estado de pós-comentário.
  • No estado de comentário em linha única, uma nova linha entra no estado de pós-comentário.
  • Qualquer outro caractere deixa o estado inalterado.

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.


Uma pesquisa no Google Livros fornece esta referência para o algoritmo de Kleene: books.google.co.uk/…
rgrig 13/03/2012

0

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 flexexemplos 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).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.