• 【编译系统02】编译器


    当我们分析到 "int n;",说明其已经定义了一个变量,之后又遇到一个 "n=3",我们从哪里去找这个n并且赋值呢?

    答案是:通过我们定义的 变量表(Table) 中查找。

    其实,这变量声明定义与变量赋值一系列动作,都是由语义分析器负责的。

    1. 当扫描到一个声明语句,比如 "string x;" 时:

      1)在语法分析中,当检测到 string <type>,其会将 (string,x)保存在(tVar.type,tVar.name)。

      2)调用 Table.addVar ,该函数会生成一个新的 变量对象(var_record),然后添加进 map<> 中。

      3)当之后遇到  x = ''hello world"时,其会调用 Table.getVar(x),然后将其赋值为 "hello world",这样就实现了赋值。

    2. var_record类定义如下():

     1 class var_record {
     2 public:
     3     symbol type; // 类型
     4     string name; // 名称
     5      
     6     // 变量值
     7     int intVal; // 整数
     8     string strVal; // 字符串
     9     
    10     
    11     
    12     int localAddr; // 局部变量相对于ebp指针的地址,或者临时string的索引地址
    13     var_record(); // 默认构造函数
    14     void init(symbol dec_type, string dec_name); // 声明初始化函数
    15     var_record(const var_record& v);//拷贝构造函数
    16     ~var_record();
    17 };

      1)变量值一开始打算使用 union{int,string} 来实现,但在c++union作为类,存在权限访问冲突(暂时没解决),因此就分开来实现。

    3. Table 变量表的定义如下:

     1 class Table {
     2     map<string, var_record*> var_map; // 变量声明列表
     3 public:
     4     Table(); // 构造函数
     5     void addVar(); // 添加变量声明记录,默认使用tvar
     6     
     7     //  该函数估计暂时用不到
     8     //void addVar(var_record*v); // 添加变量声明记录,重载(赋值已声明的变量后则要实现重载)
     9     var_record * getVar(string name); // 获取已经记录的变量名
    10 };

      1)Table类核心就是围绕map<>结构来建立

      2)两个方法,一个是添加变量,另一个是找到变量。

    4. 简单的测试代码(模拟"遇到字符串与数字的定义赋值与输出")

     1 #include "pch.h"
     2 #include "semantic.h"
     3 #include <iostream>
     4 #include <string>
     5 #include <map>
     6 using namespace std;
     7 
     8 map<string, int> a;
     9 
    10 /*
    11      模拟变量声明过程
    12      int a;
    13      a = 3;
    14 */
    15 
    16 int main() {
    17     // 建立一个全局变量表
    18     
    19     Table VarTable;
    20         
    21     // int a;
    22     tVar.type = NUM; // 变量类型是 NUM(INT) 数字类型
    23     tVar.name = "a";    // 添加变量名
    24     VarTable.addVar(); // 其默认将tVar 添加进表中
    25 
    26     // a = 3;
    27     var_record * a =  VarTable.getVar("a"); // 拿出变量a
    28     a->intVal = 3; // 将a 赋值为 3
    29     
    30     // 输出结果
    31     // cout << a << endl
    32     cout << VarTable.getVar("a")->intVal << endl;
    33     
    34 
    35     // string x;
    36     tVar.type = STR; // 变量类型是 NUM(INT) 数字类型
    37     tVar.name = "x";    // 添加变量名
    38     VarTable.addVar(); // 其默认将tVar 添加进表中
    39 
    40     // x= "hello world";
    41     var_record * x = VarTable.getVar("x"); // 拿出变量x
    42     x->strVal = "hello world"; // 将a 赋值为 3
    43     int tt =4;
    44 
    45     cout << VarTable.getVar("x")->strVal << endl;
    46     return 0;
    47 }
    View Code

    测试结果符合要求。

  • 相关阅读:
    andrid 上传图片 asp.net 后台接收并保存
    Volley封装
    error: Error retrieving parent for item: No resource found that matches the given name 'android:Widget.Material.ActionButton'.
    The type android.support.v4.view.ScrollingView cannot be resolved. It is indirectly referenced from
    Recyclerview 实现上拉加载更多
    RecyclerAdapter封装
    项目中自己一直用到的baseAdapter的类
    SwipeRefreshLayout 和RecyclerView 使用
    DrawerLayout 使用
    学习动态性能表 v$sql
  • 原文地址:https://www.cnblogs.com/onetrainee/p/11962123.html
Copyright © 2020-2023  润新知