表达式如何在一次性编译器中工作?

How does expressions work in one pass compiler?

我看过很多关于 one passmulti pass 编译器的帖子,我认为 [=20] 的基本部分=]One Pass Compiler如下。

  1. Lexical Analysis
  2. Parse and Syntax Check
  3. Symbol Table
  4. Code Generation

但是我有一个问题,我无法理解。 Expression 如何在 one pass compiler(没有 AST)

中工作

我们以1 + 2 / 3为例。假设您需要为此生成汇编代码。创建解析器后,如何从中生成程序集? ( 直接 )汇编代码如何生成不出错?

你能举个例子解释一下吗?请告诉我这个问题是否有问题。我是 Whosebug 的新手 :)

single-shot 编译器处理类似 a=b*c[i]+d*e; 的最简单方法是处理遇到的每个标记:

  • a 生成代码将 a 的地址压入堆栈
  • = 记录堆栈顶部项目将用作赋值目标的事实。
  • b 生成代码将 b 的地址压入堆栈
  • * 生成代码以弹出地址(b),获取那里的对象,然后推送它。
  • 同时记录栈顶项将用作乘法运算的左操作数这一事实。
  • c 生成代码将 c 的地址压入堆栈
  • [ 记录栈顶项将是 [ 的左操作数这一事实,并计算以下表达式
  • i 生成代码将 i 的地址压入堆栈
  • ] 生成代码以弹出地址(i),获取那里的对象,然后推送它。
  • 同时弹出栈上的两项(i的值和c的地址,相加,压入那个结果
  • + 生成代码以弹出地址(c[i]),获取那里的对象,然后推送它
  • 同时生成代码以弹出前两个值(c[i]b),将它们相乘,然后推送结果
  • 同时记录栈顶项将是 +
  • 的左操作数这一事实
  • d 生成代码将 d 的地址压入堆栈
  • * 生成代码以弹出地址,获取那里的对象,然后推送它。
  • 同时记录栈顶项将用作乘法运算的左操作数这一事实。
  • e 生成代码将 e 的地址压入堆栈
  • (语句结束):生成代码以弹出地址(e),获取那里的对象,然后推送它
  • 同时生成代码以弹出前两个值(ed),将它们相乘,然后推送结果
  • 同时生成代码以弹出前两个值(d*eb*c[i]),将它们相加,然后推送结果
  • 同时生成代码以弹出一个值 (b*c[i]+d*e) 和地址 a 并将值存储到地址

请注意,在许多平台上,如果将以推送结束的操作的代码生成推迟到生成下一个操作,并且如果将紧跟在推送之后的 pop 与它们合并,则性能可能会大大提高;此外,让编译器记录赋值运算符的左侧是 a 这一事实可能很有用,而不是生成代码来压入该地址,然后让赋值运算符直接执行存储到 a 而不是先计算地址,然后将其用于商店。另一方面,所描述的方法将能够为所有内容生成机器代码,直到正在处理的机器代码的确切字节,而无需跟踪需要展开的挂起操作之外的许多操作。