1 // Copyright 2013 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.
4 
5 // This is an example of a goyacc program.
6 // To build it:
7 // goyacc -p "expr" expr.y (produces y.go)
8 // go build -o expr y.go
9 // expr
10 // > <type an expression>
11 
12 %{
13 
14 package main
15 
16 import (
17 	"bufio"
18 	"bytes"
19 	"fmt"
20 	"io"
21 	"log"
22 	"math/big"
23 	"os"
24 	"unicode/utf8"
25 )
26 
27 %}
28 
29 %union {
30 	num *big.Rat
31 }
32 
33 %type	<num>	expr expr1 expr2 expr3
34 
35 %token '+' '-' '*' '/' '(' ')'
36 
37 %token	<num>	NUM
38 
39 %%
40 
41 top:
42 	expr
43 	{
44 		if $1.IsInt() {
45 			fmt.Println($1.Num().String())
46 		} else {
47 			fmt.Println($1.String())
48 		}
49 	}
50 
51 expr:
52 	expr1
53 |	'+' expr
54 	{
55 		$$ = $2
56 	}
57 |	'-' expr
58 	{
59 		$$ = $2.Neg($2)
60 	}
61 
62 expr1:
63 	expr2
64 |	expr1 '+' expr2
65 	{
66 		$$ = $1.Add($1, $3)
67 	}
68 |	expr1 '-' expr2
69 	{
70 		$$ = $1.Sub($1, $3)
71 	}
72 
73 expr2:
74 	expr3
75 |	expr2 '*' expr3
76 	{
77 		$$ = $1.Mul($1, $3)
78 	}
79 |	expr2 '/' expr3
80 	{
81 		$$ = $1.Quo($1, $3)
82 	}
83 
84 expr3:
85 	NUM
86 |	'(' expr ')'
87 	{
88 		$$ = $2
89 	}
90 
91 
92 %%
93 
94 // The parser expects the lexer to return 0 on EOF.  Give it a name
95 // for clarity.
96 const eof = 0
97 
98 // The parser uses the type <prefix>Lex as a lexer. It must provide
99 // the methods Lex(*<prefix>SymType) int and Error(string).
100 type exprLex struct {
101 	line []byte
102 	peek rune
103 }
104 
105 // The parser calls this method to get each new token. This
106 // implementation returns operators and NUM.
func(x * exprLex)107 func (x *exprLex) Lex(yylval *exprSymType) int {
108 	for {
109 		c := x.next()
110 		switch c {
111 		case eof:
112 			return eof
113 		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
114 			return x.num(c, yylval)
115 		case '+', '-', '*', '/', '(', ')':
116 			return int(c)
117 
118 		// Recognize Unicode multiplication and division
119 		// symbols, returning what the parser expects.
120 		case '×':
121 			return '*'
122 		case '÷':
123 			return '/'
124 
125 		case ' ', '\t', '\n', '\r':
126 		default:
127 			log.Printf("unrecognized character %q", c)
128 		}
129 	}
130 }
131 
132 // Lex a number.
133 func (x *exprLex) num(c rune, yylval *exprSymType) int {
134 	add := func(b *bytes.Buffer, c rune) {
135 		if _, err := b.WriteRune(c); err != nil {
136 			log.Fatalf("WriteRune: %s", err)
137 		}
138 	}
139 	var b bytes.Buffer
140 	add(&b, c)
141 	L: for {
142 		c = x.next()
143 		switch c {
144 		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'e', 'E':
145 			add(&b, c)
146 		default:
147 			break L
148 		}
149 	}
150 	if c != eof {
151 		x.peek = c
152 	}
153 	yylval.num = &big.Rat{}
154 	_, ok := yylval.num.SetString(b.String())
155 	if !ok {
156 		log.Printf("bad number %q", b.String())
157 		return eof
158 	}
159 	return NUM
160 }
161 
162 // Return the next rune for the lexer.
163 func (x *exprLex) next() rune {
164 	if x.peek != eof {
165 		r := x.peek
166 		x.peek = eof
167 		return r
168 	}
169 	if len(x.line) == 0 {
170 		return eof
171 	}
172 	c, size := utf8.DecodeRune(x.line)
173 	x.line = x.line[size:]
174 	if c == utf8.RuneError && size == 1 {
175 		log.Print("invalid utf8")
176 		return x.next()
177 	}
178 	return c
179 }
180 
181 // The parser calls this method on a parse error.
182 func (x *exprLex) Error(s string) {
183 	log.Printf("parse error: %s", s)
184 }
185 
186 func main() {
187 	in := bufio.NewReader(os.Stdin)
188 	for {
189 		if _, err := os.Stdout.WriteString("> "); err != nil {
190 			log.Fatalf("WriteString: %s", err)
191 		}
192 		line, err := in.ReadBytes('\n')
193 		if err == io.EOF {
194 			return
195 		}
196 		if err != nil {
197 			log.Fatalf("ReadBytes: %s", err)
198 		}
199 
200 		exprParse(&exprLex{line: line})
201 	}
202 }
203