1
// Copyright 2010 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
15
// Generic expression parser/evaluator
17
type Value interface {
19
BinaryOp(op string, y Value) Value
23
precTab map[string]int
24
newVal func(string) Value
30
const alphanum = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
32
func (p *Parser) stop(c uint8) bool {
34
case p.pos >= len(p.src):
37
if p.src[p.pos] == '"' {
42
case strings.IndexRune(alphanum, int(c)) >= 0:
43
return strings.IndexRune(alphanum, int(p.src[p.pos])) < 0
48
func (p *Parser) next() {
50
for ; p.pos < len(p.src) && p.src[p.pos] <= ' '; p.pos++ {
52
if p.pos >= len(p.src) {
58
for p.pos < len(p.src) {
64
p.tok = p.src[start:p.pos]
67
func (p *Parser) binaryExpr(prec1 int) Value {
70
for prec := p.precTab[p.tok]; prec >= prec1; prec-- {
71
for p.precTab[p.tok] == prec {
74
y := p.binaryExpr(prec + 1)
81
func Eval(precTab map[string]int, newVal func(string) Value, src string) Value {
87
return p.binaryExpr(1)
90
// Command-line expression evaluator
93
r := bufio.NewReader(os.Stdin)
96
line, err := r.ReadString('\n')
100
fmt.Printf("%s\n", Eval(precTab, trace(newVal), line))
104
// Custom grammar and values
106
var precTab = map[string]int{
122
func newVal(lit string) Value {
123
x, err := strconv.Atoi(lit)
127
b, err := strconv.ParseBool(lit)
131
return Error(fmt.Sprintf("illegal literal '%s'", lit))
136
func (e Error) String() string { return string(e) }
137
func (e Error) BinaryOp(op string, y Value) Value { return e }
141
func (x Int) String() string { return strconv.Itoa(int(x)) }
142
func (x Int) BinaryOp(op string, y Value) Value {
143
switch y := y.(type) {
172
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
177
func (x Bool) String() string { return strconv.FormatBool(bool(x)) }
178
func (x Bool) BinaryOp(op string, y Value) Value {
179
switch y := y.(type) {
194
return Error(fmt.Sprintf("illegal operation: '%v %s %v'", x, op, y))
197
func trace(newVal func(string) Value) func(string) Value {
198
return func(s string) Value {
200
fmt.Printf("\tnewVal(%q) = %s\n", s, fmtv(v))
201
return &traceValue{v}
205
type traceValue struct {
209
func (x *traceValue) BinaryOp(op string, y Value) Value {
210
z := x.Value.BinaryOp(op, y.(*traceValue).Value)
211
fmt.Printf("\t%s.BinaryOp(%q, %s) = %s\n", fmtv(x.Value), op, fmtv(y.(*traceValue).Value), fmtv(z))
212
return &traceValue{z}
215
func (x *traceValue) String() string {
216
s := x.Value.String()
217
fmt.Printf("\t%s.String() = %#v\n", fmtv(x.Value), s)
221
func fmtv(v Value) string {
222
t := fmt.Sprintf("%T", v)
223
if i := strings.LastIndex(t, "."); i >= 0 { // strip package
226
return fmt.Sprintf("%s(%#v)", t, v)