Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Yacc - Gramática reescrita
- -Para casos em que uma componente é opcional, decidimos criar um novo estado e definir as possibilidades da gramatica nesse estado.
- FuncDeclaration → FUNC ID LPAR [Parameters] RPAR [Type] FuncBody
- → function_declaration:
- function_header function body
- function_header:
- FUNC id_state LPAR parameters RPAR
- FUNC id_state LPAR parameters RPAR type
- Onde parameters pode ser vazio.
- -Para os casos de 0 ou mais repetições, decidimos criar um novo estado em que este pode ser vazio para passar a recursividade a esquerda para recursividade à direita e remover ambiguidade.
- Parameters−→ID Type {COMMA ID Type}
- → Parameters:
- parameters_decl;
- parameters_decl:
- id_state type parameters_list
- |
- ;
- parameters_list:
- COMMA id_state type parameters_list
- |
- ;
- -Para os casos de ser ou uma produção ou outra, decidimos criar um estadoque pode ser as duas produções possíveis.
- Statement−→PRINT LPAR (Expr | STRLIT) RPAR
- str_statement:
- PRINT LPAR expression RPAR
- PRINT LPAR strlit_state RPAR
- ;
- PORQUE O ID_STATE E STRLIT_STATE SÓ PARA ID E STRLIT?
- MAIS ALGUM CASO WORTH MENTIONING?
- Quanto aos erros, uma vez que o analisador deve incluir recuperação local de erros de sintaxe, Adicionámos um estado “error” nos locais assinalados no enunciado.
- AST Anotada e Tabela Simbolos
- Geração Código
- Para a geração de código percorremos a arvore anotada de maneira parecida a meta3 verificando os tipos de nós que encontramos e usando esses nós para criação de linhas LLVM.
- Inicialmente, vamos à tabela de simbolos e declaramos todas as variáveis globais. Além disso, se encontrarmos um function declaration, declaramos as variáveis locais imediatamente.
- Assign:
- verificamos se variável é global ou não para saber que tipo de store é que é feito (“@%s” ou “%%%s”).
- FuncDecl:
- Imprimimos o header da funcao e os respectivos tipos dos parâmetros (“define i32 @f(i32)”)
- Declaramos variaveis locais.
- Continuamos a analisar a arvore para imprimir os nos filhos do FuncDecl que estão dentro da função.
- Analisamos a necessidade de ser colocado um return, e caso seja preciso (“ret %type”).
- Statement:
- Verificamos o tipo (IF, For ,Return, Print).
- If:
- Verificamos se existe um block para Else para saber quantos Labels alocar.
- Após alocado espaço para os labels, e ter produzido a expressão, é feito um branch comparando a variável proveniente das expressões(“br i1 %s %%label%d, label %%label%d”).
- Inicializamos o label, produzimos os nós filhos deste e fazemos um branch para o nó após o if.
- For:
- Caso haja, criamos um label para a condição, um para o block do for e um para o fim do for.
- Branches de maneira semelhante aos ifs
- Prints:
- Parse Args:
- Expressions:
- Percorremos recursivamente até folhas da arvore e retornamos ou variável temporaria ou valor primitivo. Num nó por exemplo do tipo “add”, este vai ter duas expressions provenientes da recursividade.
- Call:
- imprimimos um call para a função com respectivos parâmetros e tipos.
- Expression:
- verificamos o valor do nó para saber se é um add, sub ou outro e após verificar se é float ou não, produzimos a linha LLVM correspondente ao valor do nó.
- Id:
- verificamos se id é global ou local e produzimos linha LLVM load para essa variável com expression.
- Tipos especiais primitivos:
- 2e3 → 2.0e3 || .3 → 0.3|| Other realits || Hexa|octal → decimal
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement