Gramáticas de tipo 3 são adequadas para representar algumas ``características locais'' de linguagens de programação, tais como definição de formatos de constantes, identificadores e palavras da linguagem. Por exemplo, uma típica definição de identificadores pode ser expressa em uma gramática
![]() |
![]() |
|
![]() |
![]() |
Uma forma equivalente de definir símbolos ou sentenças que podem ser
gerados por gramáticas de tipo 3 é através de expressões regulares.
Dado um alfabeto , então são expressões regulares em
:
Se e
são expressões regulares em A, então também o serão:
Expressões regulares podem ser vistas como expressões criadas a partir da
aplicação de três operadores, concatenação, e
, sendo que
tem a maior precedência e
, a menor. O operador
é comutativo e associativo, enquanto que concatenação é associativa mas não
comutativa.
No exemplo de identificadores, a expressão regular que descreve um identificador é
Diz-se que uma expressão regular gera um conjunto regular. Um dado conjunto regular pode ser gerado por mais de uma expressão regular. Entre as propriedades que tornam expressões regulares atraentes do ponto de vista de programadores de sistema estão
Entretanto, expressões regulares têm muitas limitações. Por exemplo, não é possível expressar através de uma gramática de tipo 3 ou de uma expressão regular sentenças na forma de delimitadores balanceados, tais como (()(())). Entretanto, tais sentenças podem ser facilmente descritas por gramáticas livres de contexto, tal como
![]() |
![]() |
|
![]() |
![]() |
|
![]() |
![]() |
Tais tipos de situações são recorrentes em linguagens de programação, onde pares de delimitadores -- tais como ( e ), { e }, [ e ] em C, ou begin e end em Pascal -- devem ocorrer de forma balanceada.