Linguagens e Expressões Regulares

Uma forma de especificação formal de linguagens.

Na secção anterior observou-se que para definir uma linguagem de programação o fecho, , não é adequado porque tem "demasiadas" palavras.

Mais precisamente, a situação é a seguinte:

Para definir uma linguagem de programação começa-se for escolher um certo alfabeto e, sobre esse alfabeto, define-se uma linguagem cujas palavras são exatamente os programas válidos da linguagem de programação.

O Problema Principal de ALP (versão 0)Dada uma linguagem e uma palavra no mesmo alfabeto, determinar se – não desenvolve condições para determinar . É necessário um "sistema" que permita definir linguagens formais e que seja:

  1. Computável: Existe um algoritmo que recebe como entrada uma palavra e ao fim de um número finito de passos produz uma resposta sim ou não conforme ou não.
  2. Eficiente: O número de passos referido no passo anterior não deve ser "muito maior" que o comprimento da palavra.
  3. Adequado: Deve ser possível definir (os programas de) qualquer linguagem de programação.

Portanto:

Problema Principal de ALP (versão 1): Determinar um sistema computável e eficiente para determinar se e que seja adequado (i.e., é uma linguagem de programação).

Linguagens Regulares

As operações entre linguagens (principalmente, a união, a concatenação e o fecho) permitem começar por linguagens muito simples e definir formalmente, rigorosamente, sem ambiguidades, linguagens mais complexas. Por exemplo, a partir do alfabeto binário , a linguagem das palavras com um número par de é .


O ênfase em "formal, rigoroso, não ambíguo" é necessário para resolver algoritmicamente o Problema Principal de ALP. Mais especificamente, pretende-se obter um programa que tem como entrada uma especificação formal de uma linguagem e que produz um segundo programa que tem como entrada uma palavra e que determina se essa palavra pertence, ou não, à linguagem dada ao primeiro programa. Isto é, pretende-se definir um programa Super tal que

  1. Se e for uma especificação formal de uma linguagem de programação L: PL = Super(e).
  2. Seja p uma palavra. PL(p) é verdade ou falso conforme p in L ou não.
  3. Tanto Super quanto PL devem ser eficientes.

O Problema Principal de ALP, nas suas várias versões, trata de encontrar uma "especificação formal" adequada e obter os programas Super e PL. De facto, a resolução seguida em ALP até vai mais longe: A resposta a é calculada de forma que quando for um programa válido (isto é, "" é verdade) também se obtém uma "representação intermédia" de , apta a ser executada.


Por enquanto define-se a classe das linguagens regulares:

Linguagem Regular (LR). Seja um alfabeto. Uma linguagem regular sobre define-se recursivamente pelas seguintes regras:

  • base Os conjuntos e, para cada são linguagens regulares.
  • passo Se e forem linguagens regulares então também são linguagens regulares.
  • fecho Um conjunto de palavras é uma linguagem regular se, e só se, pode ser definido através de um número finito de aplicações do passo a partir dos conjuntos da base.

Alguns exemplos de linguagens regulares:

  • .
  • Qualquer linguagem finita.
  • O conjunto das palavras que começam em é infinito mas regular: .

Expressões Regulares

A notação usual dos conjuntos, com , etc. torna difícil escrever e ler linguagens regulares. Para aliviar esse problema usa-se uma notação específica.

Expressão Regular (ER). Seja um alfabeto. Uma expressão regular sobre define-se recursivamente pelas seguintes regras:

  • base As expressões vazio , palavra vazia e, para cada são expressões regulares.
  • passo Se e forem expressões regulares então a união , a concatenação (ou produto) e a iteração também são expressões regulares.
  • fecho Uma expressão é uma expressão regular se, e só se, pode ser definida através de um número finito de aplicações do passo a partir das expressões da base.

Alguns exemplos de expressões regulares:

  • .
  • Qualquer palavra de .
  • .

Antes de avançar no estudo das ER e LR é importante esclarecer o seguinte ponto importante sobre a notação das expressões regulares:

Regras de Simplificação das Expressões Regulares. A escrita completa de uma expressão regular pode (ainda) ser confusa, por causa dos parêntesis:

Para simplificar esta escrita usam-se as seguintes regras de simplificação:

  1. Sempre que possível não se usa o símbolo da concatenação. Isto é, em vez de escreve-se .
  2. A iteração tem precedência sobre e sobre . Isto é, é , não . Igualmente, é , não .
  3. A concatenação tem precedência sobre a união . Isto é, é , não .

Com estas regras a ER acima fica com o seguinte aspeto:


Diagramas das Expressões Regulares

As expressões regulares podem ser representadas por um diagrama gráfico cuja visualização pode ajudar a entender a sua estrutura.

Diagrama de uma Expressão Regular (Diagrama de Wirth). O diagrama de uma expressão regular é um grafo orientado definido para as operações base e passo da seguinte forma:

Forma da Expressão RegularTipoSub-Grafo
símbolo ou re-symbol
concatenaçãore-concat
uniãore-union
iteraçãore-star

Por exemplo, o diagrama da expressão regular pode ser obtido da seguinte forma:

OperaçãoDiagrama
Iníciore-exemplo-01
Concatenaçãore-exemplo-02
Iteraçõesre-exemplo-03
Uniõesre-exemplo-04

No diagrama final há várias arestas que podem ser eliminadas e ainda continuar a representar a expressão regular inicial. Por exemplo, uma das duas arestas consecutivas, no cento do diagrama, pode ser eliminada.

