Um analisador sintático para uma gramática é um programa que
aceita como entrada uma sentença (uma lista de símbolos
) e
constrói para a sentença sua árvore gramatical (ou equivalentemente
uma seqüência de derivação) ou, caso a sentença não pertença à
linguagem descrita por
, uma indicação de erro.
Duas técnicas básicas para a contrução de analisadores sintáticos são a construção ascendente ou a construção descendente. Na contrução ascendente (bottom-up), o analisador sintático varre a sentença buscando aplicar produções que permitam substituir seqüências de símbolos da sentença pelo lado esquerdo das produções, até alcançar como único símbolo restante o símbolo sentencial.
O Algoritmo 3.3 ilustra a estratégia de reconhecimento
de sentença baseado em construção ascendente da árvore sintática.
Esse algoritmo recebe como entrada uma representação da gramática
e a lista
de símbolos terminais que compõem a
sentença. A saída é uma indicação se a sentença pertence
(true) ou não (false) à gramática
. Para a
descrição desse algoritmo, as seguintes funções são definidas:
Esse algoritmo apresenta duas condições de término possíveis: a primeira quando a sentença pode ser reduzida ao símbolo sentencial da gramática (condição de sucesso) e a segunda quando a sentença não está reduzida ao símbolo sentencial e não há mais regras aplicáveis à sentença (condição de rejeição).
Na construção descendente (top-down), o objetivo é iniciar a análise com uma lista que contém inicialmente apenas o símbolo sentencial; a partir da análise dos símbolos presentes na sentença, busca-se aplicar regras que permitam expandir os símbolos na lista até alcançar a sentença desejada.
Na construção descendente, o objetivo é obter uma derivação mais à esquerda para uma sentença. Em termos de árvores gramaticais, a construção descendente busca a construção de uma árvore a partir da raiz usando pré-ordem para definir o próximo símbolo não-terminal que deve ser considerado para análise e expansão.
Pela forma como a técnica de construção descendente opera, ela não pode ser aplicada a gramáticas com produções recursivas à esquerda, ou seja, que contenham regras da forma
É possível transformar uma produção recursiva à esquerda em uma
recursiva à direita que descreve as mesmas sentenças através da
seguinte técnica. Sejam e
duas seqüências de
símbolos que não sejam iniciadas pelo símbolo não-terminal
e
sejam as produções para
:
![]() |
![]() |
|
![]() |
![]() |
![]() |
![]() |
|
![]() |
![]() |
|
![]() |
![]() |
Os primeiros compiladores usavam essencialmente dois tipos de analisadores sintáticos. Analisadores baseados em precedência de operadores utilizam a técnica de construção ascendente combinada com informação sobre a precedência e associatividade de operadores da linguagem para guiar suas ações, sendo adequados à análise de expressões aritméticas. Analisadores do tipo descendentes recursivos implementam a técnica de construção descendente através de um conjunto de rotinas mutualmente recursivas para realizar a análise, sendo normalmente utilizados para outros comandos que não expressões aritméticas.