LLVM_ Interpreter_解释器(一)

2018-10-19  本文已影响92人  Lin__Chuan

在前一片文章中, 我介绍了与 LLVM 相关的一些内容, 里面涉及到一些应用

这里我们以 interpreter 为起点, 逐步实现一个简单版的语言转换, 之所以打算开这个系列的文章, 主要还是看了戴铭在 2018Swift 大会上做的关于解释器的演讲, 他在这篇文章里做了一些介绍.

什么是 interpreter ?

interpreter (解析器) 处理并执行源程序而不首先将其翻译成机器语言.
compiler 将源程序翻译成机器语言, interpreter 是 compiler 的一部分.

1. Lexer 词法分析

lexical analysis(lexer) : 词法分析, 将输入的源码分解为 Token 的过程, 其中, lexeme 是一系列形成 Token 的字符. Token 包括以下几种.

2. Paeser 语法分析

Paeser 读取由 Lexer 生成的 Token 序列,并根据语法构建程序的抽象语法树(简称AST). 也一过程叫 syntax analysis, 语法分析.

什么是语法呢?

syntax diagrams : 语法图, 描述编程语言 syntax 规则的图示.
grammars : 这是 context-free grammars 的简称,

grammars 以简洁的方式指定编程语言的语法。
syntax diagrams 不同,grammars 非常紧凑。

下面是 syntax diagrams

上面可以表示3, 3 + 2, 3-2, 3 + 2 - 2 等语法 上面可以表示3, 3 * 2, 3 * 2 / 7等语法

grammars 的表示方法
描述 3 * 2 / 7 的语法可以这么写

image.png

这个语法是怎么工作的?

语法通过解释它可以形成的语句来定义语言.首先从开始符号expr开始,然后用非终端的规则体重复替换非终端,直到你生成一个仅包含终端的句子为止, 这些句子构成语法定义的语言.

如何将语法转化为代码呢?

针对这个, 做一个简单演示, 将 Token 按照语法规则转化为代码 3 * 8 / 2.
我们已经将 3 * 8 / 2 这样的代码转化为 Tokens,
以下面这种 enum 结构封装

public enum LCOperationType {
    case plus
    case minus
    case mult
    case intDiv
}
public enum LCConstant {
    case integer(Int)
}
public enum LCToken {
    case operation(LCOperationType)
    case constant(LCConstant)
    case eof
}

factor() 用来取出 tokens 中的 integer value, 这里面有一个 eat(), 用来 feed value, 也就是 tokenIndex += 1.

/**
 返回一个 Integer Token value
 factor : INTEGER
 */
private func factor() -> Int {
    
    let token = currentToken
    var outputNum = 0
    if case let .constant(.integer(num)) = token {
        eat(token)
        outputNum =  num
    }
    return outputNum
}

expr() 用来做计算

/**
 expr   : factor ((MUL | DIV) factor)*
 factor : INTEGER
 */
private func expr() -> Int {
    var result = factor()
    let operationTokens = [LCToken.operation(.mult),
                           LCToken.operation(.intDiv)]
    while operationTokens.contains(currentToken) {
        if currentToken == .operation(.mult) {
            eat(currentToken)
            result = result * factor()
        }else if currentToken == .operation(.intDiv) {
            eat(currentToken)
            result = result / factor()
        }
    }
    return  result
}

4. Semantic analyzer 语义分析器

Semantic analyzer 对 AST 进行静态语义检查.

5. Interpreter 解释器

Interpreter 从 Parser 读取代表目标程序的 AST,并通过递归地遍历AST来解释它.

这个系列后面还会继续更新. 如果你也对这块感兴趣, 欢迎交流.

上一篇下一篇

猜你喜欢

热点阅读