You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
136 lines
2.5 KiB
Go
136 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"strings"
|
|
"strconv"
|
|
)
|
|
|
|
type operation func(*[]int, *int) string
|
|
type numberError string
|
|
type bufferError string
|
|
|
|
func (n numberError) Error() string { return string(n) }
|
|
func (n bufferError) Error() string { return string(n) }
|
|
|
|
var stack []int
|
|
var stackpointer int
|
|
var dictionary = map[string]operation{
|
|
"base" : func(st *[]int, stp *int) string {
|
|
base, _ := getvalue(st, stp)
|
|
r, err := getvalue(st, stp)
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
return strconv.FormatInt(int64(r), base)
|
|
},
|
|
"+" : func(st *[]int, stp *int) string {
|
|
n1, _ := getvalue(st, stp)
|
|
n2, err := getvalue(st, stp)
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
err = putvalue(st, stp, n1+n2)
|
|
if err != nil {
|
|
return err.Error()
|
|
}
|
|
return "*"
|
|
},
|
|
"quit": func(_ *[]int, _ *int) string {
|
|
os.Exit(0)
|
|
return "should have quit"
|
|
},
|
|
}
|
|
|
|
func getvalue(st *[]int, stp *int) (int, error) {
|
|
if *stp < 1 {
|
|
return 0, bufferError("buffer underflow")
|
|
}
|
|
r := (*st)[*stp-1]
|
|
*st = (*st)[:len(*st)-1]
|
|
*stp--
|
|
return r, nil
|
|
}
|
|
|
|
func putvalue(st *[]int, stp *int, n int) error {
|
|
if *stp == int(^uint(0) >> 1) { // check for maxint
|
|
return bufferError("buffer overflow")
|
|
}
|
|
*st = append(*st, n)
|
|
*stp++
|
|
return nil
|
|
}
|
|
|
|
func read(r *bufio.Reader) (string, error) {
|
|
s, err := r.ReadString('\n')
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return s[:len(s)-1], err
|
|
}
|
|
|
|
func pow(n, p int) int {
|
|
r := 1
|
|
for i := 0; i < p; i++ {
|
|
r *= n
|
|
}
|
|
return r
|
|
}
|
|
|
|
func number(st *[]int, stp *int, cmd string) error {
|
|
base := 6
|
|
if len(cmd) < 1 {
|
|
return numberError("tried parsing empty value")
|
|
}
|
|
switch {
|
|
case cmd[0] == 'd':
|
|
base = 10
|
|
case cmd[0] == 'x':
|
|
base = 16
|
|
case cmd[0] == '0':
|
|
base = 8
|
|
case cmd[0] == 'b':
|
|
base = 2
|
|
case cmd[0] == '#':
|
|
base = 36
|
|
}
|
|
if base != 6 {
|
|
cmd = cmd[1:]
|
|
}
|
|
val, err := strconv.ParseInt(cmd, base, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return putvalue(st, stp, int(val))
|
|
}
|
|
|
|
func eval(code string, inerr error) string {
|
|
if inerr != nil {
|
|
return "Error before evaluating code: " + inerr.Error()
|
|
}
|
|
var value string
|
|
for _, cmd := range strings.Split(code, " ") {
|
|
op, ok := dictionary[cmd]
|
|
if ok {
|
|
value = op(&stack, &stackpointer)
|
|
continue
|
|
}
|
|
err := number(&stack, &stackpointer, cmd)
|
|
if err != nil {
|
|
return "Error reading value: " + err.Error()
|
|
}
|
|
}
|
|
return value
|
|
}
|
|
|
|
func main() {
|
|
stdin := bufio.NewReader(os.Stdin)
|
|
dictionary["."] = func(st *[]int, stp *int) string {
|
|
return eval("10 base", nil)
|
|
}
|
|
for {
|
|
println(eval(read(stdin)))
|
|
}
|
|
}
|