diff options
Diffstat (limited to 'src/cmd/yacc')
-rw-r--r-- | src/cmd/yacc/Makefile | 12 | ||||
-rw-r--r-- | src/cmd/yacc/doc.go | 5 | ||||
-rw-r--r-- | src/cmd/yacc/testdata/expr/README | 20 | ||||
-rw-r--r-- | src/cmd/yacc/testdata/expr/expr.y (renamed from src/cmd/yacc/expr.y) | 7 | ||||
-rw-r--r-- | src/cmd/yacc/testdata/expr/main.go | 15 | ||||
-rw-r--r-- | src/cmd/yacc/yacc.go | 90 |
6 files changed, 62 insertions, 87 deletions
diff --git a/src/cmd/yacc/Makefile b/src/cmd/yacc/Makefile deleted file mode 100644 index f8c8169bd..000000000 --- a/src/cmd/yacc/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -# Copyright 2009 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. - -TARG=expr$(shell go env GOEXE) - -$(TARG): yacc.go expr.y - go run yacc.go -p expr expr.y - go build -o $(TARG) y.go - -clean: - rm -f y.go y.output $(TARG) diff --git a/src/cmd/yacc/doc.go b/src/cmd/yacc/doc.go index ceaaf2448..702c9f0d2 100644 --- a/src/cmd/yacc/doc.go +++ b/src/cmd/yacc/doc.go @@ -20,8 +20,9 @@ written in C and documented at Adepts of the original yacc will have no trouble adapting to this form of the tool. -The file expr.y in this directory is a yacc grammar for a very simple -expression parser. It needs the flag "-p expr" (see below). +The directory $GOROOT/cmd/yacc/testdata/expr is a yacc program +for a very simple expression parser. See expr.y and main.go in that +directory for examples of how to write and build yacc programs. The generated parser is reentrant. Parse expects to be given an argument that conforms to the following interface: diff --git a/src/cmd/yacc/testdata/expr/README b/src/cmd/yacc/testdata/expr/README new file mode 100644 index 000000000..302ef57a7 --- /dev/null +++ b/src/cmd/yacc/testdata/expr/README @@ -0,0 +1,20 @@ +This directory contains a simple program demonstrating how to use +the Go version of yacc. + +To build it: + + $ go generate + $ go build + +or + + $ go generate + $ go run expr.go + +The file main.go contains the "go generate" command to run yacc to +create expr.go from expr.y. It also has the package doc comment, +as godoc will not scan the .y file. + +The actual implementation is in expr.y. + +The program is not installed in the binary distributions of Go. diff --git a/src/cmd/yacc/expr.y b/src/cmd/yacc/testdata/expr/expr.y index 77e9259da..721b1c917 100644 --- a/src/cmd/yacc/expr.y +++ b/src/cmd/yacc/testdata/expr/expr.y @@ -11,11 +11,6 @@ %{ -// This tag will be copied to the generated file to prevent that file -// confusing a future build. - -// +build ignore - package main import ( @@ -37,6 +32,8 @@ import ( %type <num> expr expr1 expr2 expr3 +%token '+' '-' '*' '/' '(' ')' + %token <num> NUM %% diff --git a/src/cmd/yacc/testdata/expr/main.go b/src/cmd/yacc/testdata/expr/main.go new file mode 100644 index 000000000..8d5b6911f --- /dev/null +++ b/src/cmd/yacc/testdata/expr/main.go @@ -0,0 +1,15 @@ +// Copyright 2014 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. + +// This file holds the go generate command to run yacc on the grammar in expr.y. +// To build expr: +// % go generate +// % go build + +//go:generate -command yacc go tool yacc +//go:generate yacc -o expr.go -p "expr" expr.y + +// Expr is a simple expression evaluator that serves as a working example of +// how to use Go's yacc implemenation. +package main diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go index c53403266..4dba376fc 100644 --- a/src/cmd/yacc/yacc.go +++ b/src/cmd/yacc/yacc.go @@ -52,9 +52,9 @@ import ( "go/format" "io/ioutil" "os" + "strconv" "strings" "unicode" - "unicode/utf8" ) // the following are adjustable @@ -195,8 +195,9 @@ type Item struct { } type Symb struct { - name string - value int + name string + noconst bool + value int } type Wset struct { @@ -509,8 +510,7 @@ outer: // put out non-literal terminals for i := TOKSTART; i <= ntokens; i++ { // non-literals - c := tokset[i].name[0] - if c != ' ' && c != '$' { + if !tokset[i].noconst { fmt.Fprintf(ftable, "const %v = %v\n", tokset[i].name, tokset[i].value) } } @@ -734,7 +734,7 @@ func defin(nt int, s string) int { copy(anontrst, nontrst) nontrst = anontrst } - nontrst[nnonter] = Symb{s, 0} + nontrst[nnonter] = Symb{name: s} return NTBASE + nnonter } @@ -756,70 +756,26 @@ func defin(nt int, s string) int { // establish value for token // single character literal - if s[0] == ' ' { - s = s[1:] - r, size := utf8.DecodeRuneInString(s) - if r == utf8.RuneError && size == 1 { - errorf("invalid UTF-8 sequence %q", s) - } - val = int(r) - if val == '\\' { // escape sequence - switch { - case len(s) == 2: - // single character escape sequence - switch s[1] { - case '\'': - val = '\'' - case '"': - val = '"' - case '\\': - val = '\\' - case 'a': - val = '\a' - case 'b': - val = '\b' - case 'f': - val = '\f' - case 'n': - val = '\n' - case 'r': - val = '\r' - case 't': - val = '\t' - case 'v': - val = '\v' - default: - errorf("invalid escape %s", s) - } - case s[1] == 'u' && len(s) == 2+4, // \unnnn sequence - s[1] == 'U' && len(s) == 2+8: // \Unnnnnnnn sequence - val = 0 - s = s[2:] - for s != "" { - c := int(s[0]) - switch { - case c >= '0' && c <= '9': - c -= '0' - case c >= 'a' && c <= 'f': - c -= 'a' - 10 - case c >= 'A' && c <= 'F': - c -= 'A' - 10 - default: - errorf(`illegal \u or \U construction`) - } - val = val*16 + c - s = s[1:] - } - default: - errorf("invalid escape %s", s) - } + if s[0] == '\'' || s[0] == '"' { + q, err := strconv.Unquote(s) + if err != nil { + errorf("invalid token: %s", err) + } + rq := []rune(q) + if len(rq) != 1 { + errorf("character token too long: %s", s) } + val = int(rq[0]) if val == 0 { errorf("token value 0 is illegal") } + tokset[ntokens].noconst = true } else { val = extval extval++ + if s[0] == '$' { + tokset[ntokens].noconst = true + } } tokset[ntokens].value = val @@ -896,7 +852,7 @@ func gettok() int { case '"', '\'': match = c - tokname = " " + tokname = string(c) for { c = getrune(finput) if c == '\n' || c == EOF { @@ -909,6 +865,7 @@ func gettok() int { if tokflag { fmt.Printf(">>> IDENTIFIER \"%v\" %v\n", tokname, lineno) } + tokname += string(c) return IDENTIFIER } tokname += string(c) @@ -1029,7 +986,7 @@ func fdtype(t int) int { } func chfind(t int, s string) int { - if s[0] == ' ' { + if s[0] == '"' || s[0] == '\'' { t = 0 } for i := 0; i <= ntokens; i++ { @@ -1516,9 +1473,6 @@ func symnam(i int) string { } else { s = tokset[i].name } - if s[0] == ' ' { - s = s[1:] - } return s } |