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

Parsing 表达式如何在一次编译中工作?,parsing,compiler-optimization,abstract-syntax-tree,Parsing,Compiler Optimization,Abstract Syntax Tree,我看过很多关于一次编译和多次编译的帖子,我认为一次编译的基本部分如下 词汇分析 解析和语法检查 符号表 代码生成 但我有一个问题,我无法理解。表达式如何在单过程编译器中工作(没有AST) 让我们以1+2/3为例。假设您需要为此生成汇编代码。创建解析器后,如何从中生成程序集?(直接)汇编代码如何生成而没有任何错误 你能举例说明吗?请告诉我这个问题是否有问题。我不熟悉Stackoverflow:)单次编译过程的最简单方法,类似于a=b*c[I]+d*e将在遇到每个令牌时进行处理: a生成代码,将a

我看过很多关于一次编译多次编译的帖子,我认为一次编译的基本部分如下

  • 词汇分析
  • 解析和语法检查
  • 符号表
  • 代码生成
  • 但我有一个问题,我无法理解。表达式如何在单过程编译器中工作(没有AST)

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


    你能举例说明吗?请告诉我这个问题是否有问题。我不熟悉Stackoverflow:)

    单次编译过程的最简单方法,类似于
    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
    ),从那里获取对象,然后将其推送
  • 还生成代码以弹出前两个值(
    e
    d
    ),将它们相乘,然后推送结果
  • 还生成代码以弹出前两个值(
    d*e
    b*c[i]
    ),添加它们,并推送结果
  • 还生成代码以弹出值(
    b*c[i]+d*e
    )和地址
    a
    ,并将值存储到地址
  • 请注意,在许多平台上,如果将以推送结束的操作的代码生成推迟到生成下一个操作,并且将紧跟推送之后的POP与它们合并,则性能可能会得到极大提高;此外,让编译器记录assignm的左侧这一事实可能会很有用ent运算符是
    a
    ,而不是生成代码来推送该地址,然后让赋值运算符直接对
    a
    执行存储,而不是先计算地址,然后将其用于存储。另一方面,所述方法将能够为exac之前的所有内容生成机器代码正在处理的机器代码的t字节,无需跟踪需要解卷的未决操作之外的许多操作