Material de Apoio para o Projecto
O compilador, escrito em C++, realiza as seguintes etapas de análise para implementar a linguagem:
- análise lexical (gerador de analisadores lexicais GNU Flex 2.5.35);
- sintáctica (gerador de analisadores LALR(1) byacc 1.9 -- não utilizar outros, pois podem ser incompatíveis com o restante material de apoio;
- análise semântica e geração de código (CDK5, RTS e extensões); e
- compilação de assembly (ferramenta yasm -- ambiente de teste: linux-elf-i386).
|
|
As bibliotecas CDK e RTS de apoio ao desenvolvimento do projecto são de uso obrigatório:
O acesso ao material de apoio não público realiza-se mediante autenticação Fénix. O compilador Compact exemplifica a utilização destas bibliotecas:
|
|
As ferramentas Flex e byacc estão disponíveis para a maioria dos sistemas actuais, bastando recorrer ao repositório de software correspondente:
- A versão Flex da máquina oficial é a distribuída com o sistema OpenSUSE 11.1.
- A versão byacc é byacc-1.9-39.1.src.rpm (usar o comando " rpmbuild --rebuild byacc-1.9-39.1.src.rpm" para obter o pacote instalável -- este pacote pode também ser obtido de http://software.opensuse.org/search). Antes de instalar esta versão, verificar se o sistema em uso disponibiliza uma própria.
O compilador pf2asm permite compilar directamente código Postfix. É também um exemplo (tal como o Compact) de uso d o restante material de apoio. Este compilador é de utilização opcional (é independente da realização do projecto), mas pode ser útil para a realização de testes de protótipos de geração de código.
-
pf2asm (lite)
pf2asm-lite-201005172136.tar.bz2
- byacc-1.9-39.1.src.rpm
- compact-201003221835.tar.bz2
- libcdk5-201003221835.tar.bz2
- librts-201003221835.tar.bz2
- pf2asm-lite-201005172136.tar.bz2
Material de Apoio para o Projecto
O compilador, escrito em C++, realiza as seguintes etapas de análise para implementar a linguagem:
- análise lexical (gerador de analisadores lexicais GNU Flex 2.5.35);
- sintáctica (gerador de analisadores LALR(1) byacc 1.9 -- não utilizar outros, pois podem ser incompatíveis com o restante material de apoio;
- análise semântica e geração de código (CDK5, RTS e extensões); e
- compilação de assembly (ferramenta yasm -- ambiente de teste: linux-elf-i386).
|
|
As bibliotecas CDK e RTS de apoio ao desenvolvimento do projecto são de uso obrigatório:
O acesso ao material de apoio não público realiza-se mediante autenticação Fénix. O compilador Compact exemplifica a utilização destas bibliotecas:
|
|
As ferramentas Flex e byacc estão disponíveis para a maioria dos sistemas actuais, bastando recorrer ao repositório de software correspondente:
- A versão Flex da máquina oficial é a distribuída com o sistema OpenSUSE 11.1.
- A versão byacc é byacc-1.9-39.1.src.rpm (usar o comando " rpmbuild --rebuild byacc-1.9-39.1.src.rpm" para obter o pacote instalável -- este pacote pode também ser obtido de http://software.opensuse.org/search). Antes de instalar esta versão, verificar se o sistema em uso disponibiliza uma própria.
O compilador pf2asm permite compilar directamente código Postfix. É também um exemplo (tal como o Compact) de uso d o restante material de apoio. Este compilador é de utilização opcional (é independente da realização do projecto), mas pode ser útil para a realização de testes de protótipos de geração de código.
-
pf2asm (lite)
pf2asm-lite-201005172136.tar.bz2
- byacc-1.9-39.1.src.rpm
- compact-201003221835.tar.bz2
- libcdk5-201003221835.tar.bz2
- librts-201003221835.tar.bz2
- pf2asm-lite-201005172136.tar.bz2
- byacc-1.9-39.1.src.rpm
- compact-201003221835.tar.bz2
- libcdk5-201003221835.tar.bz2
- librts-201003221835.tar.bz2
- pf2asm-lite-201005172136.tar.bz2
Fases da Análise da Linguagem
O desenvolvimento do novo compilador deve ser incremental. O desenvolvimento dos novos processos de análise e geração deve ser horizontal. Existe um exemplo prático no wiki da disciplina.
O desenvolvimento do compilador, em especial na análise sintática e geração de código, pode evoluir da seguinte forma (partindo da sintaxe/semântica do compilador exemplo):
- migrar os tipos de dados básicos (inteiros, etc.) para a linguagem a implementar;
- migrar a instrução de impressão para a semântica a implementar;
- migrar a instrução de atribuição Compact para a nova expressão de atribuição;
- migrar/criar expressões aritméticas e lógicas inteiras;
- migrar/criar instruções condicionais e de ciclo;
- implementar invocação de funções;
- implementar funções;
- outras partes da linguagem.
Embora as fases de análise genéricas (lexical, sintáctica, semântica) estejam indicadas sequencialmente, devem ser atacadas horizontalmente e em simultâneo para cada parte da linguagem. É natural que alguns tópicos da teoria não estejam cobertos em momentos do desenvolvimento. Nestes casos, devem ser criados esqueletos de código para definir a localização do material em falta.
A análise lexical da linguagem é realizada pela ferramenta GNU Flex 2.5.35 (em modo C++), que deve operar (sem erros) sobre o ficheiro PipocaScanner.l (especificação lexical). Durante a análise lexical, deverá ser possível remover comentários e espaços brancos, identificar literais (valores constantes), identificadores (nomes de variáveis e funções), palavras chave, etc. Notar que a análise lexical não garante que estes elementos se encontrem pela ordem correcta. As sequências de escape nas cadeias de caracteres deverão ser substituídas pelos respectivos caracteres (ver manual de referência), o espaço necessário para o texto dos identificadores e cadeias de caracteres deverá ser reservado antes de devolvido.
A avaliação da análise lexical considera as expressões regulares utilizadas, bem como a robustez, clareza, simplicidade e extensibilidade da solução.
A análise sintáctica da é realizada pela ferramenta byacc (disponível acima), que opera sobre o ficheiro PipocaParser.y (especificação sintáctica), sem gerar qualquer tipo de conflitos (shift-reduce ou reduce-reduce) nem avisos ou erros. Com a análise sintáctica, é possível garantir a correcta sequência dos símbolos, embora não se verifique se as variáveis utilizadas nas expressões estão declaradas, nem se as operações suportam os tipos de dados utilizados, etc. Simultaneamente, são associadas acções que permitam construir uma árvore de análise sintáctica abstracta do programa a ser processado. Para tal, são utilizadas subclassess de cdk::node::Node (existentes na CDK5 ou definidas por derivação, no contexto do novo compilador).
Eventuais erros em programas Pipoca, encontrados durante a análise sintáctica, devem ser identificados e descritos ao utilizador (o processamento não deve ser interrompido, devendo o ficheiro deve ser processado até ao fim, procurando outros erros).
A avaliação considera a gramática do ponto de vista das verificações de coerência tratadas sintacticamente, das regras escolhidas e símbolos não terminais escolhidos, bem como a robustez, clareza, simplicidade e extensibilidade da solução proposta.
A análise semântica deverá garantir que um programa se encontra correctamente escrito e que pode ser executado.
A análise semântica identifica todos os erros estáticos (detectáveis no processo de compilação) e produzidas mensagens de erro descritivas. Caso surjam erros semânticos (estáticos), o compilador deverá terminar com um código de erro 2 (dois). Na sequência da análise semântica, e caso não surjam erros sintácticos ou semânticos (estáticos), é gerado o código final através da CDK5 (subclasses de
cdk::generator::Postfix).
Utilizando a árvore sintáctica abstracta (composta por instâncias de subclasses de
cdk::node::Node), pode-se efectuar a análise semântica e a geração de código numa só passagem em profundidade sobre a árvore sintáctica gerada.
Embora a análise semântica possa decorrer em paralelo com a geração de código, não deve ser gerado código se houver erros em alguma das fases de análise. Recorda-se que a execução de código pelo processador realiza poucas verificações, podendo produzir resultados indesejados. Aconselha-se nunca executar os programas gerados como utilizador previlegiado (e.g., em Linux, como "root" (uid=0) ou equivalente) ou num sistema sem protecção.
A geração de código final é realizada através das subsclasses de
cdk::generator::Postfix fornecidas. Estas classes utilizam o processador como uma máquina de pilha para gerar código final. Por exemplo, uma soma de duas constantes inteiras pode ser efectuada por:
Postfix *gen = new ix86(out); // exemplo para gerador ix86 (ferramenta nasm)
gen->INT(2); // coloca o primeiro operando na pilha
gen->INT(2); // coloca o segundo operando na pilha
gen->ADD(); // realiza a soma e deixa o resultado na pilha
O operador retira os operandos da pilha e deixa lá o resultado da operação. A impressão de um inteiro no topo da pilha pode ser realizada através das seguintes instruções:
gen->CALL("printi"); // chama a rotina de impressão
gen->TRASH(4); // remove o operando da pilha
A remoção do resultado da soma da pilha é necessária, depois da impressão, já que na convenção de chamada (C) é o chamador quem deve retirar os argumentos. A documentação da classe
cdk::generator::Postfix está disponível na CDK5.
O resultado da "execução" das instruções Postfix é um ficheiro assembly, que deverá ser compilado com a ferramenta
yasm, por forma a produzir um binário ELF. Assim, o comando
yasm -felf file.asm permite gerar o ficheiro
file.o a partir do ficheiro
file.asm (assumindo que não são encontrados erros). A geração do executável é efecutada através da ligação do ficheiro objecto com a biblioteca de run-time da linguagem
librts.a (disponível acima) com o comando
ld -o executavel file.o -lrts (podem ser incluídos outros ficheiros objecto ou bibliotecas, caso se utilize compilação separada).
Pacotes de Testes
Pacotes de testes para a linguagem do projecto:
- Básico: pipoca-basic-pack-201004291530.tar.bz2
- Adicional: (a publicar)