深入解析DoctorWkt/acwj项目:字符与字符串字面量的实现

深入解析DoctorWkt/acwj项目:字符与字符串字面量的实现

acwj A Compiler Writing Journey acwj 项目地址: https://gitcode.com/gh_mirrors/ac/acwj

前言

在编译器开发过程中,处理字符和字符串字面量是一个重要的里程碑。本文将深入探讨如何在DoctorWkt/acwj项目中实现字符和字符串字面量的支持,这对于理解编译器如何处理文本数据具有重要意义。

字符字面量的实现

基本概念

字符字面量在C语言中由单引号包围的单个字符组成,如 'A'。在我们的编译器中,字符字面量被当作整数类型处理,这符合C语言将字符视为小整数的特性。

扫描过程实现

扫描字符字面量的核心在于scanch()函数,它负责处理转义字符:

static int scanch(void) {
  int c = next();
  if (c == '\\') {
    switch (c = next()) {
      case 'a':  return '\a';   // 响铃
      case 'b':  return '\b';   // 退格
      case 'f':  return '\f';   // 换页
      case 'n':  return '\n';   // 换行
      case 'r':  return '\r';   // 回车
      case 't':  return '\t';   // 水平制表
      case 'v':  return '\v';   // 垂直制表
      case '\\': return '\\';   // 反斜杠
      case '"':  return '"';    // 双引号
      case '\'': return '\'';   // 单引号
      default: fatalc("未知的转义序列", c);
    }
  }
  return c;
}

这个实现涵盖了常见的转义序列,但为了简化,没有处理八进制或Unicode转义。

字符串字面量的实现

基本概念

字符串字面量由双引号包围的字符序列组成,如 "Hello"。在内存中,字符串以null字符('\0')结尾。

扫描过程

scanstr()函数负责扫描字符串字面量:

static int scanstr(char *buf) {
  int i, c;
  for (i=0; i<TEXTLEN-1; i++) {
    if ((c = scanch()) == '"') {
      buf[i] = 0;
      return i;
    }
    buf[i] = c;
  }
  fatal("字符串字面量过长");
  return 0;
}

该函数使用scanch()处理每个字符,确保字符串以null结尾,并防止缓冲区溢出。

语法分析与AST构建

在语法分析阶段,字符串字面量被处理为AST中的叶节点:

case T_STRLIT:
  id = genglobstr(Text);
  n = mkastleaf(A_STRLIT, P_CHARPTR, id);
  break;

这里的关键点:

  1. 为字符串分配全局标签
  2. 创建类型为P_CHARPTR的AST节点
  3. 使用A_STRLIT表示字符串字面量节点

代码生成

字符串存储生成

cgglobstr()函数生成字符串的汇编表示:

void cgglobstr(int l, char *strvalue) {
  char *cptr;
  cglabel(l);
  for (cptr = strvalue; *cptr; cptr++) {
    fprintf(Outfile, "\t.byte\t%d\n", *cptr);
  }
  fprintf(Outfile, "\t.byte\t0\n");
}

字符串地址加载

cgloadglobstr()生成加载字符串地址的指令:

int cgloadglobstr(int id) {
  int r = alloc_register();
  fprintf(Outfile, "\tleaq\tL%d(\%%rip), %s\n", id, reglist[r]);
  return r;
}

类型系统调整

在处理指针类型时,发现了一个重要修正:

if (inttype(ltype) && ptrtype(rtype)) {
  rsize = genprimsize(value_at(rtype));
  if (rsize > 1)
    return mkastunary(A_SCALE, rtype, tree, rsize);
  else
    return tree;  // 对于char*不需要缩放
}

这个修正确保了对char*类型的正确处理,避免了不必要的缩放操作。

测试与验证

实现完成后,编译器现在可以处理如下的代码:

char *s = "Hello world";
printint(10);

输出结果为:

10
Hello world

总结与展望

本文详细介绍了在DoctorWkt/acwj项目中实现字符和字符串字面量的过程,包括:

  1. 词法分析器对字符和字符串的扫描处理
  2. 语法分析器构建相应的AST节点
  3. 代码生成器输出正确的汇编指令
  4. 类型系统的相关调整

这个实现虽然简化了某些复杂情况(如宽字符、Unicode等),但完整覆盖了基本的字符和字符串处理需求。下一步可以考虑添加更多的运算符支持,进一步增强编译器的表达能力。

理解字符和字符串字面量的处理机制,对于深入学习编译器设计和C语言实现原理具有重要意义。这种实现方式也展示了如何将高级语言特性映射到底层机器表示的基本方法。

acwj A Compiler Writing Journey acwj 项目地址: https://gitcode.com/gh_mirrors/ac/acwj

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛美婵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值