// Copyright 2010 The Go Authors.  All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package main

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

// Generic expression parser/evaluator

type Value interface {
	String() string
	BinaryOp(op string, y Value) Value
}

type Parser struct {
	precTab map[string]int
	newVal  func(string) Value
	src     string
	pos     int
	tok     string
}

const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"

func (p *Parser) stop(c uint8) bool {
	switch {
	case p.pos >= len(p.src):
		return true
	case c == '"':
		if p.src[p.pos] == '"' {
			p.pos++
			return true
		}
		return false
	case strings.IndexRune(alphanum, int(c)) >= 0:
		return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
	}
	return true
}

func (p *Parser) next() {
	// skip blanks
	for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
	}
	if p.pos >= len(p.src) {
		p.tok = ""
		return
	}
	start := p.pos
	c := p.src[p.pos]
	for p.pos < len(p.src) {
		p.pos++
		if p.stop(c) {
			break
		}
	}
	p.tok = p.src[start:p.pos]
}

func (p *Parser) binaryExpr(prec1 int) Value {
	x := p.newVal(p.tok)
	p.next()
	for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
		for p.precTab[p.tok] == prec {
			op := p.tok
			p.next()
			y := p.binaryExpr(prec + 1)
			x = x.BinaryOp(op, y)
		}
	}
	return x
}

func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
	var p Parser
	p.precTab = precTab
	p.newVal = newVal
	p.src = src
	p.next()
	return p.binaryExpr(1)
}

// Command-line expression evaluator

func main() {
	r := bufio.NewReader(os.Stdin)
	for {
		fmt.Printf("> ")
		line, err := r.ReadString('\n')
		if err != nil {
			break
		}
		fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
	}
}

// Custom grammar and values

var precTab = map[string]int{
	"&&": 1,
	"||": 2,
	"==": 3,
	"!=": 3,
	"<":  3,
	"<=": 3,
	">":  3,
	">=": 3,
	"+":  4,
	"-":  4,
	"*":  5,
	"/":  5,
	"%":  5,
}

func newVal(lit string) Value {
	x, err := strconv.Atoi(lit)
	if err == nil {
		return Int(x)
	}
	b, err := strconv.ParseBool(lit)
	if err == nil {
		return Bool(b)
	}
	s, err := strconv.Unquote(lit)
	if err == nil {
		return String(s)
	}
	return Error(fmt.Sprintf("illegal literal '%s'", lit))
}

type Error string

func (e Error) String() string                    { return string(e) }
func (e Error) BinaryOp(op string, y Value) Value { return e }

type Int int

func (x Int) String() string { return strconv.Itoa(int(x)) }
func (x Int) BinaryOp(op string, y Value) Value {
	switch y := y.(type) {
	case Error:
		return y
	case String:
		switch op {
		case "*":
			return String(strings.Repeat(string(y), int(x)))
		}
	case Int:
		switch op {
		case "+":
			return x + y
		case "-":
			return x - y
		case "*":
			return x * y
		case "/":
			return x / y
		case "%":
			return x % y
		case "==":
			return Bool(x == y)
		case "!=":
			return Bool(x != y)
		case "<":
			return Bool(x < y)
		case "<=":
			return Bool(x <= y)
		case ">":
			return Bool(x > y)
		case ">=":
			return Bool(x >= y)
		}
	}
	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
}

type Bool bool

func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
func (x Bool) BinaryOp(op string, y Value) Value {
	switch y := y.(type) {
	case Error:
		return y
	case Bool:
		switch op {
		case "&&":
			return Bool(x && y)
		case "||":
			return Bool(x || y)
		case "==":
			return Bool(x == y)
		case "!=":
			return Bool(x != y)
		}
	}
	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
}

type String string

func (x String) String() string { return strconv.Quote(string(x)) }
func (x String) BinaryOp(op string, y Value) Value {
	switch y := y.(type) {
	case Error:
		return y
	case Int:
		switch op {
		case "*":
			return String(strings.Repeat(string(x), int(y)))
		}
	case String:
		switch op {
		case "+":
			return x + y
		case "<":
			return Bool(x < y)
		}
	}
	return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
}

func trace(newVal func(string) Value) func(string) Value {
	return func(s string) Value {
		v := newVal(s)
		fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
		return &traceValue{v}
	}
}

type traceValue struct {
	Value
}

func (x *traceValue) BinaryOp(op string, y Value) Value {
	z := x.Value.BinaryOp(op, y.(*traceValue).Value)
	fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
	return &traceValue{z}
}

func (x *traceValue) String() string {
	s := x.Value.String()
	fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
	return s
}

func fmtv(v Value) string {
	t := fmt.Sprintf("%T", v)
	if i := strings.LastIndex(t, "."); i >= 0 { // strip package
		t = t[i+1:]
	}
	return fmt.Sprintf("%s(%#v)", t, v)
}
