Basicamente o lex necessita da especificação da linguagem na forma de expressão regular e de um conjunto de funções adicionais para a manipulação dos tokens gerados, em particular de funções que trabalhem com a tabela de símbolos.
A geração do código do scanner é feita com
a execução do comando
lex arquivo_fonte
O arquivo com o fonte do lex é dividido em três partes, todas separadas pelo token "%%". Elas são:
delimitador | [ \t\n] |
brancos | {delimitador}+ |
letra_maiusc | [A-Z] |
letra_minusc | [a-z] |
letra | {letra_maiusc}|{letra_minusc} |
digito | [0-9] |
identificador | {letra}({letra}|{digito})* |
numero | {digito}+ |
while | { return (WHILE); } |
{identificador} | { mkname(); return IDENT; } |
{numero} | { mkval(); return INTNUM; } |
void mkname ( )
{ do do do do
}
void mkval ( )
{ da da da da
}
No ambiente unix existem outros pares que podem substituir o lex-yacc, sendo que a melhor escolha recai no par flex-bison, em que o flex substitui o lex, enquanto o bison substitui o yacc. Em particular, a implementação do scanner a partir do flex é muito superior âgrave; obtida pelo lex, sendo totalmente compatível com o yacc. Assim, mesmo usando o yacc é preferível que se use o lex. De qualquer forma, os dois pares aceitam os mesmos arquivos fonte para a definição da linguagem, de modo que não é preciso escolher um deles a priori.
O formato de um arquivo yacc é mais complexo do que o do lex. Ele também é composto por partes de definição, corpo e adicionais, com uma sintaxe bastante diferenciada no corpo, mesmo porque enquanto no lex a gramática é uma gramática regular, no yacc temos uma gramática de atributos (que é uma gramática livre de contexto acrescida de atributos para a manipulação semântica de contexto).
O problema na especificação do corpo de um arquivo yacc é o fato de uma gramática exibir derivações bastante distintas a partir de um mesmo símbolo não-terminal. Todas essas derivações devem aparecer no corpo, sendo que a ordem em que as mesmas aparecem acaba influenciando a forma como o yacc determina as possíveis construções da linguagem. Isso demanda um cuidado grande no momento de construir a gramática da linguagem, caso não se queira perder um tempo considerável eliminando ambiguidades inexistentes.
Aqui voce vê um exemplo de arquivo de definicao do yacc.