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.
5 // This is an example of a goyacc program.
7 // goyacc -p "expr" expr.y (produces y.go)
8 // go build -o expr y.go
10 // > <type an expression>
33 %type
<num
> expr expr1 expr2 expr3
35 %token
'+' '-' '*' '/' '(' ')'
45 fmt.Println
($1.Num
().String
())
47 fmt.Println
($1.String
())
94 // The parser expects the lexer to return 0 on EOF. Give it a name
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 {
105 // The parser calls this method to get each new token. This
106 // implementation returns operators and NUM.
107 func
(x
*exprLex
) Lex
(yylval *exprSymType
) int {
113 case
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
114 return x.num
(c
, yylval)
115 case
'+', '-', '*', '/', '(', ')':
118 // Recognize Unicode multiplication and division
119 // symbols, returning what the parser expects.
125 case
' ', '\t', '\n', '\r':
127 log.Printf
("unrecognized character %q", c
)
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
)
144 case
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'e', 'E':
153 yylval.num
= &big.Rat
{}
154 _
, ok
:= yylval.num.SetString
(b.String
())
156 log.Printf
("bad number %q", b.String
())
162 // Return the next rune for the lexer.
163 func
(x
*exprLex
) next
() rune
{
169 if len
(x.line
) == 0 {
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")
181 // The parser calls this method on a parse error.
182 func
(x
*exprLex
) Error
(s
string) {
183 log.Printf
("parse error: %s", s
)
187 in
:= bufio.NewReader
(os.Stdin
)
189 if _
, err
:= os.Stdout.WriteString
("> "); err
!= nil
{
190 log.Fatalf
("WriteString: %s", err
)
192 line
, err
:= in.ReadBytes
('\n')
197 log.Fatalf
("ReadBytes: %s", err
)
200 exprParse
(&exprLex
{line
: line
})