summaryrefslogtreecommitdiff
path: root/src/cmd/yacc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/yacc')
-rw-r--r--src/cmd/yacc/doc.go2
-rw-r--r--src/cmd/yacc/units.txt104
-rw-r--r--src/cmd/yacc/units.y35
-rw-r--r--src/cmd/yacc/yacc.go257
4 files changed, 261 insertions, 137 deletions
diff --git a/src/cmd/yacc/doc.go b/src/cmd/yacc/doc.go
index 4a2c2a314..792c104e3 100644
--- a/src/cmd/yacc/doc.go
+++ b/src/cmd/yacc/doc.go
@@ -48,4 +48,4 @@ referenced by yacc's generated code. Setting it to distinct values
allows multiple grammars to be placed in a single package.
*/
-package documentation
+package main
diff --git a/src/cmd/yacc/units.txt b/src/cmd/yacc/units.txt
index ddb2bc294..df8f567d9 100644
--- a/src/cmd/yacc/units.txt
+++ b/src/cmd/yacc/units.txt
@@ -215,58 +215,58 @@ lumen cd sr
lux cd sr/m²
/ MONEY DATE
-/ Thu Sep 10 2009
-
-argentinapeso 1 | 0.2595 $
-australiadollar 1 | 0.8618 $
-boliviaboliviano 1 | 0.1425 $
-brazilreal 1 | 0.5522 $
-britainpound 1 | 1.6651 $
-canadadollar 1 | 0.9277 $
-chilepeso 1 | 0.0018 $
-chinayuan 1 | 0.1464 $
-colombiapeso 1 | 0.0005 $
-czechkoruna 1 | 0.0572 $
-denmarkkrone 1 | 0.1958 $
-dominicanpeso 1 | 0.0278 $
-egyptpound 1 | 0.181 $
-elsalvadorcolon 1 | 0.1143 $
-europeuro 1 | 1.4577 $
-guatemalaquetzal 1 | 0.121 $
-honduraslempira 1 | 0.0529 $
-hongkongdollar 1 | 0.129 $
-hungaryforint 1 | 0.0054 $
-indiarupee 1 | 0.0207 $
-indonesiarupiah 1 | 0.0001 $
-israelshekel 1 | 0.2643 $
-japanyen 1 | 0.0109 $
-kenyashilling 1 | 0.0132 $
-kuwaitdinar 1 | 3.4854 $
-lebanonpound 1 | 0.0007 $
-malaysiaringgit 1 | 0.286 $
-mexicopeso 1 | 0.0748 $
-newzealanddollar 1 | 0.7028 $
-nicaraguacordoba 1 | 0.0487 $
-norwaykrone 1 | 0.1681 $
-pakistanrupee 1 | 0.0121 $
-paraguayguarani 1 | 0.0002 $
-perunewsol 1 | 0.3384 $
-philippinespeso 1 | 0.0207 $
-polandzloty 1 | 0.352 $
-russiaruble 1 | 0.0324 $
-saudiarabiariyal 1 | 0.2666 $
-singaporedollar 1 | 0.7018 $
-slovakkoruna 1 | 0.0484 $
-southafricarand 1 | 0.132 $
-southkoreawon 1 | 0.0008 $
-swedenkrona 1 | 0.1429 $
-switzerlandfranc 1 | 0.9627 $
-taiwandollar 1 | 0.0306 $
-thailandbaht 1 | 0.0294 $
-turkeynewlira 1 | 0.6678 $
-uaedirham 1 | 0.2722 $
-uruguaynewpeso 1 | 0.0451 $
-vietnamdong 1 | 0.0001 $
+/ Wed Aug 29, 2012
+
+argentinapeso $ 0.2160
+australiadollar $ 1.0372
+boliviaboliviano $ 0.1427
+brazilreal $ 0.4872
+britainpound $ 1.5843
+canadadollar $ 1.0117
+chilepeso $ 1 | 480.6
+chinayuan $ 0.1574
+colombiapeso $ 1 | 1834
+czechkoruna $ 0.0506
+denmarkkrone $ 0.1681
+dominicanpeso $ 0.0256
+egyptpound $ 0.1640
+elsalvadorcolon $ 1 | 8.75
+europeuro $ 1.2528
+guatemalaquetzal $ 0.1290
+honduraslempira $ 0.0511
+hongkongdollar $ 0.1289
+hungaryforint $ 1 | 226.5
+indiarupee $ 0.0180
+indonesiarupiah $ 1 | 9540
+israelshekel $ 0.2479
+japanyen $ 0.0127
+kenyashilling $ 0.0119
+kuwaitdinar $ 3.5456
+lebanonpound $ 1 | 1505.5
+malaysiaringgit $ 0.3204
+mexicopeso $ 0.0754
+newzealanddollar $ 0.8035
+nicaraguacordoba $ 0.0421
+norwaykrone $ 0.1717
+pakistanrupee $ 0.0106
+paraguayguarani $ 1 | 4415
+perunewsol $ 0.3832
+philippinespeso $ 0.0236
+polandzloty $ 0.3001
+russiaruble $ 0.0311
+saudiarabiariyal $ 1 | 3.75
+singaporedollar $ 0.7976
+slovakkoruna 1 | 30.126 europeuro
+southafricarand $ 0.1188
+southkoreawon $ 1 | 1135
+swedenkrona $ 0.1502
+switzerlandfranc $ 1.0431
+taiwandollar $ 0.0334
+thailandbaht $ 0.0319
+turkeynewlira $ 0.5504
+uaedirham $ 0.2723
+uruguaynewpeso $ 0.0465
+vietnamdong $ 1 | 20865
/ END MONEY
diff --git a/src/cmd/yacc/units.y b/src/cmd/yacc/units.y
index 7258e3e59..9c1b0b336 100644
--- a/src/cmd/yacc/units.y
+++ b/src/cmd/yacc/units.y
@@ -11,6 +11,11 @@
%{
+// This tag will end up in the generated y.go, so that forgetting
+// 'make clean' does not fail the next build.
+
+// +build ignore
+
// units.y
// example of a Go yacc program
// usage is
@@ -26,11 +31,13 @@
package main
import (
+ "bufio"
"flag"
"fmt"
- "bufio"
- "os"
"math"
+ "runtime"
+ "os"
+ "path/filepath"
"strconv"
"unicode/utf8"
)
@@ -74,9 +81,9 @@ var vflag bool
%type <node> prog expr expr0 expr1 expr2 expr3 expr4
-%token <vval> VAL
+%token <vval> VÄL // dieresis to test UTF-8
%token <vvar> VAR
-%token <numb> SUP
+%token <numb> _SUP // tests leading underscore in token name
%%
prog:
':' VAR expr
@@ -157,7 +164,7 @@ expr3:
expr2:
expr1
-| expr2 SUP
+| expr2 _SUP
{
xpn(&$$, &$1, $2)
}
@@ -197,7 +204,7 @@ expr0:
$$ = $1.node
}
}
-| VAL
+| VÄL
{
$$ = one
$$.vval = $1
@@ -234,13 +241,13 @@ loop:
return '/'
case '¹', 'ⁱ':
yylval.numb = 1
- return SUP
+ return _SUP
case '²', '⁲':
yylval.numb = 2
- return SUP
+ return _SUP
case '³', '⁳':
yylval.numb = 3
- return SUP
+ return _SUP
}
return int(c)
@@ -273,7 +280,7 @@ numb:
f = 0
}
yylval.vval = f
- return VAL
+ return VÄL
}
func (UnitsLex) Error(s string) {
@@ -287,13 +294,11 @@ func main() {
flag.Parse()
- if dir := os.Getenv("GOROOT"); dir != "" {
- file = dir + "/src/cmd/yacc/units.txt"
- }
+ file = filepath.Join(runtime.GOROOT(), "src/cmd/yacc/units.txt")
if flag.NArg() > 0 {
file = flag.Arg(0)
} else if file == "" {
- fmt.Fprintf(os.Stderr, "can not find data file units.txt; provide it as argument or set $GOROOT\n")
+ fmt.Fprintf(os.Stderr, "cannot find data file units.txt; provide it as argument or set $GOROOT\n")
os.Exit(1)
}
@@ -308,7 +313,7 @@ func main() {
/*
* read the 'units' file to
- * develope a database
+ * develop a database
*/
lineno = 0
for {
diff --git a/src/cmd/yacc/yacc.go b/src/cmd/yacc/yacc.go
index e94228152..0c18f93b6 100644
--- a/src/cmd/yacc/yacc.go
+++ b/src/cmd/yacc/yacc.go
@@ -51,6 +51,8 @@ import (
"fmt"
"os"
"strings"
+ "unicode"
+ "unicode/utf8"
)
// the following are adjustable
@@ -153,6 +155,8 @@ var ftable *bufio.Writer // y.go file
var fcode = &bytes.Buffer{} // saved code
var foutput *bufio.Writer // y.output file
+var fmtImported bool // output file has recorded an import of "fmt"
+
var oflag string // -o [y.go] - y.go file
var vflag string // -v [y.output] - y.output file
var lflag bool // -l - disable line directives
@@ -323,7 +327,6 @@ var resrv = []Resrv{
var zznewstate = 0
const EOF = -1
-const UTFmax = 0x3f
func main() {
@@ -716,8 +719,8 @@ func moreprod() {
}
//
-// define s to be a terminal if t=0
-// or a nonterminal if t=1
+// define s to be a terminal if nt==0
+// or a nonterminal if nt==1
//
func defin(nt int, s string) int {
val := 0
@@ -750,56 +753,66 @@ func defin(nt int, s string) int {
// establish value for token
// single character literal
- if s[0] == ' ' && len(s) == 1+1 {
- val = int(s[1])
- } else if s[0] == ' ' && s[1] == '\\' { // escape sequence
- if len(s) == 2+1 {
- // single character escape sequence
- switch s[2] {
- case '\'':
- val = '\''
- case '"':
- val = '"'
- case '\\':
- val = '\\'
- case 'a':
- val = '\a'
- case 'b':
- val = '\b'
- case 'n':
- val = '\n'
- case 'r':
- val = '\r'
- case 't':
- val = '\t'
- case 'v':
- val = '\v'
- default:
- errorf("invalid escape %v", s[1:3])
- }
- } else if s[2] == 'u' && len(s) == 2+1+4 { // \unnnn sequence
- val = 0
- s = s[3:]
- 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
+ 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("illegal \\unnnn construction")
+ errorf("invalid escape %s", s)
}
- val = val*16 + c
- s = s[1:]
- }
- if val == 0 {
- errorf("'\\u0000' is illegal")
+ 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)
}
- } else {
- errorf("unknown escape")
+ }
+ if val == 0 {
+ errorf("token value 0 is illegal")
}
} else {
val = extval
@@ -985,7 +998,7 @@ func gettok() int {
func getword(c rune) {
tokname = ""
- for isword(c) || isdigit(c) || c == '_' || c == '.' || c == '$' {
+ for isword(c) || isdigit(c) || c == '.' || c == '$' {
tokname += string(c)
c = getrune(finput)
}
@@ -1073,6 +1086,7 @@ out:
//
// saves code between %{ and %}
+// adds an import for __fmt__ the first time
//
func cpycode() {
lno := lineno
@@ -1085,15 +1099,18 @@ func cpycode() {
if !lflag {
fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
}
+ // accumulate until %}
+ code := make([]rune, 0, 1024)
for c != EOF {
if c == '%' {
c = getrune(finput)
if c == '}' {
+ emitcode(code, lno+1)
return
}
- ftable.WriteRune('%')
+ code = append(code, '%')
}
- ftable.WriteRune(c)
+ code = append(code, c)
if c == '\n' {
lineno++
}
@@ -1104,6 +1121,107 @@ func cpycode() {
}
//
+// emits code saved up from between %{ and %}
+// called by cpycode
+// adds an import for __yyfmt__ after the package clause
+//
+func emitcode(code []rune, lineno int) {
+ for i, line := range lines(code) {
+ writecode(line)
+ if !fmtImported && isPackageClause(line) {
+ fmt.Fprintln(ftable, `import __yyfmt__ "fmt"`)
+ fmt.Fprintf(ftable, "//line %v:%v\n\t\t", infile, lineno+i)
+ fmtImported = true
+ }
+ }
+}
+
+//
+// does this line look like a package clause? not perfect: might be confused by early comments.
+//
+func isPackageClause(line []rune) bool {
+ line = skipspace(line)
+
+ // must be big enough.
+ if len(line) < len("package X\n") {
+ return false
+ }
+
+ // must start with "package"
+ for i, r := range []rune("package") {
+ if line[i] != r {
+ return false
+ }
+ }
+ line = skipspace(line[len("package"):])
+
+ // must have another identifier.
+ if len(line) == 0 || (!unicode.IsLetter(line[0]) && line[0] != '_') {
+ return false
+ }
+ for len(line) > 0 {
+ if !unicode.IsLetter(line[0]) && !unicode.IsDigit(line[0]) && line[0] != '_' {
+ break
+ }
+ line = line[1:]
+ }
+ line = skipspace(line)
+
+ // eol, newline, or comment must follow
+ if len(line) == 0 {
+ return true
+ }
+ if line[0] == '\r' || line[0] == '\n' {
+ return true
+ }
+ if len(line) >= 2 {
+ return line[0] == '/' && (line[1] == '/' || line[1] == '*')
+ }
+ return false
+}
+
+//
+// skip initial spaces
+//
+func skipspace(line []rune) []rune {
+ for len(line) > 0 {
+ if line[0] != ' ' && line[0] != '\t' {
+ break
+ }
+ line = line[1:]
+ }
+ return line
+}
+
+//
+// break code into lines
+//
+func lines(code []rune) [][]rune {
+ l := make([][]rune, 0, 100)
+ for len(code) > 0 {
+ // one line per loop
+ var i int
+ for i = range code {
+ if code[i] == '\n' {
+ break
+ }
+ }
+ l = append(l, code[:i+1])
+ code = code[i+1:]
+ }
+ return l
+}
+
+//
+// writes code to ftable
+//
+func writecode(code []rune) {
+ for _, r := range code {
+ ftable.WriteRune(r)
+ }
+}
+
+//
// skip over comments
// skipcom is called after reading a '/'
//
@@ -1230,7 +1348,7 @@ loop:
if j >= max {
errorf("Illegal use of $%v", j)
}
- } else if isword(c) || c == '_' || c == '.' {
+ } else if isword(c) || c == '.' {
// look for $name
ungetrune(finput, c)
if gettok() != IDENTIFIER {
@@ -2775,7 +2893,7 @@ func others() {
j = tokset[i].value
if j >= 0 && j < 256 {
if temp1[j] != 0 {
- fmt.Print("yacc bug -- cant have 2 different Ts with same value\n")
+ fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
fmt.Printf(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name)
nerrors++
}
@@ -2799,7 +2917,7 @@ func others() {
j = tokset[i].value - PRIVATE
if j >= 0 && j < 256 {
if temp1[j] != 0 {
- fmt.Print("yacc bug -- cant have 2 different Ts with same value\n")
+ fmt.Print("yacc bug -- cannot have 2 different Ts with same value\n")
fmt.Printf(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name)
nerrors++
}
@@ -2982,7 +3100,7 @@ var peekrune rune
func isdigit(c rune) bool { return c >= '0' && c <= '9' }
func isword(c rune) bool {
- return c >= 0xa0 || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+ return c >= 0xa0 || c == '_' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
}
func mktemp(t string) string { return t }
@@ -3110,12 +3228,13 @@ type $$Lexer interface {
const $$Flag = -1000
func $$Tokname(c int) string {
- if c > 0 && c <= len($$Toknames) {
- if $$Toknames[c-1] != "" {
- return $$Toknames[c-1]
+ // 4 is TOKSTART above
+ if c >= 4 && c-4 < len($$Toknames) {
+ if $$Toknames[c-4] != "" {
+ return $$Toknames[c-4]
}
}
- return fmt.Sprintf("tok-%v", c)
+ return __yyfmt__.Sprintf("tok-%v", c)
}
func $$Statname(s int) string {
@@ -3124,7 +3243,7 @@ func $$Statname(s int) string {
return $$Statenames[s]
}
}
- return fmt.Sprintf("state-%v", s)
+ return __yyfmt__.Sprintf("state-%v", s)
}
func $$lex1(lex $$Lexer, lval *$$SymType) int {
@@ -3157,7 +3276,7 @@ out:
c = $$Tok2[1] /* unknown char */
}
if $$Debug >= 3 {
- fmt.Printf("lex %U %s\n", uint(char), $$Tokname(c))
+ __yyfmt__.Printf("lex %U %s\n", uint(char), $$Tokname(c))
}
return c
}
@@ -3184,7 +3303,7 @@ ret1:
$$stack:
/* put a state and value onto the stack */
if $$Debug >= 4 {
- fmt.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
+ __yyfmt__.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
}
$$p++
@@ -3253,8 +3372,8 @@ $$default:
$$lex.Error("syntax error")
Nerrs++
if $$Debug >= 1 {
- fmt.Printf("%s", $$Statname($$state))
- fmt.Printf("saw %s\n", $$Tokname($$char))
+ __yyfmt__.Printf("%s", $$Statname($$state))
+ __yyfmt__.Printf("saw %s\n", $$Tokname($$char))
}
fallthrough
@@ -3273,7 +3392,7 @@ $$default:
/* the current p has no shift on "error", pop stack */
if $$Debug >= 2 {
- fmt.Printf("error recovery pops state %d\n", $$S[$$p].yys)
+ __yyfmt__.Printf("error recovery pops state %d\n", $$S[$$p].yys)
}
$$p--
}
@@ -3282,7 +3401,7 @@ $$default:
case 3: /* no shift yet; clobber input char */
if $$Debug >= 2 {
- fmt.Printf("error recovery discards %s\n", $$Tokname($$char))
+ __yyfmt__.Printf("error recovery discards %s\n", $$Tokname($$char))
}
if $$char == $$EofCode {
goto ret1
@@ -3294,7 +3413,7 @@ $$default:
/* reduction by production $$n */
if $$Debug >= 2 {
- fmt.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
+ __yyfmt__.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
}
$$nt := $$n