😸

勉強がてらGoで簡単なコンパイラーを作成してみた

2023/05/30に公開

コンパイラの作成は複雑なプロセスですが、Go言語を用いて最も単純な形式のコンパイラを作ってみました。

字句解析(Lexical Analysis): コードをトークンに分割します。例えば、let x = 10;というコードをLET, IDENTIFIER, ASSIGN, INTEGER, SEMICOLONのように分割します。

構文解析(Parsing): トークンを解析し、抽象構文木(AST: Abstract Syntax Tree)を生成します。これは、トークンの階層的な表現で、トークンがどのように互いに関連しているかを示します。

意味解析(Semantic Analysis): ASTを調査し、型チェックや変数が宣言されているかどうかなどのチェックを行います。

コード生成(Code Generation): 最終的なコード(機械語、バイトコードなど)を生成します。このステップでASTがターゲットのコードに変換されます。

以下は、最も簡単な形の言語(例えば、数字と加算のみ)のコンパイラを作成するGo言語のコードスニペットです。

package main

import (
    "fmt"
    "strconv"
    "strings"
)

// Token Types
const (
    INT = "INT"
    PLUS = "PLUS"
)

type Token struct {
    Type  string
    Value string
}

func Lex(input string) []Token {
    var tokens []Token

    for _, char := range strings.Split(input, " ") {
        switch {
        case char == "+":
            tokens = append(tokens, Token{PLUS, char})
        default:
            if _, err := strconv.Atoi(char); err == nil {
                tokens = append(tokens, Token{INT, char})
            }
        }
    }

    return tokens
}

func Parse(tokens []Token) int {
    result := 0

    for _, token := range tokens {
        switch token.Type {
        case INT:
            value, _ := strconv.Atoi(token.Value)
            result += value
        }
    }

    return result
}

func main() {
    input := "2 + 2 + 3 + 4"
    tokens := Lex(input)
    result := Parse(tokens)
    fmt.Println(result)
}

この例では、字句解析器が2 + 2 + 3 + 4という入力をトークンに分割し、それぞれがINTまたはPLUSタイプのトークンになります。その後、構文解析器がこれらのトークンを解析し、すべてのINTトークンの値を加算します。

Discussion