从零写一个编译器(八):语义分析之构造符号表

项目的完整代码在 C2j-Compiler

前言

在之前完成了描述符号表的数据结构,现在就可以正式构造符号表了。符号表的创建自然是要根据语法分析过程中走的,所以符号表的创建就在LRStateTableParser里的takeActionForReduce方法

不过在此之前,当然还需要一个方便对这个符号表操作的类了

这一篇主要的两个文件是

  • TypeSystem.java
  • LRStateTableParser.java

操作符号表

操作符号表的方法都在TypeSystem类里。

TypeSystem里主要有这几个方法:

类型说明符

逻辑都很简单

public TypeLink newType(String typeText) {
      Specifier sp;
      int type = Specifier.NONE;
      boolean isLong = false, isSigned = true;
      switch (typeText.charAt(0)) {
          case 'c':
              if (typeText.charAt(1) == 'h') {
                  type = Specifier.CHAR;
              }
              break;
          case 'd':
          case 'f':
              System.err.println("Floating point Numbers are not supported");
              System.exit(1);
              break;
          case 'i':
              type = Specifier.INT;
              break;
          case 'l':
              isLong = true;
              break;
          case 'u':
              isSigned = false;
              break;
          case 'v':
              if (typeText.charAt(2) == 'i') {
                  type = Specifier.VOID;
              }
              break;
          case 's':
              //ignore short signed
              break;
          default:
              break;
      }

      sp = new Specifier();
      sp.setType(type);
      sp.setLong(isLong);
      sp.setSign(isSigned);

      TypeLink link = new TypeLink(false, false, sp);

      return link;
  }

创建存储类型

其实这一部分有的到后面解释执行或者代码生成的时候,现在这个编译器是不处理的

这一部分的逻辑也很简单

public TypeLink newClass(String classText) {
      Specifier sp = new Specifier();
      sp.setType(Specifier.NONE);
      setClassType(sp, classText.charAt(0));

      TypeLink link = new TypeLink(false, false, sp);
      return link;
  }

  private void setClassType(Specifier sp, char c) {
      switch(c) {
          case 0:
              sp.setStorageClass(Specifier.FIXED);
              sp.setStatic(false);
              sp.setExternal(false);
              break;
          case 't':
              sp.setStorageClass(Specifier.TYPEDEF);
              break;
          case 'r':
              sp.setStorageClass(Specifier.REGISTER);
              break;
          case 's':
              sp.setStatic(true);
              break;
          case 'e':
              sp.setExternal(true);
              break;
          default:
              System.err.println("Internal error, Invalid Class type");
              System.exit(1);
              break;
      }
  }

给符号添加修饰符

addSpecifierToDeclaration是为当前整

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这是一个比较复杂的问题,需要涉及到多个知识点。以下是一个简单的编译器实现示例,包括词法分析、语法分析和语义分析。 ```c // 词法分析部分 // 定义标识符类型 enum TokenType { ID, NUM, OPERATOR }; // 定义词法分析结果结构体 struct Token { enum TokenType type; char value[32]; }; // 词法分析函数 struct Token lex(char* input) { struct Token token; // 从输入字符串中读取下一个标记 // 判断标记类型并储存到 token 结构体 // 返回 token 结构体 return token; } // 语法分析部分 // 定义语法分析结果结构体 struct ParseResult { bool success; // 其他语法分析结果 }; // 语法分析函数 struct ParseResult parse(struct Token* tokens, int token_count) { struct ParseResult result; // 判断 tokens 是否符合语法规则 // 如果符合,设置 result.success 为 true,否则为 false return result; } // 语义分析部分 // 定义语义分析结果结构体 struct AnalyzeResult { bool success; // 其他语义分析结果 }; // 语义分析函数 struct AnalyzeResult analyze(struct Token* tokens, int token_count) { struct AnalyzeResult result; // 判断 tokens 是否符合语义规则 // 如果符合,设置 result.success 为 true,否则为 false return result; } // 主函数 int main() { char input[1024]; fgets(input, 1024, stdin); // 词法分析 struct Token tokens[32]; int token_count = 0; while (/* 输入字符串还有下一个标记 */) { struct Token token = lex(/* 输入字符串 */); tokens[token_count++] = token; } // 语法分析 struct ParseResult parse_result = parse(tokens, token_count); if (!parse_result.success) { printf("语法错误\n"); return 1; } // 语义分析 struct AnalyzeResult analyze_result = analyze(tokens, token_count); if (!analyze_result.success) { printf("语义错误\n"); return 1; } // 编译成功 printf("编译成功\n"); return 0; } ``` 以上只是一个简单的示例,实际的编译器实现要更加复杂。需要了解更多相关知识,才能编写出更为完整和实用的编译器

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值