OperaçãoDiagrama
Simplificaçãore-exemplo-05

Neste caso foi simples detetar uma aresta que podia ser eliminada. Em geral, quais são as arestas que podem ser eliminadas?

Teorema da Eliminação de Arestas Vazias. A aresta fig-teo-arestas-vazias pode ser eliminada se:

  • O vértice não é final e não saem mais arestas de ou
  • O vértice não é inicial e não entram mais arestas em .

Alternativamente, a aresta não pode ser eliminada se:

  • O vértice é final ou saem mais arestas de e
  • O vértice é inicial ou entram mais arestas em .

Usando o teorema da eliminação de arestas vazias:

OperaçãoDiagrama
Simplificação (II)re-exemplo-06

Semântica das Expressões Regulares

O número quatro pode ser referido de várias formas: IV, 100, 4, quatro, 2+2, etc. Todas essas formas são expressões – texto, sintaxe – cuja interpretação – significado, semântica – é um certo objeto abstrato.

Esta é também a relação entre as linguagens regulares e as expressões regulares: As linguagens são conjuntos (objetos matemáticos, abstratos) que podem ser representados por certas expressões. Isto é, a semântica das ER são as LR. Reciprocamente, as ER são uma sintaxe para as LR. Mais precisamente:

Linguagem Representada por uma Expressão Regular. Qualquer expressão regular sobre representa uma certa linguagem, definida pelas seguintes regras:

  • .
  • .
  • Para cada .
  • Se for uma expressão regular então .
  • Se forem expressões regulares então .
  • Se forem expressões regulares então .

Até aqui, e neste enunciado em particular, estão a ser usados os mesmos símbolos (sintaxe), por exemplo com significados (semântica) muito diferentes. Por exemplo, "" numa ER é apenas um símbolo que liga outras ERs — da mesma forma que + liga \quaddois números\quad duas expressões numéricas. Mas "" numa LR é uma operação entre conjuntos, que tem um valor bem definido — tal como 2 + 2 tem um valor bem definido (sob as convenções comuns).

Além disso, foi apenas definida uma função entre ERs e certos conjuntos de palavras – nada afirma, até aqui, que é regular. Isto é, se for uma expressão regular então é uma linguagem. A relação com as linguagens regulares fica esclarecida a seguir:

Equivalência de Expressões e Linguagens Regulares.

  • Cada expressão regular representa uma linguagem regular. Mais especificamente: Se for uma expressão regular sobre então é uma linguagem regular sobre .
  • Cada linguagem regular pode ser representada por uma expressão regular. Mais especificamente: Se for uma linguagem regular sobre então existe uma expressão regular sobre , , tal que .

Isto é, as expressões regulares denotam exatamente as linguagens regulares e a relação entre umas e outras é a função . Dito de outra forma, as LR são a semântica associada às ER e, reciprocamente, as ER proporcionam uma sintaxe para as LR.

Por exemplo, a linguagem dos inteiros sem sinal e sem à esquerda (isto é, a representação binária dos números inteiros positivos):


Há ainda outro tipo importante de equivalência: Depois de fixado o conjunto de símbolos e de operações, duas expressões (sintaxes) muito diferentes podem ter o mesmo valor (semântica).

Por exemplo o número quatro (o objeto matemático abstrato) pode ser representado pelas expressões , , , etc. Nestes casos escreve-se , etc. Mas em ALP é preciso cuidado com o sinal "". As expressões "" e "" são sintaticamente diferentes (por exemplo, porque "" tem apenas um símbolo e "" tem três) mas equivalentes (a mesma semântica).

Nas linguagens regulares "" representa a igualdade entre conjuntos, uma relação matemática. No caso das expressões regulares é necessário esclarecer se se trata de igualdade sintática ou de uma equivalência (isto é, uma igualdade semântica). Por exemplo, e são diferentes ao nível sintático: diferem logo no primeiro símbolo. Mas ambas representam a mesma linguagem regular, o conjunto . Isto é, .

Equivalência de Expressões Regulares. Duas expressões regulares, , sobre são equivalentes, , se .

No uso comum de expressões regulares pretende-se usar a equivalência, não a igualdade sintática, pelo que "" normalmente representa a equivalência, apesar de esta escrita ser um abuso da notação. Isto é, escreve-se em vez de , porque é mais conveniente. Os casos em que se trata a igualdade sintática devem ser explicitamente assinalados como tais.


Propriedades das Expressões Regulares

Sejam expressões regulares sobre o alfabeto . Considerando as operações de união e concatenação:

Para o fecho:

Com estas equivalências uma ER inicialmente complicada (isto é, comprida e/ou profunda) pode ser simplificada. Um exemplo imediato é . Outro exemplo:

Aplicando as regras de equivalência


As linguagens e expressões regulares são o passo atual para resolver o Problema Principal de ALP (versão 1)Determinar um sistema computável, eficiente e adequado para definir linguagens de programação.

Nesse sentido importa responder às seguintes questões:

  1. Dada uma linguagem regular , como obter um sistema computável e eficiente para determinar se ?
  2. As linguagens regulares são adequadas para definir todas as linguagens de programação? Por exemplo, será possível definir a sintaxe dos programas Python ou Java usando apenas expressões regulares?

Estas questões são resolvidas no próximo capítulo, Autómatos Finitos, onde é definido e estudado um modelo abstrato de computador simples e como este se relaciona com as ER e LR.