brainfuck解析器

看到一个有趣的问题

用不超过512个字符的brainfuck语言代码,输出一个尽可能大的数?2 关注 · 2 回答问题icon-default.png?t=N7T8https://www.zhihu.com/question/622572410

看了下brainfuck的语法,极其简单。

尝试写了一个解释器,顺便测试了下,挺有趣的。

package main

import (
	"os"
	"reflect"
	"strconv"
	"unsafe"
)

func BytesToString(data []byte) string {
	return *(*string)(unsafe.Pointer(&data))
}
func StringToReadBytes(data string) []byte {
	stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&data))
	byteHeader := reflect.SliceHeader{
		Data: stringHeader.Data,
		Len:  stringHeader.Len,
		Cap:  stringHeader.Len,
	}
	return *(*[]byte)(unsafe.Pointer(&byteHeader))
}

type Stack struct {
	Data  []int
	Count int
}

func (this *Stack) Push(n int) {
	if len(this.Data) <= this.Count {
		this.Data = append(this.Data, 0)
	}
	this.Data[this.Count] = n
	this.Count++
}

func (this *Stack) Pop() int {
	if this.Count == 0 {
		return 0
	}
	this.Count--
	return this.Data[this.Count]
}

func main() {
	args := os.Args
	dataMaxLen := 10240
	code := "-[>-[>+++++++[>++++++++<-]>.[-]<<-]<-]" //测试code
	codeIndex := 0
	outMaxLen := 1024
	input := []uint8{}
	inputIndex := 0
	argsNum := len(args)

	if argsNum >= 2 {
		code = args[1]
	}

	if argsNum >= 3 {
		input = StringToReadBytes(args[2])
	}

	if argsNum >= 4 {
		tmpNum, err := strconv.ParseUint(args[3], 10, 64)
		if err == nil {
			dataMaxLen = int(tmpNum)
		}
	}

	if argsNum >= 5 {
		tmpNum, err := strconv.ParseUint(args[4], 10, 64)
		if err == nil {
			outMaxLen = int(tmpNum)
		}
	}
	data := make([]uint8, dataMaxLen)
	dataIndex := dataMaxLen / 2
	stack := &Stack{}
	out := make([]uint8, outMaxLen)
	outIndex := 0
	println("code:", code, ";input:", BytesToString(input))
	for codeIndex < len(code) {
		switch code[codeIndex] {
		case '>':
			dataIndex++
			if dataIndex >= dataMaxLen {
				print("data index:", dataIndex, " out")
				return
			}
			codeIndex++
			break
		case '<':
			dataIndex--
			if dataIndex < 0 {
				print("data index:", dataIndex, " out")
				return
			}
			codeIndex++
			break
		case '+':
			data[dataIndex]++
			codeIndex++
			break
		case '-':
			data[dataIndex]--
			codeIndex++
			break
		case '.':

			if outIndex < outMaxLen {
				out[outIndex] = data[dataIndex]
				outIndex++
			}

			codeIndex++
			break
		case ',':
			if inputIndex < len(input) {
				data[dataIndex] = input[inputIndex]
				inputIndex++
			} else {
				data[dataIndex] = 0
			}
			codeIndex++
			break
		case '[':
			if data[dataIndex] != 0 { //进入循环体
				stack.Push(codeIndex)
				codeIndex++
			} else { //跳出
				left := 0
				for codeIndex < len(code) {
					if code[codeIndex] == '[' {
						left++
					} else if code[codeIndex] == ']' {
						left--
						if left == 0 {
							codeIndex++
							break
						}
					}
					codeIndex++
				}
			}
			break
		case ']':
			if stack.Count == 0 {
				codeIndex++
				break
			}
			codeIndex = stack.Pop()
			break
		default:
			codeIndex++
			break
		}
	}
	//把输出内容一次性输出
	print(BytesToString(out[:outIndex]))
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值