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:
- 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
ounão
conforme ou não. - Eficiente: O número de passos referido no passo anterior não deve ser "muito maior" que o comprimento da palavra.
- 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
- Se
e
for uma especificação formal de uma linguagem de programaçãoL
:PL = Super(e)
. - Seja
p
uma palavra.PL(p)
éverdade
oufalso
conformep in L
ou não. - Tanto
Super
quantoPL
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:
- Sempre que possível não se usa o símbolo da concatenação. Isto é, em vez de escreve-se .
- A iteração tem precedência sobre e sobre . Isto é, é , não . Igualmente, é , não .
- 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 Regular Tipo Sub-Grafo símbolo ou concatenação união iteração
Por exemplo, o diagrama da expressão regular pode ser obtido da seguinte forma:
Operação | Diagrama |
---|---|
Início | |
Concatenação | |
Iterações | |
Uniões |
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ção | Diagrama |
---|---|
Simplificação |
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
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ção | Diagrama |
---|---|
Simplificação (II) |
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:
- Dada uma linguagem regular , como obter um sistema computável e eficiente para determinar se ?
- 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
ouJava
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.