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
14package main
15
16import (
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
41top:
42 expr
43 {
44 if $1.IsInt() {
45 fmt.Println($1.Num().String())
46 } else {
47 fmt.Println($1.String())
48 }
49 }
50
51expr:
52 expr1
53| '+' expr
54 {
55 $$ = $2
56 }
57| '-' expr
58 {
59 $$ = $2.Neg($2)
60 }
61
62expr1:
63 expr2
64| expr1 '+' expr2
65 {
66 $$ = $1.Add($1, $3)
67 }
68| expr1 '-' expr2
69 {
70 $$ = $1.Sub($1, $3)
71 }
72
73expr2:
74 expr3
75| expr2 '*' expr3
76 {
77 $$ = $1.Mul($1, $3)
78 }
79| expr2 '/' expr3
80 {
81 $$ = $1.Quo($1, $3)
82 }
83
84expr3:
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.
96const 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).
100type 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.
107func (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.
133func (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.
163func (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.
182func (x *exprLex) Error(s string) {
183 log.Printf("parse error: %s", s)
184}
185
186func 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}
View as plain text