【Interpreter】构建简单的解释器(第3部分—Go语言实现)

【Interpreter】构建简单的解释器(第3部分—Go语言实现)

一、描述

在第二部分的基础上,扩展代码,实现可以解释包含任意数量的加法和减法的表达式,例如 “9 - 5 + 3 + 11”

二、代码

// Go 实现

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
	"unicode"
)

type TOKEN_TYPE int

const (
	TYPE_NONE TOKEN_TYPE = iota
	TYPE_INTEGER
	TYPE_PLUS
	TYPE_MINUS
	TYPE_MUL
	TYPE_DIV
	TYPE_EOF
)

type Token struct {
	TokenType  TOKEN_TYPE
	TokenValue interface{}
}

type Interpreter struct {
	Text         []rune
	Pos          int
	CurrentToken Token
	CurrentChar  rune
}

func (interpreter *Interpreter) Advance() {
	interpreter.Pos += 1

	if interpreter.Pos > len(interpreter.Text)-1 {
		interpreter.CurrentChar = 0
	} else {
		interpreter.CurrentChar = interpreter.Text[interpreter.Pos]
	}
}

func StrToInt(s string) int {
	if ret, err := strconv.Atoi(s); err == nil {
		return ret
	}
	panic(fmt.Sprintf("Cannot convert %s to int!", s))
}

func (interpreter *Interpreter) Integer() int {
	result := ""

	for interpreter.CurrentChar != 0 && unicode.IsDigit(interpreter.CurrentChar) {
		result += string(interpreter.CurrentChar)
		interpreter.Advance()
	}

	return StrToInt(result)
}

func (interpreter *Interpreter) SkipSpace() {
	for interpreter.CurrentChar != 0 && unicode.IsSpace(interpreter.CurrentChar) {
		interpreter.Advance()
	}
}

func (interpreter *Interpreter) GetNextToken() Token {

	for interpreter.CurrentChar != 0 {
		if unicode.IsSpace(interpreter.CurrentChar) {
			interpreter.SkipSpace()
		}

		if unicode.IsDigit(interpreter.CurrentChar) {
			return Token{TYPE_INTEGER, interpreter.Integer()}
		}

		if interpreter.CurrentChar == '+' {
			interpreter.Advance()
			return Token{TYPE_PLUS, '+'}
		}

		if interpreter.CurrentChar == '-' {
			interpreter.Advance()
			return Token{TYPE_MINUS, '-'}
		}

		panic("invalid text.")
	}

	return Token{TYPE_EOF, nil}
}

func (interpreter *Interpreter) Eat(token_type TOKEN_TYPE) {
	if interpreter.CurrentToken.TokenType == token_type {
		interpreter.CurrentToken = interpreter.GetNextToken()
	} else {
		panic("invalid token type.")
	}
}

func (interpreter *Interpreter) Term() int {
	token := interpreter.CurrentToken
	interpreter.Eat(TYPE_INTEGER)

	return token.TokenValue.(int)
}

func (interpreter *Interpreter) Expr() {

	defer func() {
		if r := recover(); r != nil {
			fmt.Println("[ERROR] ", r)
		}
	}()

	interpreter.CurrentToken = interpreter.GetNextToken()
	result := interpreter.Term()

	for {
		if interpreter.CurrentToken.TokenType == TYPE_PLUS {
			interpreter.Eat(TYPE_PLUS)
			result += interpreter.Term()
		} else if interpreter.CurrentToken.TokenType == TYPE_MINUS {
			interpreter.Eat(TYPE_MINUS)
			result -= interpreter.Term()
		} else {
			break
		}
	}

	fmt.Println("> ", result)
}

func main() {
	fmt.Println("------------------ <PART-3> ------------------")

	reader := bufio.NewReader(os.Stdin)

	for {
		fmt.Print("[CALC]-> ")

		text, _ := reader.ReadString('\n')
		text = strings.ToLower(strings.TrimSpace(strings.TrimSuffix(text, "\n")))
		if len(text) == 0 {
			continue
		}

		if text == "exit" {
			fmt.Println("-------------------程序已退出------------------")
			fmt.Println("------------------- <END> --------------------")
			os.Exit(0)
		}

		my_text := []rune(text)

		my_interpreter := Interpreter{my_text, 0, Token{}, my_text[0]}

		my_interpreter.Expr()
	}
}

三、运行结果

------------------ <PART-3> ------------------
[CALC]-> 9 -5
>  4
[CALC]-> 9-5+3
>  7
[CALC]->    9 - 5 + 3 + 11   
>  18
[CALC]-> 9+2+ 
[ERROR]  invalid token type.
[CALC]-> exit
-------------------程序已退出------------------
------------------- <END> --------------------

——2019-01-09——

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值