Pergunta

Depois de criar a árvore de análise, preciso preencher a tabela de símbolos agora.

Eu tenho que armazenar informações como

Tipo, escopo, deslocamento etc. para os identificadores.

Agora, como posso saber o tipo e o escopo dos identificadores, já que tudo que sei é o valor do lexema e o número da linha desse ID específico (após análise lexical).

Como é que eu entendi tudo isso?obrigado.

Foi útil?

Solução

Agora, como eu conheço o tipo, escopo dos identificadores, pois tudo o que sei é o valor do lexeme e o número da linha para esse ID específico (após a análise lexical).

Como o EJP mencionou, você precisa percorrer a árvore de análise.Sua árvore deveria ter sido criada para que você possa fazer uma travessia em ordem, visitando cada nó na mesma ordem em que as instruções e expressões do código-fonte são avaliadas.Os nós da sua árvore também devem corresponder a uma construção de linguagem específica, por exemplo. WhileStmtNode, MethodDeclNode, etc.

Suponha que eu esteja construindo a tabela de símbolos, percorrendo recursivamente a árvore, e acabei de inserir um nó do corpo do método.Eu poderia ter algo como o seguinte:

public void doAction(MethodBodyNode methodBody) {
    currScope = 2;
    methodBody.getExpr().applyAction(this);
    currScope = 2;
}

Mantenho uma variável global para gerenciar o escopo.Cada vez que entro em um bloco onde o escopo muda, eu incremento currScope.Da mesma forma, eu manteria currClass e currMethod variáveis ​​​​para armazenar com o nome do símbolo, tipo, deslocamento, etc.para fases posteriores.

Atualizar:

Agora diga, eu estou atravessando a árvore, toda vez que eu me deparo com um ID i teria que inserir o valor para a tabela de símbolos junto com o tipo, escopo e outros, digamos para escopo eu verifico se eu me deparo com '{' ou nome da função, mas como faço para saber que tipo de ID é este.

Cada nó da árvore deve conter todas as informações necessárias para toda a construção.Se estiver usando um gerador de analisador, como CUP ou Bison, você poderá especificar como construir a árvore nas ações gramaticais.Por exemplo.

variableDeclaration::= identifier:i identifier:i2 SEMICOLON {: RESULT = new VarDeclNode(i, i2, null); :};
identifier::= ID:i {: RESULT = new IdNode(i.getLineNum(), i.getCharNum(), i.getStringValue()); :};

Essas produções combinariam Foo f; e anexe um nó de declaração de variável à árvore.Esse nó encapsula dois nós identificadores que contêm o número da linha, o número do caractere e o valor da string do lexema.O primeiro nó identificador é o tipo e o segundo é o nome da variável. ID é um símbolo de terminal retornado pelo lexer ao combinar um identificador.Presumo que você esteja familiarizado com isso até certo ponto.

public class VarDeclNode extends StmtNode {

    private IdNode id;
    private IdNode type;
    private ExprNode expr;

    public VarDeclNode(IdNode id, IdNode type, ExprNode expr) {
        super();
        this.id = id;
        this.type = type;
        this.expr = expr;
    }

}

Quando você tem uma árvore de sintaxe com nós como este, você tem todas as informações que precisa.

2ª atualização:

Não importa se você está usando um analisador personalizado ou gerado, há um ponto distinto onde você adiciona um nó à árvore ao combinar uma produção.E não importa qual idioma você está usando.Estruturas C funcionarão perfeitamente.

se for um não terminal tem a informação como nome Nonterminals, e se ele é um terminal, ou seja,um token, então as informações no token, ou seja,valor do lexema, O nome do token e o número da linha são armazenados

Você deve ter nós especializados na árvore, por ex.ClassNode, TypeNode, MethodDeclNode, IfStmtNode, ExprNode.Você não pode simplesmente armazenar um tipo de nó e colocar não-terminais e terminais nele.Um não-terminal é representado como um nó de árvore, não há nenhuma outra informação para armazenar sobre ele além das partes que o compõem, que geralmente são eles próprios não-terminais.Você não armazenaria nenhuma informação de token.Existem apenas alguns casos em que você realmente armazenaria o valor da string de um lexema:para um identificador e para um literal de string/booleano/inteiro.

Dê uma olhada em esse exemplo.Durante a primeira redução quando S é reduzido a (S + F), você anexa um ParenExprNode até a raiz da árvore.Você também anexa um AddExprNode como filho do ParenExprNode.Essa lógica deve ser codificada em seu analisador ao aplicar uma redução pela regra 2 da gramática.

A árvore:

    ExprNode (root)
       |
  ParenExprNode
       |
   AddExprNode
   /         \
ExprNode   ExprNode

O código:

struct ExprNode { void* exprNode; };
struct ParenExprNode { void* exprNode; };
struct AddExprNode { void* op1, * op2; };
struct IdNode { char* val; int line; int charNum; };
struct IntLiteralNode { int val; int line; int charNum; };

void reduce_rule_2(ExprNode* expr) {

    //remove stack symbols

    //create nodes
    struct ParenExprNode* parenExpr = malloc(sizeof(struct ParenExprNode));
    struct AddExprNode* addExpr = malloc(sizeof(struct AddExprNode));
    addExpr->op1 = malloc(sizeof(struct ExprNode));
    addExpr->op2 = malloc(sizeof(struct ExprNode));

    //link them
    parenExpr->exprNode = (void*)addExpr;
    expr->exprNode = (void*)parenExpr;
}

Na próxima etapa, o parêntese esquerdo é removido da entrada.Depois, S está no topo da pilha e é reduzido a F pela regra 1.Desde F é o não-terminal de um identificador, é representado por IdNode.

A árvore:

    ExprNode
       |
  ParenExprNode
       |
   AddExprNode
   /         \
ExprNode   ExprNode
   |
 IdNode

O código:

reduce_rule_2(addExpr->op1);

void reduce_rule_1(ExprNode* expr) {
    //reduce stack symbols
    struct IdNode* id = malloc(sizeof(struct IdNode));
    id->val = parser_matched_text();
    id->lineNum = parser_line_num();
    id->charNum = parser_char_num();
    expr->exprNode = (void*)id;
}

E assim por diante...

Outras dicas

.

Tudo o que sei é o valor do Lexeme e o número da linha para esse ID específico

Isso não é verdade.Você sabe onde é declarado na árvore de análise, o que lhe diz tudo que você precisa.Você faz esta etapa processamento a árvore de análise.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top