Заполнение таблицы символов после анализа;Сборка компилятора

StackOverflow https://stackoverflow.com//questions/9703227

Вопрос

После создания дерева разбора мне нужно заполнить таблицу символов.

Мне нужно хранить информацию типа

Тип, область действия, смещение и т. д. для идентификаторов.

Теперь, как мне узнать тип и область действия идентификаторов, поскольку все, что я знаю, это значение лексемы и номер строки для этого конкретного идентификатора (после лексического анализа).

Как мне обо всем этом узнать?Спасибо.

Это было полезно?

Решение

Теперь, как я узнаю тип, область объема идентификаторов, поскольку все, что я знаю, это значение Lexeme и номер строки для этого конкретного идентификатора (после лексического анализа).

Как упоминалось в EJP, вам нужно пройти через дерево синтаксического анализа.Ваше дерево должно было быть создано таким образом, чтобы вы могли выполнять обход по порядку, посещая каждый узел в том же порядке, в котором оцениваются операторы и выражения исходного кода.Узлы вашего дерева также должны соответствовать определенной языковой конструкции, например. WhileStmtNode, MethodDeclNode, и т. д.

Предположим, я создаю таблицу символов, рекурсивно просматривая дерево, и только что ввел узел тела метода.У меня может быть что-то вроде следующего:

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

Я сохраняю глобальную переменную для управления областью действия.Каждый раз, когда я вхожу в блок, где изменяется область действия, я увеличиваю currScope.Точно так же я бы поддержал currClass и currMethod переменные для хранения имени символа, типа, смещения и т. д.для более поздних фаз.

Обновлять:

Теперь скажем, я пересекаю дерево, каждый раз, когда сталкиваюсь с идентификатором, мне пришлось бы ввести значение в таблице символов вместе с типом, сферой и другими, скажем, на область, я проверю, если я сталкиваюсь с именем функции, Но как я узнаю, что такое тип идентификатора.

Каждый узел дерева должен содержать всю необходимую информацию для всей конструкции.Если вы используете генератор синтаксического анализатора, такой как CUP или Bison, вы можете указать, как строить дерево, в действиях грамматики.Например.

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

Эти постановки будут соответствовать Foo f; и добавьте узел объявления переменной в дерево.Этот узел инкапсулирует два узла идентификаторов, которые содержат номер строки, номер символа и строковое значение лексемы.Первый узел идентификатора — это тип, а второй — имя переменной. ID — это терминальный символ, возвращаемый лексером при сопоставлении идентификатора.Я предполагаю, что вы в некоторой степени знакомы с этим.

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;
    }

}

Если у вас есть синтаксическое дерево с такими узлами, у вас есть вся необходимая информация.

2-е обновление:

Неважно, используете ли вы собственный синтаксический анализатор или сгенерированный, есть один определенный момент, когда вы добавляете узел в дерево при сопоставлении с продуктом.И не важно, какой язык вы используете.Структуры C вполне подойдут.

Если это не терминал имеет информацию как имя неподмеси, и если это терминал, т.е.токен, затем информация в токене, т.е.Значение Lexeme, имя токена и номер строки хранятся

У вас должны быть специализированные узлы в дереве, например.ClassNode, TypeNode, MethodDeclNode, IfStmtNode, ExprNode.Вы не можете просто хранить один тип узла и помещать в него нетерминалы и терминалы.Нетерминал представлен в виде узла дерева, о нем нет никакой другой информации, кроме составляющих его частей, которые обычно сами являются нетерминалами.Вы не будете хранить никакой информации о токене.Есть лишь несколько случаев, когда вы действительно сохраняете строковое значение лексемы:для идентификатора и для строкового/логического/целочисленного литерала.

Посмотри на этот пример.Во время первого сокращения, когда S сводится к (S + F), вы добавляете ParenExprNode до корня дерева.Вы также добавляете AddExprNode как ребенок ParenExprNode.Эта логика должна быть жестко запрограммирована в вашем парсере при применении сокращения по правилу 2 грамматики.

Дерево:

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

Код:

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;
}

На следующем шаге левая скобка удаляется из входных данных.После этого S находится на вершине стека и уменьшается до F по правилу 1.С F является нетерминалом для идентификатора, он представлен IdNode.

Дерево:

    ExprNode
       |
  ParenExprNode
       |
   AddExprNode
   /         \
ExprNode   ExprNode
   |
 IdNode

Код:

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;
}

И так далее...

Другие советы

Все, что я знаю, это значение lexeme и номер строки для этого конкретного идентификатора

Это не правда.Вы знаете, где он объявлен в дереве разбора, что говорит вам все, что вам нужно.Вы делаете этот шаг по обработке дерева разбора.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top