summaryrefslogtreecommitdiff
path: root/src/cmd/goyacc
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/goyacc')
-rw-r--r--src/cmd/goyacc/Makefile17
-rw-r--r--src/cmd/goyacc/doc.go46
-rw-r--r--src/cmd/goyacc/goyacc.go3311
-rw-r--r--src/cmd/goyacc/units.txt576
-rw-r--r--src/cmd/goyacc/units.y765
5 files changed, 0 insertions, 4715 deletions
diff --git a/src/cmd/goyacc/Makefile b/src/cmd/goyacc/Makefile
deleted file mode 100644
index ac0f427cc..000000000
--- a/src/cmd/goyacc/Makefile
+++ /dev/null
@@ -1,17 +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.
-
-include ../../Make.inc
-
-TARG=goyacc
-GOFILES=\
- goyacc.go\
-
-include ../../Make.cmd
-
-units: goyacc units.y
- ./goyacc -p units_ units.y
- $(GC) y.go
- $(LD) -o units y.$O
-
diff --git a/src/cmd/goyacc/doc.go b/src/cmd/goyacc/doc.go
deleted file mode 100644
index 5dd6abe69..000000000
--- a/src/cmd/goyacc/doc.go
+++ /dev/null
@@ -1,46 +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.
-
-/*
-
-Goyacc is a version of yacc for Go.
-It is written in Go and generates parsers written in Go.
-
-It is largely transliterated from the Inferno version written in Limbo
-which in turn was largely transliterated from the Plan 9 version
-written in C and documented at
-
- http://plan9.bell-labs.com/magic/man2html/1/yacc
-
-Yacc adepts will have no trouble adapting to this form of the tool.
-
-The file units.y in this directory is a yacc grammar for a version of
-the Unix tool units, also written in Go and largely transliterated
-from the Plan 9 C version. It needs the flag "-p units_" (see
-below).
-
-The generated parser is reentrant. Parse expects to be given an
-argument that conforms to the following interface:
-
- type yyLexer interface {
- Lex(lval *yySymType) int
- Error(e string)
- }
-
-Lex should return the token identifier, and place other token
-information in lval (which replaces the usual yylval).
-Error is equivalent to yyerror in the original yacc.
-
-Code inside the parser may refer to the variable yylex,
-which holds the yyLexer passed to Parse.
-
-Multiple grammars compiled into a single program should be placed in
-distinct packages. If that is impossible, the "-p prefix" flag to
-goyacc sets the prefix, by default yy, that begins the names of
-symbols, including types, the parser, and the lexer, generated and
-referenced by goyacc's generated code. Setting it to distinct values
-allows multiple grammars to be placed in a single package.
-
-*/
-package documentation
diff --git a/src/cmd/goyacc/goyacc.go b/src/cmd/goyacc/goyacc.go
deleted file mode 100644
index 481540188..000000000
--- a/src/cmd/goyacc/goyacc.go
+++ /dev/null
@@ -1,3311 +0,0 @@
-/*
-Derived from Inferno's utils/iyacc/yacc.c
-http://code.google.com/p/inferno-os/source/browse/utils/iyacc/yacc.c
-
-This copyright NOTICE applies to all files in this directory and
-subdirectories, unless another copyright notice appears in a given
-file or subdirectory. If you take substantial code from this software to use in
-other programs, you must somehow include with it an appropriate
-copyright notice that includes the copyright notice and the other
-notices below. It is fine (and often tidier) to do that in a separate
-file such as NOTICE, LICENCE or COPYING.
-
- Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
- Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
- Portions Copyright © 1997-1999 Vita Nuova Limited
- Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
- Portions Copyright © 2004,2006 Bruce Ellis
- Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
- Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
- Portions Copyright © 2009 The Go Authors. All rights reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-package main
-
-// yacc
-// major difference is lack of stem ("y" variable)
-//
-
-import (
- "flag"
- "fmt"
- "bufio"
- "os"
- "strings"
- "bytes"
-)
-
-// the following are adjustable
-// according to memory size
-const (
- ACTSIZE = 30000
- NSTATES = 2000
- TEMPSIZE = 2000
-
- SYMINC = 50 // increase for non-term or term
- RULEINC = 50 // increase for max rule length prodptr[i]
- PRODINC = 100 // increase for productions prodptr
- WSETINC = 50 // increase for working sets wsets
- STATEINC = 200 // increase for states statemem
-
- NAMESIZE = 50
- NTYPES = 63
- ISIZE = 400
-
- PRIVATE = 0xE000 // unicode private use
-
- // relationships which must hold:
- // TEMPSIZE >= NTERMS + NNONTERM + 1;
- // TEMPSIZE >= NSTATES;
- //
-
- NTBASE = 010000
- ERRCODE = 8190
- ACCEPTCODE = 8191
- YYLEXUNK = 3
- TOKSTART = 4 //index of first defined token
-)
-
-// no, left, right, binary assoc.
-const (
- NOASC = iota
- LASC
- RASC
- BASC
-)
-
-// flags for state generation
-const (
- DONE = iota
- MUSTDO
- MUSTLOOKAHEAD
-)
-
-// flags for a rule having an action, and being reduced
-const (
- ACTFLAG = 1 << (iota + 2)
- REDFLAG
-)
-
-// output parser flags
-const yyFlag = -1000
-
-// parse tokens
-const (
- IDENTIFIER = PRIVATE + iota
- MARK
- TERM
- LEFT
- RIGHT
- BINARY
- PREC
- LCURLY
- IDENTCOLON
- NUMBER
- START
- TYPEDEF
- TYPENAME
- UNION
-)
-
-const ENDFILE = 0
-const EMPTY = 1
-const WHOKNOWS = 0
-const OK = 1
-const NOMORE = -1000
-
-// macros for getting associativity and precedence levels
-func ASSOC(i int) int { return i & 3 }
-
-func PLEVEL(i int) int { return (i >> 4) & 077 }
-
-func TYPE(i int) int { return (i >> 10) & 077 }
-
-// macros for setting associativity and precedence levels
-func SETASC(i, j int) int { return i | j }
-
-func SETPLEV(i, j int) int { return i | (j << 4) }
-
-func SETTYPE(i, j int) int { return i | (j << 10) }
-
-// I/O descriptors
-var finput *bufio.Reader // input file
-var stderr *bufio.Writer
-var ftable *bufio.Writer // y.go file
-var fcode = &bytes.Buffer{} // saved code
-var foutput *bufio.Writer // y.output file
-
-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
-var prefix string // name prefix for identifiers, default yy
-
-func init() {
- flag.StringVar(&oflag, "o", "y.go", "parser output")
- flag.StringVar(&prefix, "p", "yy", "name prefix to use in generated code")
- flag.StringVar(&vflag, "v", "y.output", "create parsing tables")
- flag.BoolVar(&lflag, "l", false, "disable line directives")
-}
-
-var stacksize = 200
-
-// communication variables between various I/O routines
-var infile string // input file name
-var numbval int // value of an input number
-var tokname string // input token name, slop for runes and 0
-var tokflag = false
-
-// structure declarations
-type Lkset []int
-
-type Pitem struct {
- prod []int
- off int // offset within the production
- first int // first term or non-term in item
- prodno int // production number for sorting
-}
-
-type Item struct {
- pitem Pitem
- look Lkset
-}
-
-type Symb struct {
- name string
- value int
-}
-
-type Wset struct {
- pitem Pitem
- flag int
- ws Lkset
-}
-
-// storage of types
-var ntypes int // number of types defined
-var typeset [NTYPES]string // pointers to type tags
-
-// token information
-
-var ntokens = 0 // number of tokens
-var tokset []Symb
-var toklev []int // vector with the precedence of the terminals
-
-// nonterminal information
-
-var nnonter = -1 // the number of nonterminals
-var nontrst []Symb
-var start int // start symbol
-
-// state information
-
-var nstate = 0 // number of states
-var pstate = make([]int, NSTATES+2) // index into statemem to the descriptions of the states
-var statemem []Item
-var tystate = make([]int, NSTATES) // contains type information about the states
-var tstates []int // states generated by terminal gotos
-var ntstates []int // states generated by nonterminal gotos
-var mstates = make([]int, NSTATES) // chain of overflows of term/nonterm generation lists
-var lastred int // number of last reduction of a state
-var defact = make([]int, NSTATES) // default actions of states
-
-// lookahead set information
-
-var lkst []Lkset
-var nolook = 0 // flag to turn off lookahead computations
-var tbitset = 0 // size of lookahead sets
-var clset Lkset // temporary storage for lookahead computations
-
-// working set information
-
-var wsets []Wset
-var cwp int
-
-// storage for action table
-
-var amem []int // action table storage
-var memp int // next free action table position
-var indgo = make([]int, NSTATES) // index to the stored goto table
-
-// temporary vector, indexable by states, terms, or ntokens
-
-var temp1 = make([]int, TEMPSIZE) // temporary storage, indexed by terms + ntokens or states
-var lineno = 1 // current input line number
-var fatfl = 1 // if on, error is fatal
-var nerrors = 0 // number of errors
-
-// assigned token type values
-
-var extval = 0
-
-// grammar rule information
-
-var nprod = 1 // number of productions
-var prdptr [][]int // pointers to descriptions of productions
-var levprd []int // precedence levels for the productions
-var rlines []int // line number for this rule
-
-// statistics collection variables
-
-var zzgoent = 0
-var zzgobest = 0
-var zzacent = 0
-var zzexcp = 0
-var zzclose = 0
-var zzrrconf = 0
-var zzsrconf = 0
-var zzstate = 0
-
-// optimizer arrays
-
-var yypgo [][]int
-var optst [][]int
-var ggreed []int
-var pgo []int
-
-var maxspr int // maximum spread of any entry
-var maxoff int // maximum offset into a array
-var maxa int
-
-// storage for information about the nonterminals
-
-var pres [][][]int // vector of pointers to productions yielding each nonterminal
-var pfirst []Lkset
-var pempty []int // vector of nonterminals nontrivially deriving e
-
-// random stuff picked out from between functions
-
-var indebug = 0 // debugging flag for cpfir
-var pidebug = 0 // debugging flag for putitem
-var gsdebug = 0 // debugging flag for stagen
-var cldebug = 0 // debugging flag for closure
-var pkdebug = 0 // debugging flag for apack
-var g2debug = 0 // debugging for go2gen
-var adb = 0 // debugging for callopt
-
-type Resrv struct {
- name string
- value int
-}
-
-var resrv = []Resrv{
- {"binary", BINARY},
- {"left", LEFT},
- {"nonassoc", BINARY},
- {"prec", PREC},
- {"right", RIGHT},
- {"start", START},
- {"term", TERM},
- {"token", TERM},
- {"type", TYPEDEF},
- {"union", UNION},
- {"struct", UNION},
-}
-
-var zznewstate = 0
-
-const EOF = -1
-const UTFmax = 0x3f
-
-func main() {
-
- setup() // initialize and read productions
-
- tbitset = (ntokens + 32) / 32
- cpres() // make table of which productions yield a given nonterminal
- cempty() // make a table of which nonterminals can match the empty string
- cpfir() // make a table of firsts of nonterminals
-
- stagen() // generate the states
-
- yypgo = make([][]int, nnonter+1)
- optst = make([][]int, nstate)
- output() // write the states and the tables
- go2out()
-
- hideprod()
- summary()
-
- callopt()
-
- others()
-
- exit(0)
-}
-
-func setup() {
- var j, ty int
-
- stderr = bufio.NewWriter(os.NewFile(2, "stderr"))
- foutput = nil
-
- flag.Parse()
- if flag.NArg() != 1 {
- usage()
- }
- if stacksize < 1 {
- // never set so cannot happen
- fmt.Fprintf(stderr, "yacc: stack size too small\n")
- usage()
- }
- yaccpar = strings.Replace(yaccpartext, "$$", prefix, -1)
- openup()
-
- defin(0, "$end")
- extval = PRIVATE // tokens start in unicode 'private use'
- defin(0, "error")
- defin(1, "$accept")
- defin(0, "$unk")
- i := 0
-
- t := gettok()
-
-outer:
- for {
- switch t {
- default:
- errorf("syntax error tok=%v", t-PRIVATE)
-
- case MARK, ENDFILE:
- break outer
-
- case ';':
-
- case START:
- t = gettok()
- if t != IDENTIFIER {
- errorf("bad %%start construction")
- }
- start = chfind(1, tokname)
-
- case TYPEDEF:
- t = gettok()
- if t != TYPENAME {
- errorf("bad syntax in %%type")
- }
- ty = numbval
- for {
- t = gettok()
- switch t {
- case IDENTIFIER:
- t = chfind(1, tokname)
- if t < NTBASE {
- j = TYPE(toklev[t])
- if j != 0 && j != ty {
- errorf("type redeclaration of token %s",
- tokset[t].name)
- } else {
- toklev[t] = SETTYPE(toklev[t], ty)
- }
- } else {
- j = nontrst[t-NTBASE].value
- if j != 0 && j != ty {
- errorf("type redeclaration of nonterminal %v",
- nontrst[t-NTBASE].name)
- } else {
- nontrst[t-NTBASE].value = ty
- }
- }
- continue
-
- case ',':
- continue
- }
- break
- }
- continue
-
- case UNION:
- cpyunion()
-
- case LEFT, BINARY, RIGHT, TERM:
- // nonzero means new prec. and assoc.
- lev := t - TERM
- if lev != 0 {
- i++
- }
- ty = 0
-
- // get identifiers so defined
- t = gettok()
-
- // there is a type defined
- if t == TYPENAME {
- ty = numbval
- t = gettok()
- }
- for {
- switch t {
- case ',':
- t = gettok()
- continue
-
- case ';':
- break
-
- case IDENTIFIER:
- j = chfind(0, tokname)
- if j >= NTBASE {
- errorf("%v defined earlier as nonterminal", tokname)
- }
- if lev != 0 {
- if ASSOC(toklev[j]) != 0 {
- errorf("redeclaration of precedence of %v", tokname)
- }
- toklev[j] = SETASC(toklev[j], lev)
- toklev[j] = SETPLEV(toklev[j], i)
- }
- if ty != 0 {
- if TYPE(toklev[j]) != 0 {
- errorf("redeclaration of type of %v", tokname)
- }
- toklev[j] = SETTYPE(toklev[j], ty)
- }
- t = gettok()
- if t == NUMBER {
- tokset[j].value = numbval
- t = gettok()
- }
-
- continue
- }
- break
- }
- continue
-
- case LCURLY:
- cpycode()
- }
- t = gettok()
- }
-
- if t == ENDFILE {
- errorf("unexpected EOF before %%")
- }
-
- // put out non-literal terminals
- for i := TOKSTART; i <= ntokens; i++ {
- // non-literals
- c := tokset[i].name[0]
- if c != ' ' && c != '$' {
- fmt.Fprintf(ftable, "const\t%v\t= %v\n", tokset[i].name, tokset[i].value)
- }
- }
-
- // put out names of token names
- fmt.Fprintf(ftable, "var\t%sToknames\t =[]string {\n", prefix)
- for i := TOKSTART; i <= ntokens; i++ {
- fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name)
- }
- fmt.Fprintf(ftable, "}\n")
-
- // put out names of state names
- fmt.Fprintf(ftable, "var\t%sStatenames\t =[]string {\n", prefix)
- // for i:=TOKSTART; i<=ntokens; i++ {
- // fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name);
- // }
- fmt.Fprintf(ftable, "}\n")
-
- fmt.Fprintf(fcode, "switch %snt {\n", prefix)
-
- moreprod()
- prdptr[0] = []int{NTBASE, start, 1, 0}
-
- nprod = 1
- curprod := make([]int, RULEINC)
- t = gettok()
- if t != IDENTCOLON {
- errorf("bad syntax on first rule")
- }
-
- if start == 0 {
- prdptr[0][1] = chfind(1, tokname)
- }
-
- // read rules
- // put into prdptr array in the format
- // target
- // followed by id's of terminals and non-terminals
- // followd by -nprod
-
- for t != MARK && t != ENDFILE {
- mem := 0
-
- // process a rule
- rlines[nprod] = lineno
- if t == '|' {
- curprod[mem] = prdptr[nprod-1][0]
- mem++
- } else if t == IDENTCOLON {
- curprod[mem] = chfind(1, tokname)
- if curprod[mem] < NTBASE {
- errorf("token illegal on LHS of grammar rule")
- }
- mem++
- } else {
- errorf("illegal rule: missing semicolon or | ?")
- }
-
- // read rule body
- t = gettok()
- for {
- for t == IDENTIFIER {
- curprod[mem] = chfind(1, tokname)
- if curprod[mem] < NTBASE {
- levprd[nprod] = toklev[curprod[mem]]
- }
- mem++
- if mem >= len(curprod) {
- ncurprod := make([]int, mem+RULEINC)
- copy(ncurprod, curprod)
- curprod = ncurprod
- }
- t = gettok()
- }
- if t == PREC {
- if gettok() != IDENTIFIER {
- errorf("illegal %%prec syntax")
- }
- j = chfind(2, tokname)
- if j >= NTBASE {
- errorf("nonterminal " + nontrst[j-NTBASE].name + " illegal after %%prec")
- }
- levprd[nprod] = toklev[j]
- t = gettok()
- }
- if t != '=' {
- break
- }
- levprd[nprod] |= ACTFLAG
- fmt.Fprintf(fcode, "\ncase %v:", nprod)
- cpyact(curprod, mem)
-
- // action within rule...
- t = gettok()
- if t == IDENTIFIER {
- // make it a nonterminal
- j = chfind(1, fmt.Sprintf("$$%v", nprod))
-
- //
- // the current rule will become rule number nprod+1
- // enter null production for action
- //
- prdptr[nprod] = make([]int, 2)
- prdptr[nprod][0] = j
- prdptr[nprod][1] = -nprod
-
- // update the production information
- nprod++
- moreprod()
- levprd[nprod] = levprd[nprod-1] & ^ACTFLAG
- levprd[nprod-1] = ACTFLAG
- rlines[nprod] = lineno
-
- // make the action appear in the original rule
- curprod[mem] = j
- mem++
- if mem >= len(curprod) {
- ncurprod := make([]int, mem+RULEINC)
- copy(ncurprod, curprod)
- curprod = ncurprod
- }
- }
- }
-
- for t == ';' {
- t = gettok()
- }
- curprod[mem] = -nprod
- mem++
-
- // check that default action is reasonable
- if ntypes != 0 && (levprd[nprod]&ACTFLAG) == 0 &&
- nontrst[curprod[0]-NTBASE].value != 0 {
- // no explicit action, LHS has value
- tempty := curprod[1]
- if tempty < 0 {
- errorf("must return a value, since LHS has a type")
- }
- if tempty >= NTBASE {
- tempty = nontrst[tempty-NTBASE].value
- } else {
- tempty = TYPE(toklev[tempty])
- }
- if tempty != nontrst[curprod[0]-NTBASE].value {
- errorf("default action causes potential type clash")
- }
- fmt.Fprintf(fcode, "\ncase %v:", nprod)
- fmt.Fprintf(fcode, "\n\t%sVAL.%v = %sS[%spt-0].%v;",
- prefix, typeset[tempty], prefix, prefix, typeset[tempty])
- }
- moreprod()
- prdptr[nprod] = make([]int, mem)
- copy(prdptr[nprod], curprod)
- nprod++
- moreprod()
- levprd[nprod] = 0
- }
-
- //
- // end of all rules
- // dump out the prefix code
- //
-
- fmt.Fprintf(fcode, "\n\t}")
-
- fmt.Fprintf(ftable, "const %sEofCode = 1\n", prefix)
- fmt.Fprintf(ftable, "const %sErrCode = 2\n", prefix)
- fmt.Fprintf(ftable, "const %sMaxDepth = %v\n", prefix, stacksize)
-
- //
- // copy any postfix code
- //
- if t == MARK {
- if !lflag {
- fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
- }
- for {
- c := getrune(finput)
- if c == EOF {
- break
- }
- ftable.WriteRune(c)
- }
- }
-}
-
-//
-// allocate enough room to hold another production
-//
-func moreprod() {
- n := len(prdptr)
- if nprod >= n {
- nn := n + PRODINC
- aprod := make([][]int, nn)
- alevprd := make([]int, nn)
- arlines := make([]int, nn)
-
- copy(aprod, prdptr)
- copy(alevprd, levprd)
- copy(arlines, rlines)
-
- prdptr = aprod
- levprd = alevprd
- rlines = arlines
- }
-}
-
-//
-// define s to be a terminal if t=0
-// or a nonterminal if t=1
-//
-func defin(nt int, s string) int {
- val := 0
- if nt != 0 {
- nnonter++
- if nnonter >= len(nontrst) {
- anontrst := make([]Symb, nnonter+SYMINC)
- copy(anontrst, nontrst)
- nontrst = anontrst
- }
- nontrst[nnonter] = Symb{s, 0}
- return NTBASE + nnonter
- }
-
- // must be a token
- ntokens++
- if ntokens >= len(tokset) {
- nn := ntokens + SYMINC
- atokset := make([]Symb, nn)
- atoklev := make([]int, nn)
-
- copy(atoklev, toklev)
- copy(atokset, tokset)
-
- tokset = atokset
- toklev = atoklev
- }
- tokset[ntokens].name = s
- toklev[ntokens] = 0
-
- // 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
- default:
- errorf("illegal \\unnnn construction")
- }
- val = val*16 + c
- s = s[1:]
- }
- if val == 0 {
- errorf("'\\u0000' is illegal")
- }
- } else {
- errorf("unknown escape")
- }
- } else {
- val = extval
- extval++
- }
-
- tokset[ntokens].value = val
- return ntokens
-}
-
-var peekline = 0
-
-func gettok() int {
- var i, match, c int
-
- tokname = ""
- for {
- lineno += peekline
- peekline = 0
- c = getrune(finput)
- for c == ' ' || c == '\n' || c == '\t' || c == '\v' || c == '\r' {
- if c == '\n' {
- lineno++
- }
- c = getrune(finput)
- }
-
- // skip comment -- fix
- if c != '/' {
- break
- }
- lineno += skipcom()
- }
-
- switch c {
- case EOF:
- if tokflag {
- fmt.Printf(">>> ENDFILE %v\n", lineno)
- }
- return ENDFILE
-
- case '{':
- ungetrune(finput, c)
- if tokflag {
- fmt.Printf(">>> ={ %v\n", lineno)
- }
- return '='
-
- case '<':
- // get, and look up, a type name (union member name)
- c = getrune(finput)
- for c != '>' && c != EOF && c != '\n' {
- tokname += string(c)
- c = getrune(finput)
- }
-
- if c != '>' {
- errorf("unterminated < ... > clause")
- }
-
- for i = 1; i <= ntypes; i++ {
- if typeset[i] == tokname {
- numbval = i
- if tokflag {
- fmt.Printf(">>> TYPENAME old <%v> %v\n", tokname, lineno)
- }
- return TYPENAME
- }
- }
- ntypes++
- numbval = ntypes
- typeset[numbval] = tokname
- if tokflag {
- fmt.Printf(">>> TYPENAME new <%v> %v\n", tokname, lineno)
- }
- return TYPENAME
-
- case '"', '\'':
- match = c
- tokname = " "
- for {
- c = getrune(finput)
- if c == '\n' || c == EOF {
- errorf("illegal or missing ' or \"")
- }
- if c == '\\' {
- tokname += string('\\')
- c = getrune(finput)
- } else if c == match {
- if tokflag {
- fmt.Printf(">>> IDENTIFIER \"%v\" %v\n", tokname, lineno)
- }
- return IDENTIFIER
- }
- tokname += string(c)
- }
-
- case '%':
- c = getrune(finput)
- switch c {
- case '%':
- if tokflag {
- fmt.Printf(">>> MARK %%%% %v\n", lineno)
- }
- return MARK
- case '=':
- if tokflag {
- fmt.Printf(">>> PREC %%= %v\n", lineno)
- }
- return PREC
- case '{':
- if tokflag {
- fmt.Printf(">>> LCURLY %%{ %v\n", lineno)
- }
- return LCURLY
- }
-
- getword(c)
- // find a reserved word
- for c = 0; c < len(resrv); c++ {
- if tokname == resrv[c].name {
- if tokflag {
- fmt.Printf(">>> %%%v %v %v\n", tokname,
- resrv[c].value-PRIVATE, lineno)
- }
- return resrv[c].value
- }
- }
- errorf("invalid escape, or illegal reserved word: %v", tokname)
-
- case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- numbval = c - '0'
- for {
- c = getrune(finput)
- if !isdigit(c) {
- break
- }
- numbval = numbval*10 + c - '0'
- }
- ungetrune(finput, c)
- if tokflag {
- fmt.Printf(">>> NUMBER %v %v\n", numbval, lineno)
- }
- return NUMBER
-
- default:
- if isword(c) || c == '.' || c == '$' {
- getword(c)
- break
- }
- if tokflag {
- fmt.Printf(">>> OPERATOR %v %v\n", string(c), lineno)
- }
- return c
- }
-
- // look ahead to distinguish IDENTIFIER from IDENTCOLON
- c = getrune(finput)
- for c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\r' || c == '/' {
- if c == '\n' {
- peekline++
- }
- // look for comments
- if c == '/' {
- peekline += skipcom()
- }
- c = getrune(finput)
- }
- if c == ':' {
- if tokflag {
- fmt.Printf(">>> IDENTCOLON %v: %v\n", tokname, lineno)
- }
- return IDENTCOLON
- }
-
- ungetrune(finput, c)
- if tokflag {
- fmt.Printf(">>> IDENTIFIER %v %v\n", tokname, lineno)
- }
- return IDENTIFIER
-}
-
-func getword(c int) {
- tokname = ""
- for isword(c) || isdigit(c) || c == '_' || c == '.' || c == '$' {
- tokname += string(c)
- c = getrune(finput)
- }
- ungetrune(finput, c)
-}
-
-//
-// determine the type of a symbol
-//
-func fdtype(t int) int {
- var v int
- var s string
-
- if t >= NTBASE {
- v = nontrst[t-NTBASE].value
- s = nontrst[t-NTBASE].name
- } else {
- v = TYPE(toklev[t])
- s = tokset[t].name
- }
- if v <= 0 {
- errorf("must specify type for %v", s)
- }
- return v
-}
-
-func chfind(t int, s string) int {
- if s[0] == ' ' {
- t = 0
- }
- for i := 0; i <= ntokens; i++ {
- if s == tokset[i].name {
- return i
- }
- }
- for i := 0; i <= nnonter; i++ {
- if s == nontrst[i].name {
- return NTBASE + i
- }
- }
-
- // cannot find name
- if t > 1 {
- errorf("%v should have been defined earlier", s)
- }
- return defin(t, s)
-}
-
-//
-// copy the union declaration to the output, and the define file if present
-//
-func cpyunion() {
-
- if !lflag {
- fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
- }
- fmt.Fprintf(ftable, "type\t%sSymType\tstruct", prefix)
-
- level := 0
-
-out:
- for {
- c := getrune(finput)
- if c == EOF {
- errorf("EOF encountered while processing %%union")
- }
- ftable.WriteRune(c)
- switch c {
- case '\n':
- lineno++
- case '{':
- if level == 0 {
- fmt.Fprintf(ftable, "\n\tyys\tint;")
- }
- level++
- case '}':
- level--
- if level == 0 {
- break out
- }
- }
- }
- fmt.Fprintf(ftable, "\n")
-}
-
-//
-// saves code between %{ and %}
-//
-func cpycode() {
- lno := lineno
-
- c := getrune(finput)
- if c == '\n' {
- c = getrune(finput)
- lineno++
- }
- if !lflag {
- fmt.Fprintf(ftable, "\n//line %v:%v\n", infile, lineno)
- }
- for c != EOF {
- if c == '%' {
- c = getrune(finput)
- if c == '}' {
- return
- }
- ftable.WriteRune('%')
- }
- ftable.WriteRune(c)
- if c == '\n' {
- lineno++
- }
- c = getrune(finput)
- }
- lineno = lno
- errorf("eof before %%}")
-}
-
-//
-// skip over comments
-// skipcom is called after reading a '/'
-//
-func skipcom() int {
- var c int
-
- c = getrune(finput)
- if c == '/' {
- for c != EOF {
- if c == '\n' {
- return 1
- }
- c = getrune(finput)
- }
- errorf("EOF inside comment")
- return 0
- }
- if c != '*' {
- errorf("illegal comment")
- }
-
- nl := 0 // lines skipped
- c = getrune(finput)
-
-l1:
- switch c {
- case '*':
- c = getrune(finput)
- if c == '/' {
- break
- }
- goto l1
-
- case '\n':
- nl++
- fallthrough
-
- default:
- c = getrune(finput)
- goto l1
- }
- return nl
-}
-
-func dumpprod(curprod []int, max int) {
- fmt.Printf("\n")
- for i := 0; i < max; i++ {
- p := curprod[i]
- if p < 0 {
- fmt.Printf("[%v] %v\n", i, p)
- } else {
- fmt.Printf("[%v] %v\n", i, symnam(p))
- }
- }
-}
-
-//
-// copy action to the next ; or closing }
-//
-func cpyact(curprod []int, max int) {
-
- if !lflag {
- fmt.Fprintf(fcode, "\n//line %v:%v\n", infile, lineno)
- }
-
- lno := lineno
- brac := 0
-
-loop:
- for {
- c := getrune(finput)
-
- swt:
- switch c {
- case ';':
- if brac == 0 {
- ftable.WriteRune(c)
- return
- }
-
- case '{':
- if brac == 0 {
- }
- ftable.WriteRune('\t')
- brac++
-
- case '$':
- s := 1
- tok := -1
- c = getrune(finput)
-
- // type description
- if c == '<' {
- ungetrune(finput, c)
- if gettok() != TYPENAME {
- errorf("bad syntax on $<ident> clause")
- }
- tok = numbval
- c = getrune(finput)
- }
- if c == '$' {
- fmt.Fprintf(fcode, "%sVAL", prefix)
-
- // put out the proper tag...
- if ntypes != 0 {
- if tok < 0 {
- tok = fdtype(curprod[0])
- }
- fmt.Fprintf(fcode, ".%v", typeset[tok])
- }
- continue loop
- }
- if c == '-' {
- s = -s
- c = getrune(finput)
- }
- j := 0
- if isdigit(c) {
- for isdigit(c) {
- j = j*10 + c - '0'
- c = getrune(finput)
- }
- ungetrune(finput, c)
- j = j * s
- if j >= max {
- errorf("Illegal use of $%v", j)
- }
- } else if isword(c) || c == '_' || c == '.' {
- // look for $name
- ungetrune(finput, c)
- if gettok() != IDENTIFIER {
- errorf("$ must be followed by an identifier")
- }
- tokn := chfind(2, tokname)
- fnd := -1
- c = getrune(finput)
- if c != '@' {
- ungetrune(finput, c)
- } else if gettok() != NUMBER {
- errorf("@ must be followed by number")
- } else {
- fnd = numbval
- }
- for j = 1; j < max; j++ {
- if tokn == curprod[j] {
- fnd--
- if fnd <= 0 {
- break
- }
- }
- }
- if j >= max {
- errorf("$name or $name@number not found")
- }
- } else {
- fcode.WriteRune('$')
- if s < 0 {
- fcode.WriteRune('-')
- }
- ungetrune(finput, c)
- continue loop
- }
- fmt.Fprintf(fcode, "%sS[%spt-%v]", prefix, prefix, max-j-1)
-
- // put out the proper tag
- if ntypes != 0 {
- if j <= 0 && tok < 0 {
- errorf("must specify type of $%v", j)
- }
- if tok < 0 {
- tok = fdtype(curprod[j])
- }
- fmt.Fprintf(fcode, ".%v", typeset[tok])
- }
- continue loop
-
- case '}':
- brac--
- if brac != 0 {
- break
- }
- fcode.WriteRune(c)
- return
-
- case '/':
- nc := getrune(finput)
- if nc != '/' && nc != '*' {
- ungetrune(finput, nc)
- break
- }
- // a comment
- fcode.WriteRune(c)
- fcode.WriteRune(nc)
- c = getrune(finput)
- for c != EOF {
- switch {
- case c == '\n':
- lineno++
- if nc == '/' { // end of // comment
- break swt
- }
- case c == '*' && nc == '*': // end of /* comment?
- nnc := getrune(finput)
- if nnc == '/' {
- fcode.WriteRune('*')
- fcode.WriteRune('/')
- c = getrune(finput)
- break swt
- }
- ungetrune(finput, nnc)
- }
- fcode.WriteRune(c)
- c = getrune(finput)
- }
- errorf("EOF inside comment")
-
- case '\'', '"':
- // character string or constant
- match := c
- fcode.WriteRune(c)
- c = getrune(finput)
- for c != EOF {
- if c == '\\' {
- fcode.WriteRune(c)
- c = getrune(finput)
- if c == '\n' {
- lineno++
- }
- } else if c == match {
- break swt
- }
- if c == '\n' {
- errorf("newline in string or char const")
- }
- fcode.WriteRune(c)
- c = getrune(finput)
- }
- errorf("EOF in string or character constant")
-
- case EOF:
- lineno = lno
- errorf("action does not terminate")
-
- case '\n':
- lineno++
- }
-
- fcode.WriteRune(c)
- }
-}
-
-func openup() {
- infile = flag.Arg(0)
- finput = open(infile)
- if finput == nil {
- errorf("cannot open %v", infile)
- }
-
- foutput = nil
- if vflag != "" {
- foutput = create(vflag)
- if foutput == nil {
- errorf("can't create file %v", vflag)
- }
- }
-
- ftable = nil
- if oflag == "" {
- oflag = "y.go"
- }
- ftable = create(oflag)
- if ftable == nil {
- errorf("can't create file %v", oflag)
- }
-
-}
-
-//
-// return a pointer to the name of symbol i
-//
-func symnam(i int) string {
- var s string
-
- if i >= NTBASE {
- s = nontrst[i-NTBASE].name
- } else {
- s = tokset[i].name
- }
- if s[0] == ' ' {
- s = s[1:]
- }
- return s
-}
-
-//
-// set elements 0 through n-1 to c
-//
-func aryfil(v []int, n, c int) {
- for i := 0; i < n; i++ {
- v[i] = c
- }
-}
-
-//
-// compute an array with the beginnings of productions yielding given nonterminals
-// The array pres points to these lists
-// the array pyield has the lists: the total size is only NPROD+1
-//
-func cpres() {
- pres = make([][][]int, nnonter+1)
- curres := make([][]int, nprod)
-
- if false {
- for j := 0; j <= nnonter; j++ {
- fmt.Printf("nnonter[%v] = %v\n", j, nontrst[j].name)
- }
- for j := 0; j < nprod; j++ {
- fmt.Printf("prdptr[%v][0] = %v+NTBASE\n", j, prdptr[j][0]-NTBASE)
- }
- }
-
- fatfl = 0 // make undefined symbols nonfatal
- for i := 0; i <= nnonter; i++ {
- n := 0
- c := i + NTBASE
- for j := 0; j < nprod; j++ {
- if prdptr[j][0] == c {
- curres[n] = prdptr[j][1:]
- n++
- }
- }
- if n == 0 {
- errorf("nonterminal %v not defined", nontrst[i].name)
- continue
- }
- pres[i] = make([][]int, n)
- copy(pres[i], curres)
- }
- fatfl = 1
- if nerrors != 0 {
- summary()
- exit(1)
- }
-}
-
-func dumppres() {
- for i := 0; i <= nnonter; i++ {
- fmt.Printf("nonterm %d\n", i)
- curres := pres[i]
- for j := 0; j < len(curres); j++ {
- fmt.Printf("\tproduction %d:", j)
- prd := curres[j]
- for k := 0; k < len(prd); k++ {
- fmt.Printf(" %d", prd[k])
- }
- fmt.Print("\n")
- }
- }
-}
-
-//
-// mark nonterminals which derive the empty string
-// also, look for nonterminals which don't derive any token strings
-//
-func cempty() {
- var i, p, np int
- var prd []int
-
- pempty = make([]int, nnonter+1)
-
- // first, use the array pempty to detect productions that can never be reduced
- // set pempty to WHONOWS
- aryfil(pempty, nnonter+1, WHOKNOWS)
-
- // now, look at productions, marking nonterminals which derive something
-more:
- for {
- for i = 0; i < nprod; i++ {
- prd = prdptr[i]
- if pempty[prd[0]-NTBASE] != 0 {
- continue
- }
- np = len(prd) - 1
- for p = 1; p < np; p++ {
- if prd[p] >= NTBASE && pempty[prd[p]-NTBASE] == WHOKNOWS {
- break
- }
- }
- // production can be derived
- if p == np {
- pempty[prd[0]-NTBASE] = OK
- continue more
- }
- }
- break
- }
-
- // now, look at the nonterminals, to see if they are all OK
- for i = 0; i <= nnonter; i++ {
- // the added production rises or falls as the start symbol ...
- if i == 0 {
- continue
- }
- if pempty[i] != OK {
- fatfl = 0
- errorf("nonterminal " + nontrst[i].name + " never derives any token string")
- }
- }
-
- if nerrors != 0 {
- summary()
- exit(1)
- }
-
- // now, compute the pempty array, to see which nonterminals derive the empty string
- // set pempty to WHOKNOWS
- aryfil(pempty, nnonter+1, WHOKNOWS)
-
- // loop as long as we keep finding empty nonterminals
-
-again:
- for {
- next:
- for i = 1; i < nprod; i++ {
- // not known to be empty
- prd = prdptr[i]
- if pempty[prd[0]-NTBASE] != WHOKNOWS {
- continue
- }
- np = len(prd) - 1
- for p = 1; p < np; p++ {
- if prd[p] < NTBASE || pempty[prd[p]-NTBASE] != EMPTY {
- continue next
- }
- }
-
- // we have a nontrivially empty nonterminal
- pempty[prd[0]-NTBASE] = EMPTY
-
- // got one ... try for another
- continue again
- }
- return
- }
-}
-
-func dumpempty() {
- for i := 0; i <= nnonter; i++ {
- if pempty[i] == EMPTY {
- fmt.Printf("non-term %d %s matches empty\n", i, symnam(i+NTBASE))
- }
- }
-}
-
-//
-// compute an array with the first of nonterminals
-//
-func cpfir() {
- var s, n, p, np, ch, i int
- var curres [][]int
- var prd []int
-
- wsets = make([]Wset, nnonter+WSETINC)
- pfirst = make([]Lkset, nnonter+1)
- for i = 0; i <= nnonter; i++ {
- wsets[i].ws = mkset()
- pfirst[i] = mkset()
- curres = pres[i]
- n = len(curres)
-
- // initially fill the sets
- for s = 0; s < n; s++ {
- prd = curres[s]
- np = len(prd) - 1
- for p = 0; p < np; p++ {
- ch = prd[p]
- if ch < NTBASE {
- setbit(pfirst[i], ch)
- break
- }
- if pempty[ch-NTBASE] == 0 {
- break
- }
- }
- }
- }
-
- // now, reflect transitivity
- changes := 1
- for changes != 0 {
- changes = 0
- for i = 0; i <= nnonter; i++ {
- curres = pres[i]
- n = len(curres)
- for s = 0; s < n; s++ {
- prd = curres[s]
- np = len(prd) - 1
- for p = 0; p < np; p++ {
- ch = prd[p] - NTBASE
- if ch < 0 {
- break
- }
- changes |= setunion(pfirst[i], pfirst[ch])
- if pempty[ch] == 0 {
- break
- }
- }
- }
- }
- }
-
- if indebug == 0 {
- return
- }
- if foutput != nil {
- for i = 0; i <= nnonter; i++ {
- fmt.Fprintf(foutput, "\n%v: %v %v\n",
- nontrst[i].name, pfirst[i], pempty[i])
- }
- }
-}
-
-//
-// generate the states
-//
-func stagen() {
- // initialize
- nstate = 0
- tstates = make([]int, ntokens+1) // states generated by terminal gotos
- ntstates = make([]int, nnonter+1) // states generated by nonterminal gotos
- amem = make([]int, ACTSIZE)
- memp = 0
-
- clset = mkset()
- pstate[0] = 0
- pstate[1] = 0
- aryfil(clset, tbitset, 0)
- putitem(Pitem{prdptr[0], 0, 0, 0}, clset)
- tystate[0] = MUSTDO
- nstate = 1
- pstate[2] = pstate[1]
-
- //
- // now, the main state generation loop
- // first pass generates all of the states
- // later passes fix up lookahead
- // could be sped up a lot by remembering
- // results of the first pass rather than recomputing
- //
- first := 1
- for more := 1; more != 0; first = 0 {
- more = 0
- for i := 0; i < nstate; i++ {
- if tystate[i] != MUSTDO {
- continue
- }
-
- tystate[i] = DONE
- aryfil(temp1, nnonter+1, 0)
-
- // take state i, close it, and do gotos
- closure(i)
-
- // generate goto's
- for p := 0; p < cwp; p++ {
- pi := wsets[p]
- if pi.flag != 0 {
- continue
- }
- wsets[p].flag = 1
- c := pi.pitem.first
- if c <= 1 {
- if pstate[i+1]-pstate[i] <= p {
- tystate[i] = MUSTLOOKAHEAD
- }
- continue
- }
-
- // do a goto on c
- putitem(wsets[p].pitem, wsets[p].ws)
- for q := p + 1; q < cwp; q++ {
- // this item contributes to the goto
- if c == wsets[q].pitem.first {
- putitem(wsets[q].pitem, wsets[q].ws)
- wsets[q].flag = 1
- }
- }
-
- if c < NTBASE {
- state(c) // register new state
- } else {
- temp1[c-NTBASE] = state(c)
- }
- }
-
- if gsdebug != 0 && foutput != nil {
- fmt.Fprintf(foutput, "%v: ", i)
- for j := 0; j <= nnonter; j++ {
- if temp1[j] != 0 {
- fmt.Fprintf(foutput, "%v %v,", nontrst[j].name, temp1[j])
- }
- }
- fmt.Fprintf(foutput, "\n")
- }
-
- if first != 0 {
- indgo[i] = apack(temp1[1:], nnonter-1) - 1
- }
-
- more++
- }
- }
-}
-
-//
-// generate the closure of state i
-//
-func closure(i int) {
- zzclose++
-
- // first, copy kernel of state i to wsets
- cwp = 0
- q := pstate[i+1]
- for p := pstate[i]; p < q; p++ {
- wsets[cwp].pitem = statemem[p].pitem
- wsets[cwp].flag = 1 // this item must get closed
- copy(wsets[cwp].ws, statemem[p].look)
- cwp++
- }
-
- // now, go through the loop, closing each item
- work := 1
- for work != 0 {
- work = 0
- for u := 0; u < cwp; u++ {
- if wsets[u].flag == 0 {
- continue
- }
-
- // dot is before c
- c := wsets[u].pitem.first
- if c < NTBASE {
- wsets[u].flag = 0
- // only interesting case is where . is before nonterminal
- continue
- }
-
- // compute the lookahead
- aryfil(clset, tbitset, 0)
-
- // find items involving c
- for v := u; v < cwp; v++ {
- if wsets[v].flag != 1 || wsets[v].pitem.first != c {
- continue
- }
- pi := wsets[v].pitem.prod
- ipi := wsets[v].pitem.off + 1
-
- wsets[v].flag = 0
- if nolook != 0 {
- continue
- }
-
- ch := pi[ipi]
- ipi++
- for ch > 0 {
- // terminal symbol
- if ch < NTBASE {
- setbit(clset, ch)
- break
- }
-
- // nonterminal symbol
- setunion(clset, pfirst[ch-NTBASE])
- if pempty[ch-NTBASE] == 0 {
- break
- }
- ch = pi[ipi]
- ipi++
- }
- if ch <= 0 {
- setunion(clset, wsets[v].ws)
- }
- }
-
- //
- // now loop over productions derived from c
- //
- curres := pres[c-NTBASE]
- n := len(curres)
-
- nexts:
- // initially fill the sets
- for s := 0; s < n; s++ {
- prd := curres[s]
-
- //
- // put these items into the closure
- // is the item there
- //
- for v := 0; v < cwp; v++ {
- // yes, it is there
- if wsets[v].pitem.off == 0 &&
- aryeq(wsets[v].pitem.prod, prd) != 0 {
- if nolook == 0 &&
- setunion(wsets[v].ws, clset) != 0 {
- wsets[v].flag = 1
- work = 1
- }
- continue nexts
- }
- }
-
- // not there; make a new entry
- if cwp >= len(wsets) {
- awsets := make([]Wset, cwp+WSETINC)
- copy(awsets, wsets)
- wsets = awsets
- }
- wsets[cwp].pitem = Pitem{prd, 0, prd[0], -prd[len(prd)-1]}
- wsets[cwp].flag = 1
- wsets[cwp].ws = mkset()
- if nolook == 0 {
- work = 1
- copy(wsets[cwp].ws, clset)
- }
- cwp++
- }
- }
- }
-
- // have computed closure; flags are reset; return
- if cldebug != 0 && foutput != nil {
- fmt.Fprintf(foutput, "\nState %v, nolook = %v\n", i, nolook)
- for u := 0; u < cwp; u++ {
- if wsets[u].flag != 0 {
- fmt.Fprintf(foutput, "flag set\n")
- }
- wsets[u].flag = 0
- fmt.Fprintf(foutput, "\t%v", writem(wsets[u].pitem))
- prlook(wsets[u].ws)
- fmt.Fprintf(foutput, "\n")
- }
- }
-}
-
-//
-// sorts last state,and sees if it equals earlier ones. returns state number
-//
-func state(c int) int {
- zzstate++
- p1 := pstate[nstate]
- p2 := pstate[nstate+1]
- if p1 == p2 {
- return 0 // null state
- }
-
- // sort the items
- var k, l int
- for k = p1 + 1; k < p2; k++ { // make k the biggest
- for l = k; l > p1; l-- {
- if statemem[l].pitem.prodno < statemem[l-1].pitem.prodno ||
- statemem[l].pitem.prodno == statemem[l-1].pitem.prodno &&
- statemem[l].pitem.off < statemem[l-1].pitem.off {
- s := statemem[l]
- statemem[l] = statemem[l-1]
- statemem[l-1] = s
- } else {
- break
- }
- }
- }
-
- size1 := p2 - p1 // size of state
-
- var i int
- if c >= NTBASE {
- i = ntstates[c-NTBASE]
- } else {
- i = tstates[c]
- }
-
-look:
- for ; i != 0; i = mstates[i] {
- // get ith state
- q1 := pstate[i]
- q2 := pstate[i+1]
- size2 := q2 - q1
- if size1 != size2 {
- continue
- }
- k = p1
- for l = q1; l < q2; l++ {
- if aryeq(statemem[l].pitem.prod, statemem[k].pitem.prod) == 0 ||
- statemem[l].pitem.off != statemem[k].pitem.off {
- continue look
- }
- k++
- }
-
- // found it
- pstate[nstate+1] = pstate[nstate] // delete last state
-
- // fix up lookaheads
- if nolook != 0 {
- return i
- }
- k = p1
- for l = q1; l < q2; l++ {
- if setunion(statemem[l].look, statemem[k].look) != 0 {
- tystate[i] = MUSTDO
- }
- k++
- }
- return i
- }
-
- // state is new
- zznewstate++
- if nolook != 0 {
- errorf("yacc state/nolook error")
- }
- pstate[nstate+2] = p2
- if nstate+1 >= NSTATES {
- errorf("too many states")
- }
- if c >= NTBASE {
- mstates[nstate] = ntstates[c-NTBASE]
- ntstates[c-NTBASE] = nstate
- } else {
- mstates[nstate] = tstates[c]
- tstates[c] = nstate
- }
- tystate[nstate] = MUSTDO
- nstate++
- return nstate - 1
-}
-
-func putitem(p Pitem, set Lkset) {
- p.off++
- p.first = p.prod[p.off]
-
- if pidebug != 0 && foutput != nil {
- fmt.Fprintf(foutput, "putitem(%v), state %v\n", writem(p), nstate)
- }
- j := pstate[nstate+1]
- if j >= len(statemem) {
- asm := make([]Item, j+STATEINC)
- copy(asm, statemem)
- statemem = asm
- }
- statemem[j].pitem = p
- if nolook == 0 {
- s := mkset()
- copy(s, set)
- statemem[j].look = s
- }
- j++
- pstate[nstate+1] = j
-}
-
-//
-// creates output string for item pointed to by pp
-//
-func writem(pp Pitem) string {
- var i int
-
- p := pp.prod
- q := chcopy(nontrst[prdptr[pp.prodno][0]-NTBASE].name) + ": "
- npi := pp.off
-
- pi := aryeq(p, prdptr[pp.prodno])
-
- for {
- c := ' '
- if pi == npi {
- c = '.'
- }
- q += string(c)
-
- i = p[pi]
- pi++
- if i <= 0 {
- break
- }
- q += chcopy(symnam(i))
- }
-
- // an item calling for a reduction
- i = p[npi]
- if i < 0 {
- q += fmt.Sprintf(" (%v)", -i)
- }
-
- return q
-}
-
-//
-// pack state i from temp1 into amem
-//
-func apack(p []int, n int) int {
- //
- // we don't need to worry about checking because
- // we will only look at entries known to be there...
- // eliminate leading and trailing 0's
- //
- off := 0
- pp := 0
- for ; pp <= n && p[pp] == 0; pp++ {
- off--
- }
-
- // no actions
- if pp > n {
- return 0
- }
- for ; n > pp && p[n] == 0; n-- {
- }
- p = p[pp : n+1]
-
- // now, find a place for the elements from p to q, inclusive
- r := len(amem) - len(p)
-
-nextk:
- for rr := 0; rr <= r; rr++ {
- qq := rr
- for pp = 0; pp < len(p); pp++ {
- if p[pp] != 0 {
- if p[pp] != amem[qq] && amem[qq] != 0 {
- continue nextk
- }
- }
- qq++
- }
-
- // we have found an acceptable k
- if pkdebug != 0 && foutput != nil {
- fmt.Fprintf(foutput, "off = %v, k = %v\n", off+rr, rr)
- }
- qq = rr
- for pp = 0; pp < len(p); pp++ {
- if p[pp] != 0 {
- if qq > memp {
- memp = qq
- }
- amem[qq] = p[pp]
- }
- qq++
- }
- if pkdebug != 0 && foutput != nil {
- for pp = 0; pp <= memp; pp += 10 {
- fmt.Fprintf(foutput, "\n")
- for qq = pp; qq <= pp+9; qq++ {
- fmt.Fprintf(foutput, "%v ", amem[qq])
- }
- fmt.Fprintf(foutput, "\n")
- }
- }
- return off + rr
- }
- errorf("no space in action table")
- return 0
-}
-
-//
-// print the output for the states
-//
-func output() {
- var c, u, v int
-
- fmt.Fprintf(ftable, "\n//line yacctab:1\n")
- fmt.Fprintf(ftable, "var\t%sExca = []int {\n", prefix)
-
- noset := mkset()
-
- // output the stuff for state i
- for i := 0; i < nstate; i++ {
- nolook = 0
- if tystate[i] != MUSTLOOKAHEAD {
- nolook = 1
- }
- closure(i)
-
- // output actions
- nolook = 1
- aryfil(temp1, ntokens+nnonter+1, 0)
- for u = 0; u < cwp; u++ {
- c = wsets[u].pitem.first
- if c > 1 && c < NTBASE && temp1[c] == 0 {
- for v = u; v < cwp; v++ {
- if c == wsets[v].pitem.first {
- putitem(wsets[v].pitem, noset)
- }
- }
- temp1[c] = state(c)
- } else if c > NTBASE {
- c -= NTBASE
- if temp1[c+ntokens] == 0 {
- temp1[c+ntokens] = amem[indgo[i]+c]
- }
- }
- }
- if i == 1 {
- temp1[1] = ACCEPTCODE
- }
-
- // now, we have the shifts; look at the reductions
- lastred = 0
- for u = 0; u < cwp; u++ {
- c = wsets[u].pitem.first
-
- // reduction
- if c > 0 {
- continue
- }
- lastred = -c
- us := wsets[u].ws
- for k := 0; k <= ntokens; k++ {
- if bitset(us, k) == 0 {
- continue
- }
- if temp1[k] == 0 {
- temp1[k] = c
- } else if temp1[k] < 0 { // reduce/reduce conflict
- if foutput != nil {
- fmt.Fprintf(foutput,
- "\n %v: reduce/reduce conflict (red'ns "+
- "%v and %v) on %v",
- i, -temp1[k], lastred, symnam(k))
- }
- if -temp1[k] > lastred {
- temp1[k] = -lastred
- }
- zzrrconf++
- } else {
- // potential shift/reduce conflict
- precftn(lastred, k, i)
- }
- }
- }
- wract(i)
- }
-
- fmt.Fprintf(ftable, "}\n")
- fmt.Fprintf(ftable, "const\t%sNprod\t= %v\n", prefix, nprod)
- fmt.Fprintf(ftable, "const\t%sPrivate\t= %v\n", prefix, PRIVATE)
- fmt.Fprintf(ftable, "var\t%sTokenNames []string\n", prefix)
- fmt.Fprintf(ftable, "var\t%sStates []string\n", prefix)
-}
-
-//
-// decide a shift/reduce conflict by precedence.
-// r is a rule number, t a token number
-// the conflict is in state s
-// temp1[t] is changed to reflect the action
-//
-func precftn(r, t, s int) {
- var action int
-
- lp := levprd[r]
- lt := toklev[t]
- if PLEVEL(lt) == 0 || PLEVEL(lp) == 0 {
- // conflict
- if foutput != nil {
- fmt.Fprintf(foutput,
- "\n%v: shift/reduce conflict (shift %v(%v), red'n %v(%v)) on %v",
- s, temp1[t], PLEVEL(lt), r, PLEVEL(lp), symnam(t))
- }
- zzsrconf++
- return
- }
- if PLEVEL(lt) == PLEVEL(lp) {
- action = ASSOC(lt)
- } else if PLEVEL(lt) > PLEVEL(lp) {
- action = RASC // shift
- } else {
- action = LASC
- } // reduce
- switch action {
- case BASC: // error action
- temp1[t] = ERRCODE
- case LASC: // reduce
- temp1[t] = -r
- }
-}
-
-//
-// output state i
-// temp1 has the actions, lastred the default
-//
-func wract(i int) {
- var p, p1 int
-
- // find the best choice for lastred
- lastred = 0
- ntimes := 0
- for j := 0; j <= ntokens; j++ {
- if temp1[j] >= 0 {
- continue
- }
- if temp1[j]+lastred == 0 {
- continue
- }
- // count the number of appearances of temp1[j]
- count := 0
- tred := -temp1[j]
- levprd[tred] |= REDFLAG
- for p = 0; p <= ntokens; p++ {
- if temp1[p]+tred == 0 {
- count++
- }
- }
- if count > ntimes {
- lastred = tred
- ntimes = count
- }
- }
-
- //
- // for error recovery, arrange that, if there is a shift on the
- // error recovery token, `error', that the default be the error action
- //
- if temp1[2] > 0 {
- lastred = 0
- }
-
- // clear out entries in temp1 which equal lastred
- // count entries in optst table
- n := 0
- for p = 0; p <= ntokens; p++ {
- p1 = temp1[p]
- if p1+lastred == 0 {
- temp1[p] = 0
- p1 = 0
- }
- if p1 > 0 && p1 != ACCEPTCODE && p1 != ERRCODE {
- n++
- }
- }
-
- wrstate(i)
- defact[i] = lastred
- flag := 0
- os := make([]int, n*2)
- n = 0
- for p = 0; p <= ntokens; p++ {
- p1 = temp1[p]
- if p1 != 0 {
- if p1 < 0 {
- p1 = -p1
- } else if p1 == ACCEPTCODE {
- p1 = -1
- } else if p1 == ERRCODE {
- p1 = 0
- } else {
- os[n] = p
- n++
- os[n] = p1
- n++
- zzacent++
- continue
- }
- if flag == 0 {
- fmt.Fprintf(ftable, "-1, %v,\n", i)
- }
- flag++
- fmt.Fprintf(ftable, "\t%v, %v,\n", p, p1)
- zzexcp++
- }
- }
- if flag != 0 {
- defact[i] = -2
- fmt.Fprintf(ftable, "\t-2, %v,\n", lastred)
- }
- optst[i] = os
-}
-
-//
-// writes state i
-//
-func wrstate(i int) {
- var j0, j1, u int
- var pp, qq int
-
- if foutput == nil {
- return
- }
- fmt.Fprintf(foutput, "\nstate %v\n", i)
- qq = pstate[i+1]
- for pp = pstate[i]; pp < qq; pp++ {
- fmt.Fprintf(foutput, "\t%v\n", writem(statemem[pp].pitem))
- }
- if tystate[i] == MUSTLOOKAHEAD {
- // print out empty productions in closure
- for u = pstate[i+1] - pstate[i]; u < cwp; u++ {
- if wsets[u].pitem.first < 0 {
- fmt.Fprintf(foutput, "\t%v\n", writem(wsets[u].pitem))
- }
- }
- }
-
- // check for state equal to another
- for j0 = 0; j0 <= ntokens; j0++ {
- j1 = temp1[j0]
- if j1 != 0 {
- fmt.Fprintf(foutput, "\n\t%v ", symnam(j0))
-
- // shift, error, or accept
- if j1 > 0 {
- if j1 == ACCEPTCODE {
- fmt.Fprintf(foutput, "accept")
- } else if j1 == ERRCODE {
- fmt.Fprintf(foutput, "error")
- } else {
- fmt.Fprintf(foutput, "shift %v", j1)
- }
- } else {
- fmt.Fprintf(foutput, "reduce %v (src line %v)", -j1, rlines[-j1])
- }
- }
- }
-
- // output the final production
- if lastred != 0 {
- fmt.Fprintf(foutput, "\n\t. reduce %v (src line %v)\n\n",
- lastred, rlines[lastred])
- } else {
- fmt.Fprintf(foutput, "\n\t. error\n\n")
- }
-
- // now, output nonterminal actions
- j1 = ntokens
- for j0 = 1; j0 <= nnonter; j0++ {
- j1++
- if temp1[j1] != 0 {
- fmt.Fprintf(foutput, "\t%v goto %v\n", symnam(j0+NTBASE), temp1[j1])
- }
- }
-}
-
-//
-// output the gotos for the nontermninals
-//
-func go2out() {
- for i := 1; i <= nnonter; i++ {
- go2gen(i)
-
- // find the best one to make default
- best := -1
- times := 0
-
- // is j the most frequent
- for j := 0; j < nstate; j++ {
- if tystate[j] == 0 {
- continue
- }
- if tystate[j] == best {
- continue
- }
-
- // is tystate[j] the most frequent
- count := 0
- cbest := tystate[j]
- for k := j; k < nstate; k++ {
- if tystate[k] == cbest {
- count++
- }
- }
- if count > times {
- best = cbest
- times = count
- }
- }
-
- // best is now the default entry
- zzgobest += times - 1
- n := 0
- for j := 0; j < nstate; j++ {
- if tystate[j] != 0 && tystate[j] != best {
- n++
- }
- }
- goent := make([]int, 2*n+1)
- n = 0
- for j := 0; j < nstate; j++ {
- if tystate[j] != 0 && tystate[j] != best {
- goent[n] = j
- n++
- goent[n] = tystate[j]
- n++
- zzgoent++
- }
- }
-
- // now, the default
- if best == -1 {
- best = 0
- }
-
- zzgoent++
- goent[n] = best
- yypgo[i] = goent
- }
-}
-
-//
-// output the gotos for nonterminal c
-//
-func go2gen(c int) {
- var i, cc, p, q int
-
- // first, find nonterminals with gotos on c
- aryfil(temp1, nnonter+1, 0)
- temp1[c] = 1
- work := 1
- for work != 0 {
- work = 0
- for i = 0; i < nprod; i++ {
- // cc is a nonterminal with a goto on c
- cc = prdptr[i][1] - NTBASE
- if cc >= 0 && temp1[cc] != 0 {
- // thus, the left side of production i does too
- cc = prdptr[i][0] - NTBASE
- if temp1[cc] == 0 {
- work = 1
- temp1[cc] = 1
- }
- }
- }
- }
-
- // now, we have temp1[c] = 1 if a goto on c in closure of cc
- if g2debug != 0 && foutput != nil {
- fmt.Fprintf(foutput, "%v: gotos on ", nontrst[c].name)
- for i = 0; i <= nnonter; i++ {
- if temp1[i] != 0 {
- fmt.Fprintf(foutput, "%v ", nontrst[i].name)
- }
- }
- fmt.Fprintf(foutput, "\n")
- }
-
- // now, go through and put gotos into tystate
- aryfil(tystate, nstate, 0)
- for i = 0; i < nstate; i++ {
- q = pstate[i+1]
- for p = pstate[i]; p < q; p++ {
- cc = statemem[p].pitem.first
- if cc >= NTBASE {
- // goto on c is possible
- if temp1[cc-NTBASE] != 0 {
- tystate[i] = amem[indgo[i]+c]
- break
- }
- }
- }
- }
-}
-
-//
-// in order to free up the mem and amem arrays for the optimizer,
-// and still be able to output yyr1, etc., after the sizes of
-// the action array is known, we hide the nonterminals
-// derived by productions in levprd.
-//
-func hideprod() {
- nred := 0
- levprd[0] = 0
- for i := 1; i < nprod; i++ {
- if (levprd[i] & REDFLAG) == 0 {
- if foutput != nil {
- fmt.Fprintf(foutput, "Rule not reduced: %v\n",
- writem(Pitem{prdptr[i], 0, 0, i}))
- }
- fmt.Printf("rule %v never reduced\n", writem(Pitem{prdptr[i], 0, 0, i}))
- nred++
- }
- levprd[i] = prdptr[i][0] - NTBASE
- }
- if nred != 0 {
- fmt.Printf("%v rules never reduced\n", nred)
- }
-}
-
-func callopt() {
- var j, k, p, q, i int
- var v []int
-
- pgo = make([]int, nnonter+1)
- pgo[0] = 0
- maxoff = 0
- maxspr = 0
- for i = 0; i < nstate; i++ {
- k = 32000
- j = 0
- v = optst[i]
- q = len(v)
- for p = 0; p < q; p += 2 {
- if v[p] > j {
- j = v[p]
- }
- if v[p] < k {
- k = v[p]
- }
- }
-
- // nontrivial situation
- if k <= j {
- // j is now the range
- // j -= k; // call scj
- if k > maxoff {
- maxoff = k
- }
- }
- tystate[i] = q + 2*j
- if j > maxspr {
- maxspr = j
- }
- }
-
- // initialize ggreed table
- ggreed = make([]int, nnonter+1)
- for i = 1; i <= nnonter; i++ {
- ggreed[i] = 1
- j = 0
-
- // minimum entry index is always 0
- v = yypgo[i]
- q = len(v) - 1
- for p = 0; p < q; p += 2 {
- ggreed[i] += 2
- if v[p] > j {
- j = v[p]
- }
- }
- ggreed[i] = ggreed[i] + 2*j
- if j > maxoff {
- maxoff = j
- }
- }
-
- // now, prepare to put the shift actions into the amem array
- for i = 0; i < ACTSIZE; i++ {
- amem[i] = 0
- }
- maxa = 0
- for i = 0; i < nstate; i++ {
- if tystate[i] == 0 && adb > 1 {
- fmt.Fprintf(ftable, "State %v: null\n", i)
- }
- indgo[i] = yyFlag
- }
-
- i = nxti()
- for i != NOMORE {
- if i >= 0 {
- stin(i)
- } else {
- gin(-i)
- }
- i = nxti()
- }
-
- // print amem array
- if adb > 2 {
- for p = 0; p <= maxa; p += 10 {
- fmt.Fprintf(ftable, "%v ", p)
- for i = 0; i < 10; i++ {
- fmt.Fprintf(ftable, "%v ", amem[p+i])
- }
- ftable.WriteRune('\n')
- }
- }
-
- aoutput()
- osummary()
-}
-
-//
-// finds the next i
-//
-func nxti() int {
- max := 0
- maxi := 0
- for i := 1; i <= nnonter; i++ {
- if ggreed[i] >= max {
- max = ggreed[i]
- maxi = -i
- }
- }
- for i := 0; i < nstate; i++ {
- if tystate[i] >= max {
- max = tystate[i]
- maxi = i
- }
- }
- if max == 0 {
- return NOMORE
- }
- return maxi
-}
-
-func gin(i int) {
- var s int
-
- // enter gotos on nonterminal i into array amem
- ggreed[i] = 0
-
- q := yypgo[i]
- nq := len(q) - 1
-
- // now, find amem place for it
-nextgp:
- for p := 0; p < ACTSIZE; p++ {
- if amem[p] != 0 {
- continue
- }
- for r := 0; r < nq; r += 2 {
- s = p + q[r] + 1
- if s > maxa {
- maxa = s
- if maxa >= ACTSIZE {
- errorf("a array overflow")
- }
- }
- if amem[s] != 0 {
- continue nextgp
- }
- }
-
- // we have found amem spot
- amem[p] = q[nq]
- if p > maxa {
- maxa = p
- }
- for r := 0; r < nq; r += 2 {
- s = p + q[r] + 1
- amem[s] = q[r+1]
- }
- pgo[i] = p
- if adb > 1 {
- fmt.Fprintf(ftable, "Nonterminal %v, entry at %v\n", i, pgo[i])
- }
- return
- }
- errorf("cannot place goto %v\n", i)
-}
-
-func stin(i int) {
- var s int
-
- tystate[i] = 0
-
- // enter state i into the amem array
- q := optst[i]
- nq := len(q)
-
-nextn:
- // find an acceptable place
- for n := -maxoff; n < ACTSIZE; n++ {
- flag := 0
- for r := 0; r < nq; r += 2 {
- s = q[r] + n
- if s < 0 || s > ACTSIZE {
- continue nextn
- }
- if amem[s] == 0 {
- flag++
- } else if amem[s] != q[r+1] {
- continue nextn
- }
- }
-
- // check the position equals another only if the states are identical
- for j := 0; j < nstate; j++ {
- if indgo[j] == n {
-
- // we have some disagreement
- if flag != 0 {
- continue nextn
- }
- if nq == len(optst[j]) {
-
- // states are equal
- indgo[i] = n
- if adb > 1 {
- fmt.Fprintf(ftable, "State %v: entry at"+
- "%v equals state %v\n",
- i, n, j)
- }
- return
- }
-
- // we have some disagreement
- continue nextn
- }
- }
-
- for r := 0; r < nq; r += 2 {
- s = q[r] + n
- if s > maxa {
- maxa = s
- }
- if amem[s] != 0 && amem[s] != q[r+1] {
- errorf("clobber of a array, pos'n %v, by %v", s, q[r+1])
- }
- amem[s] = q[r+1]
- }
- indgo[i] = n
- if adb > 1 {
- fmt.Fprintf(ftable, "State %v: entry at %v\n", i, indgo[i])
- }
- return
- }
- errorf("Error; failure to place state %v", i)
-}
-
-//
-// this version is for limbo
-// write out the optimized parser
-//
-func aoutput() {
- fmt.Fprintf(ftable, "const\t%sLast\t= %v\n", prefix, maxa+1)
- arout("Act", amem, maxa+1)
- arout("Pact", indgo, nstate)
- arout("Pgo", pgo, nnonter+1)
-}
-
-//
-// put out other arrays, copy the parsers
-//
-func others() {
- var i, j int
-
- arout("R1", levprd, nprod)
- aryfil(temp1, nprod, 0)
-
- //
- //yyr2 is the number of rules for each production
- //
- for i = 1; i < nprod; i++ {
- temp1[i] = len(prdptr[i]) - 2
- }
- arout("R2", temp1, nprod)
-
- aryfil(temp1, nstate, -1000)
- for i = 0; i <= ntokens; i++ {
- for j := tstates[i]; j != 0; j = mstates[j] {
- temp1[j] = i
- }
- }
- for i = 0; i <= nnonter; i++ {
- for j = ntstates[i]; j != 0; j = mstates[j] {
- temp1[j] = -i
- }
- }
- arout("Chk", temp1, nstate)
- arout("Def", defact, nstate)
-
- // put out token translation tables
- // table 1 has 0-256
- aryfil(temp1, 256, 0)
- c := 0
- for i = 1; i <= ntokens; i++ {
- 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.Printf(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name)
- nerrors++
- }
- temp1[j] = i
- if j > c {
- c = j
- }
- }
- }
- for i = 0; i <= c; i++ {
- if temp1[i] == 0 {
- temp1[i] = YYLEXUNK
- }
- }
- arout("Tok1", temp1, c+1)
-
- // table 2 has PRIVATE-PRIVATE+256
- aryfil(temp1, 256, 0)
- c = 0
- for i = 1; i <= ntokens; i++ {
- 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.Printf(" %s and %s\n", tokset[i].name, tokset[temp1[j]].name)
- nerrors++
- }
- temp1[j] = i
- if j > c {
- c = j
- }
- }
- }
- arout("Tok2", temp1, c+1)
-
- // table 3 has everything else
- fmt.Fprintf(ftable, "var\t%sTok3\t= []int {\n", prefix)
- c = 0
- for i = 1; i <= ntokens; i++ {
- j = tokset[i].value
- if j >= 0 && j < 256 {
- continue
- }
- if j >= PRIVATE && j < 256+PRIVATE {
- continue
- }
-
- fmt.Fprintf(ftable, "%4d,%4d,", j, i)
- c++
- if c%5 == 0 {
- ftable.WriteRune('\n')
- }
- }
- fmt.Fprintf(ftable, "%4d,\n };\n", 0)
-
- // copy parser text
- c = getrune(finput)
- for c != EOF {
- ftable.WriteRune(c)
- c = getrune(finput)
- }
-
- // copy yaccpar
- fmt.Fprintf(ftable, "\n//line yaccpar:1\n")
-
- parts := strings.SplitN(yaccpar, prefix+"run()", 2)
- fmt.Fprintf(ftable, "%v", parts[0])
- ftable.Write(fcode.Bytes())
- fmt.Fprintf(ftable, "%v", parts[1])
-}
-
-func arout(s string, v []int, n int) {
- s = prefix + s
- fmt.Fprintf(ftable, "var\t%v\t= []int {\n", s)
- for i := 0; i < n; i++ {
- if i%10 == 0 {
- ftable.WriteRune('\n')
- }
- fmt.Fprintf(ftable, "%4d", v[i])
- ftable.WriteRune(',')
- }
- fmt.Fprintf(ftable, "\n};\n")
-}
-
-//
-// output the summary on y.output
-//
-func summary() {
- if foutput != nil {
- fmt.Fprintf(foutput, "\n%v terminals, %v nonterminals\n", ntokens, nnonter+1)
- fmt.Fprintf(foutput, "%v grammar rules, %v/%v states\n", nprod, nstate, NSTATES)
- fmt.Fprintf(foutput, "%v shift/reduce, %v reduce/reduce conflicts reported\n", zzsrconf, zzrrconf)
- fmt.Fprintf(foutput, "%v working sets used\n", len(wsets))
- fmt.Fprintf(foutput, "memory: parser %v/%v\n", memp, ACTSIZE)
- fmt.Fprintf(foutput, "%v extra closures\n", zzclose-2*nstate)
- fmt.Fprintf(foutput, "%v shift entries, %v exceptions\n", zzacent, zzexcp)
- fmt.Fprintf(foutput, "%v goto entries\n", zzgoent)
- fmt.Fprintf(foutput, "%v entries saved by goto default\n", zzgobest)
- }
- if zzsrconf != 0 || zzrrconf != 0 {
- fmt.Printf("\nconflicts: ")
- if zzsrconf != 0 {
- fmt.Printf("%v shift/reduce", zzsrconf)
- }
- if zzsrconf != 0 && zzrrconf != 0 {
- fmt.Printf(", ")
- }
- if zzrrconf != 0 {
- fmt.Printf("%v reduce/reduce", zzrrconf)
- }
- fmt.Printf("\n")
- }
-}
-
-//
-// write optimizer summary
-//
-func osummary() {
- if foutput == nil {
- return
- }
- i := 0
- for p := maxa; p >= 0; p-- {
- if amem[p] == 0 {
- i++
- }
- }
-
- fmt.Fprintf(foutput, "Optimizer space used: output %v/%v\n", maxa+1, ACTSIZE)
- fmt.Fprintf(foutput, "%v table entries, %v zero\n", maxa+1, i)
- fmt.Fprintf(foutput, "maximum spread: %v, maximum offset: %v\n", maxspr, maxoff)
-}
-
-//
-// copies and protects "'s in q
-//
-func chcopy(q string) string {
- s := ""
- i := 0
- j := 0
- for i = 0; i < len(q); i++ {
- if q[i] == '"' {
- s += q[j:i] + "\\"
- j = i
- }
- }
- return s + q[j:i]
-}
-
-func usage() {
- fmt.Fprintf(stderr, "usage: goyacc [-o output] [-v parsetable] input\n")
- exit(1)
-}
-
-func bitset(set Lkset, bit int) int { return set[bit>>5] & (1 << uint(bit&31)) }
-
-func setbit(set Lkset, bit int) { set[bit>>5] |= (1 << uint(bit&31)) }
-
-func mkset() Lkset { return make([]int, tbitset) }
-
-//
-// set a to the union of a and b
-// return 1 if b is not a subset of a, 0 otherwise
-//
-func setunion(a, b []int) int {
- sub := 0
- for i := 0; i < tbitset; i++ {
- x := a[i]
- y := x | b[i]
- a[i] = y
- if y != x {
- sub = 1
- }
- }
- return sub
-}
-
-func prlook(p Lkset) {
- if p == nil {
- fmt.Fprintf(foutput, "\tNULL")
- return
- }
- fmt.Fprintf(foutput, " { ")
- for j := 0; j <= ntokens; j++ {
- if bitset(p, j) != 0 {
- fmt.Fprintf(foutput, "%v ", symnam(j))
- }
- }
- fmt.Fprintf(foutput, "}")
-}
-
-//
-// utility routines
-//
-var peekrune int
-
-func isdigit(c int) bool { return c >= '0' && c <= '9' }
-
-func isword(c int) bool {
- return c >= 0xa0 || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
-}
-
-func mktemp(t string) string { return t }
-
-//
-// return 1 if 2 arrays are equal
-// return 0 if not equal
-//
-func aryeq(a []int, b []int) int {
- n := len(a)
- if len(b) != n {
- return 0
- }
- for ll := 0; ll < n; ll++ {
- if a[ll] != b[ll] {
- return 0
- }
- }
- return 1
-}
-
-func putrune(f *bufio.Writer, c int) {
- s := string(c)
- for i := 0; i < len(s); i++ {
- f.WriteByte(s[i])
- }
-}
-
-func getrune(f *bufio.Reader) int {
- var r int
-
- if peekrune != 0 {
- if peekrune == EOF {
- return EOF
- }
- r = peekrune
- peekrune = 0
- return r
- }
-
- c, n, err := f.ReadRune()
- if n == 0 {
- return EOF
- }
- if err != nil {
- errorf("read error: %v", err)
- }
- //fmt.Printf("rune = %v n=%v\n", string(c), n);
- return c
-}
-
-func ungetrune(f *bufio.Reader, c int) {
- if f != finput {
- panic("ungetc - not finput")
- }
- if peekrune != 0 {
- panic("ungetc - 2nd unget")
- }
- peekrune = c
-}
-
-func write(f *bufio.Writer, b []byte, n int) int {
- panic("write")
- return 0
-}
-
-func open(s string) *bufio.Reader {
- fi, err := os.Open(s)
- if err != nil {
- errorf("error opening %v: %v", s, err)
- }
- //fmt.Printf("open %v\n", s);
- return bufio.NewReader(fi)
-}
-
-func create(s string) *bufio.Writer {
- fo, err := os.Create(s)
- if err != nil {
- errorf("error creating %v: %v", s, err)
- }
- //fmt.Printf("create %v mode %v\n", s);
- return bufio.NewWriter(fo)
-}
-
-//
-// write out error comment
-//
-func errorf(s string, v ...interface{}) {
- nerrors++
- fmt.Fprintf(stderr, s, v...)
- fmt.Fprintf(stderr, ": %v:%v\n", infile, lineno)
- if fatfl != 0 {
- summary()
- exit(1)
- }
-}
-
-func exit(status int) {
- if ftable != nil {
- ftable.Flush()
- ftable = nil
- }
- if foutput != nil {
- foutput.Flush()
- foutput = nil
- }
- if stderr != nil {
- stderr.Flush()
- stderr = nil
- }
- os.Exit(status)
-}
-
-var yaccpar string // will be processed version of yaccpartext: s/$$/prefix/g
-var yaccpartext = `
-/* parser for yacc output */
-
-var $$Debug = 0
-
-type $$Lexer interface {
- Lex(lval *$$SymType) int
- Error(s string)
-}
-
-const $$Flag = -1000
-
-func $$Tokname(c int) string {
- if c > 0 && c <= len($$Toknames) {
- if $$Toknames[c-1] != "" {
- return $$Toknames[c-1]
- }
- }
- return fmt.Sprintf("tok-%v", c)
-}
-
-func $$Statname(s int) string {
- if s >= 0 && s < len($$Statenames) {
- if $$Statenames[s] != "" {
- return $$Statenames[s]
- }
- }
- return fmt.Sprintf("state-%v", s)
-}
-
-func $$lex1(lex $$Lexer, lval *$$SymType) int {
- c := 0
- char := lex.Lex(lval)
- if char <= 0 {
- c = $$Tok1[0]
- goto out
- }
- if char < len($$Tok1) {
- c = $$Tok1[char]
- goto out
- }
- if char >= $$Private {
- if char < $$Private+len($$Tok2) {
- c = $$Tok2[char-$$Private]
- goto out
- }
- }
- for i := 0; i < len($$Tok3); i += 2 {
- c = $$Tok3[i+0]
- if c == char {
- c = $$Tok3[i+1]
- goto out
- }
- }
-
-out:
- if c == 0 {
- c = $$Tok2[1] /* unknown char */
- }
- if $$Debug >= 3 {
- fmt.Printf("lex %U %s\n", uint(char), $$Tokname(c))
- }
- return c
-}
-
-func $$Parse($$lex $$Lexer) int {
- var $$n int
- var $$lval $$SymType
- var $$VAL $$SymType
- $$S := make([]$$SymType, $$MaxDepth)
-
- Nerrs := 0 /* number of errors */
- Errflag := 0 /* error recovery flag */
- $$state := 0
- $$char := -1
- $$p := -1
- goto $$stack
-
-ret0:
- return 0
-
-ret1:
- return 1
-
-$$stack:
- /* put a state and value onto the stack */
- if $$Debug >= 4 {
- fmt.Printf("char %v in %v\n", $$Tokname($$char), $$Statname($$state))
- }
-
- $$p++
- if $$p >= len($$S) {
- nyys := make([]$$SymType, len($$S)*2)
- copy(nyys, $$S)
- $$S = nyys
- }
- $$S[$$p] = $$VAL
- $$S[$$p].yys = $$state
-
-$$newstate:
- $$n = $$Pact[$$state]
- if $$n <= $$Flag {
- goto $$default /* simple state */
- }
- if $$char < 0 {
- $$char = $$lex1($$lex, &$$lval)
- }
- $$n += $$char
- if $$n < 0 || $$n >= $$Last {
- goto $$default
- }
- $$n = $$Act[$$n]
- if $$Chk[$$n] == $$char { /* valid shift */
- $$char = -1
- $$VAL = $$lval
- $$state = $$n
- if Errflag > 0 {
- Errflag--
- }
- goto $$stack
- }
-
-$$default:
- /* default state action */
- $$n = $$Def[$$state]
- if $$n == -2 {
- if $$char < 0 {
- $$char = $$lex1($$lex, &$$lval)
- }
-
- /* look through exception table */
- xi := 0
- for {
- if $$Exca[xi+0] == -1 && $$Exca[xi+1] == $$state {
- break
- }
- xi += 2
- }
- for xi += 2; ; xi += 2 {
- $$n = $$Exca[xi+0]
- if $$n < 0 || $$n == $$char {
- break
- }
- }
- $$n = $$Exca[xi+1]
- if $$n < 0 {
- goto ret0
- }
- }
- if $$n == 0 {
- /* error ... attempt to resume parsing */
- switch Errflag {
- case 0: /* brand new error */
- $$lex.Error("syntax error")
- Nerrs++
- if $$Debug >= 1 {
- fmt.Printf("%s", $$Statname($$state))
- fmt.Printf("saw %s\n", $$Tokname($$char))
- }
- fallthrough
-
- case 1, 2: /* incompletely recovered error ... try again */
- Errflag = 3
-
- /* find a state where "error" is a legal shift action */
- for $$p >= 0 {
- $$n = $$Pact[$$S[$$p].yys] + $$ErrCode
- if $$n >= 0 && $$n < $$Last {
- $$state = $$Act[$$n] /* simulate a shift of "error" */
- if $$Chk[$$state] == $$ErrCode {
- goto $$stack
- }
- }
-
- /* the current p has no shift onn "error", pop stack */
- if $$Debug >= 2 {
- fmt.Printf("error recovery pops state %d, uncovers %d\n",
- $$S[$$p].yys, $$S[$$p-1].yys)
- }
- $$p--
- }
- /* there is no state on the stack with an error shift ... abort */
- goto ret1
-
- case 3: /* no shift yet; clobber input char */
- if $$Debug >= 2 {
- fmt.Printf("error recovery discards %s\n", $$Tokname($$char))
- }
- if $$char == $$EofCode {
- goto ret1
- }
- $$char = -1
- goto $$newstate /* try again in the same state */
- }
- }
-
- /* reduction by production $$n */
- if $$Debug >= 2 {
- fmt.Printf("reduce %v in:\n\t%v\n", $$n, $$Statname($$state))
- }
-
- $$nt := $$n
- $$pt := $$p
- _ = $$pt // guard against "declared and not used"
-
- $$p -= $$R2[$$n]
- $$VAL = $$S[$$p+1]
-
- /* consult goto table to find next state */
- $$n = $$R1[$$n]
- $$g := $$Pgo[$$n]
- $$j := $$g + $$S[$$p].yys + 1
-
- if $$j >= $$Last {
- $$state = $$Act[$$g]
- } else {
- $$state = $$Act[$$j]
- if $$Chk[$$state] != -$$n {
- $$state = $$Act[$$g]
- }
- }
- // dummy call; replaced with literal code
- $$run()
- goto $$stack /* stack new state and value */
-}
-`
diff --git a/src/cmd/goyacc/units.txt b/src/cmd/goyacc/units.txt
deleted file mode 100644
index ddb2bc294..000000000
--- a/src/cmd/goyacc/units.txt
+++ /dev/null
@@ -1,576 +0,0 @@
-/ Plan 9's /lib/units
-/ http://plan9.bell-labs.com/sources/plan9/lib/units
-/
-/ Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
-/ Distributed under the terms of the Lucent Public License Version 1.02
-/ See http://plan9.bell-labs.com/plan9/license.html
-/
-/order of evaluation
-/ + -
-/ * /
-/ juxtaposition (meaning *)
-/ ¹ ² ³ ^
-/ | (meaning /)
-/ name number ()
-
-/dimensions
-m #
-kg #
-sec #
-coul #
-candela #
-$ #
-radian #
-bit #
-erlang #
-°K #
-°C #
-°F #
-
-/constants
-
-π 3.14159265358979323846
-pi π
-c 2.997925e+8 m/sec
-g 9.80665 m/sec²
-au 1.49597871e+11 m
-mole 6.022169e+23
-e 1.6021917e-19 coul
-energy c²
-force g
-mercury 1.33322e+5 kg/m²sec²
-hg mercury
-h 6.62620e-34 m²kg/sec
-ℏ h/2 π
-hbar ℏ
-nonillion 1e30
-octillion 1e27
-septillion 1e24
-sextillion 1e21
-pentillion 1e18
-quadrillion 1e15
-trillion 1e12
-billion 1e9
-million 1e6
-thousand 1e3
-hundred 1e2
-
-/dimensionless
-
-° 1|180 π radian
-degree °
-circle 2 π radian
-turn 2 π radian
-grad .9 °
-arcdeg 1 °
-arcmin 1|60 °
-arcsec 1|3600 °
-ccs 1|36 erlang
-
-steradian radian²
-sphere 4 π steradian
-sr steradian
-giga 1024 1024 1024
-
-/Time
-
-second sec
-s sec
-minute 60 sec
-min minute
-hour 60 min
-hr hour
-day 24 hr
-da day
-week 7 day
-year 365.24219879 day
-yr year
-month 1|12 year
-ms millisec
-us microsec
-
-/Mass
-
-gram millikg
-gm gram
-mg milligram
-metricton kilokg
-
-/Avoirdupois
-
-lb .45359237 kg
-lbf lb g
-pound lb
-ounce 1|16 lb
-oz ounce
-dram 1|16 oz
-dr dram
-grain 1|7000 lb
-gr grain
-shortton 2000 lb
-ton shortton
-longton 2240 lb
-
-/Apothecary
-
-scruple 20 grain
-apdram 60 grain
-apounce 480 grain
-troyounce apounce
-appound 5760 grain
-troypound appound
-
-/Length
-
-meter m
-cm centimeter
-mm millimeter
-km kilometer
-nm nanometer
-micron micrometer
-µ micrometer
-Å decinanometer
-angstrom Å
-
-inch 2.54 cm
-" inch
-in inch
-inches inch
-' 12"
-foot 12 in
-feet foot
-ft foot
-yard 3 ft
-yd yard
-rod 5.5 yd
-rd rod
-mile 5280 ft
-mi mile
-
-british 1200|3937 m/ft
-nmile 1852 m
-
-acre 4840 yd²
-
-cc cm³
-liter kilocc
-ml milliliter
-
-/US Liquid
-
-gallon 231 in³
-imperial 1.20095
-epa 0.8
-gal gallon
-quart 1|4 gal
-qt quart
-pint 1|2 qt
-pt pint
-
-floz 1|16 pt
-fldr 1|8 floz
-
-/US Dry
-
-dry 268.8025 in³/gallon
-peck 8 dry quart
-pk peck
-bushel 4 peck
-bu bushel
-
-/British
-
-brgallon 277.420 in³
-brquart 1|4 brgallon
-brpint 1|2 brquart
-brfloz 1|20 brpint
-brpeck 554.84 in³
-brbushel 4 brpeck
-
-/Energy Work
-
-newton kg m/sec²
-nt newton
-joule nt m
-cal 4.1868 joule
-
-/Electrical
-
-coulomb coul
-ampere coul/sec
-amp ampere
-watt joule/sec
-volt watt/amp
-Ω volt/amp
-ohm Ω
-mho 1/Ω
-farad coul/volt
-henry sec²/farad
-weber volt sec
-
-/Light
-
-cd candela
-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 $
-
-/ END MONEY
-
-€ europeuro
-£ britainpound
-¥ japanyen
-dollar $
-
-baht thailandbaht
-brpound britainpound
-dirham uaedirham
-euro europeuro
-forint hungaryforint
-krona swedenkrona
-peso mexicopeso
-rand southafricarand
-real brazilreal
-yuan chinayuan
-ringgit malaysiaringgit
-riyal saudiarabiariyal
-ruble russiaruble
-rupee indiarupee
-rupiah indonesiarupiah
-shekel israelshekel
-sol perunewsol
-won southkoreawon
-yen japanyen
-zloty polandzloty
-
-usdollar dollar
-sterling britainpound | pound
-poundsterling britainpound
-
-/bits
-
-baud bit/sec
-byte 8 bit
-short 2 byte
-long 4 byte
-vlong 8 bytes
-frame 2352 byte
-
-/Australian liquid measure
-
-pony 7 brfloz
-midie 10 brfloz
-pot midie
-handle midie
-schooner 15 brfloz
-jug 40 brfloz
-resch midie
-alf midie
-tinny 13 brfloz
-stubby tinny
-twisty 250 ml
-longneck 2 tinny
-slab 24 tinny
-sixpack 6 tinny
-nip brfloz
-
-/wine
-winebottle 750 ml
-balthazar 16 winebottle
-jeroboam 4 winebottle
-magnum 2 winebottle
-mathusalem 8 winebottle
-methuselah 8 winebottle
-nebuchadnezzar 20 winebottle
-rehoboam 6 winebottle
-salmanazar 12 winebottle
-split 0.25 winebottle
-jigger 1.5 floz
-
-/Trivia
-
-% 1|100
-admiraltyknot 6080 ft/hr
-ε₀ (1e-9/36π) farad/m
-α (1/4π ε₀) e²/ℏ c
-alpha α
-apostilb cd/π m²
-are 1e+2 m²
-arpentcan 27.52 mi
-arpentlin 191.835 ft
-astronomicalunit au
-atmosphere 1.01325e+5 nt/m²
-atm atmosphere
-atomicmassunit 1.66044e-27 kg
-amu atomicmassunit
-bag 94 lb
-bakersdozen 13
-bar 1e+5 nt/m²
-barie 1e-1 nt/m²
-barleycorn 1|3 in
-barn 1e-28 m²
-barrel 42 gal
-barye 1e-1 nt/m²
-bev 1e+9 e volt
-biot 10 amp
-blondel cd/π m²
-boardfoot 144 in³
-bolt 40 yd
-bottommeasure 1|40 in
-britishthermalunit 1.05506e+3 joule
-btu britishthermalunit
-quad 1.0e+15 btu
-refrigeration 12000 btu/ton hour
-buck dollar
-cable 720 ft
-caliber 1e-2 in
-calorie cal
-carat 205 mg
-cent centidollar
-cental 100 lb
-centesimalminute 1e-2 grad
-centesimalsecond 1e-4 grad
-century 100 year
-cfs ft³/sec
-chain 66 ft
-circularinch 1|4 π in²
-circularmil 1e-6|4 π in²
-clusec 1e-8 mm hg m³/s
-coomb 4 bu
-cord 128 ft³
-cordfoot cord
-crith 9.06e-2 gm
-cubit 18 in
-cup 1|2 pt
-curie 3.7e+10/sec
-cusec ft³/sec
-dalton amu
-decade 10 yr
-degK °K
-degC °C
-degF °F
-dipotre 1/m
-displacementton 35 ft³
-doppelzentner 100 kg
-dozen 12
-drop .03 cm³
-dyne cm gm/sec²
-electronvolt e volt
-ell 45 in
-engineerschain 100 ft
-engineerslink 100|100 ft
-equivalentfootcandle lumen/π ft²
-equivalentlux lumen/π m²
-equivalentphot cd/π cm²
-erg cm²gm/sec²
-ev e volt
-faraday 9.652e+4 coul
-fathom 6 ft
-fermi 1e-15 m
-fifth 4|5 qt
-fin 5 dollar
-finger 7|8 in
-firkin 9 gal
-footcandle lumen/ft²
-footlambert cd/π ft²
-fortnight 14 da
-franklin 3.33564e-10 coul
-frigorie kilocal
-furlong 220 yd
-galileo 1e-2 m/sec²
-gamma 1e-9 weber/m²
-gauss 1e-4 weber/m²
-geodeticfoot british ft
-geographicalmile 1852 m
-gilbert 7.95775e-1 amp
-gill 1|4 pt
-gross 144
-gunterschain 22 yd
-hand 4 in
-hectare 1e+4 m²
-hefnercandle .92 cd
-hertz 1/sec
-hogshead 2 barrel
-hd hogshead
-homestead 1|4 mi²
-horsepower 550 ft lb g/sec
-hp horsepower
-hyl gm force sec²/m
-hz 1/sec
-imaginarycubicfoot 1.4 ft³
-karat 1|24
-kcal kilocal
-kcalorie kilocal
-kev 1e+3 e volt
-key kg
-khz 1e+3/sec
-kilderkin 18 gal
-knot nmile/hr
-kwh kilowatt hour
-lambert cd/π cm²
-langley cal/cm²
-last 80 bu
-league 3 mi
-lightyear c yr
-ly lightyear
-lightsecond c sec
-line 1|12 in
-link 66|100 ft
-longhundredweight 112 lb
-longquarter 28 lb
-lusec 1e-6 mm hg m³/s
-mach 331.46 m/sec
-marineleague 3 nmile
-maxwell 1e-8 weber
-metriccarat 200 mg
-mev 1e+6 e volt
-mgd megagal/day
-mh millihenry
-mhz 1e+6/sec
-mil 1e-3 in
-millenium 1000 year
-minersinch 1.5 ft³/min
-minim 1|60 fldr
-mo month
-mpg mile/gal
-mph mile/hr
-nail 1|16 yd
-nauticalmile nmile
-nit cd/m²
-noggin 1|8 qt
-nox 1e-3 lux
-ns nanosec
-oersted 2.5e+2 amp/m π
-oe oersted
-pace 36 in
-palm 3 in
-parasang 3.5 mi
-parsec au radian/arcsec
-pascal nt/m²
-pc parsec
-pennyweight 1|20 oz
-percent %
-perch rd
-pf picofarad
-phot lumen/cm²
-pica 1|6 in
-pieze 1e+3 nt/m²
-pipe 4 barrel
-point 1|72 in
-poise gm/cm sec
-pole rd
-poundal ft lb/sec²
-pdl poundal
-proof 1/200
-psi lb g/in²
-quarter 9 in
-quartersection 1|4 mi²
-quintal 100 kg
-quire 25
-rad 100 erg/gm
-ream 500
-registerton 100 ft³
-rhe 10 m²/nt sec
-rontgen 2.58e-4 curie/kg
-rood 1.21e+3 yd
-rope 20 ft
-rutherford 1e+6/sec
-rydberg 1.36054e+1 ev
-sabin 1 ft²
-sack 3 bu
-seam 8 bu
-section mi²
-shippington 40 ft³
-shorthundredweight 100 lb
-shortquarter 25 lb
-siemens 1/Ω
-σ 5.66956e-5 erg/cm² °K^4 sec
-sigma σ
-skein 120 yd
-skot 1e-3 apostilb
-slug lb g sec²/ft
-span 9 in
-spat 4 π sr
-spindle 14400 yd
-square 100 ft²
-squidge 1|972 inch
-catsquidge 1|432 inch
-stere m³
-sthene 1e+3 nt
-stilb cd/cm²
-stoke 1e-4 m²/sec
-stone 14 lb
-strike 2 bu
-surveyfoot british ft
-surveyorschain 66 ft
-surveyorslink 66|100 ft
-tablespoon 4 fldr
-teaspoon 4|3 fldr
-tesla weber/m²
-therm 1e+5 btu
-thermie 1e+6 cal
-timberfoot ft³
-tnt 4.6e+6 m²/sec²
-tonne 1e+6 gm
-torr mm hg
-township 36 mi²
-tun 8 barrel
-water .22491|2.54 kg/m²sec²
-wey 40 bu
-weymass 252 lb
-Xunit 1.00202e-13 m
-k 1.38047e-16 erg/°K
-foal 9223372036854775807
diff --git a/src/cmd/goyacc/units.y b/src/cmd/goyacc/units.y
deleted file mode 100644
index d9ef663d9..000000000
--- a/src/cmd/goyacc/units.y
+++ /dev/null
@@ -1,765 +0,0 @@
-// Derived from Plan 9's /sys/src/cmd/units.y
-// http://plan9.bell-labs.com/sources/plan9/sys/src/cmd/units.y
-//
-// Copyright (C) 2003, Lucent Technologies Inc. and others. All Rights Reserved.
-// Portions Copyright 2009 The Go Authors. All Rights Reserved.
-// Distributed under the terms of the Lucent Public License Version 1.02
-// See http://plan9.bell-labs.com/plan9/license.html
-
-// Generate parser with prefix "units_":
-// goyacc -p "units_"
-
-%{
-
-// units.y
-// example of a goyacc program
-// usage is
-// goyacc units.y (produces y.go)
-// 6g y.go
-// 6l y.6
-// ./6.out $GOROOT/src/cmd/goyacc/units
-// you have: c
-// you want: furlongs/fortnight
-// * 1.8026178e+12
-// / 5.5474878e-13
-// you have:
-
-package main
-
-import (
- "flag"
- "fmt"
- "bufio"
- "os"
- "math"
- "strconv"
- "utf8"
-)
-
-const (
- Ndim = 15 // number of dimensions
- Maxe = 695 // log of largest number
-)
-
-type Node struct {
- vval float64
- dim [Ndim]int8
-}
-
-type Var struct {
- name string
- node Node
-}
-
-var fi *bufio.Reader // input
-var fund [Ndim]*Var // names of fundamental units
-var line string // current input line
-var lineno int // current input line number
-var linep int // index to next rune in unput
-var nerrors int // error count
-var one Node // constant one
-var peekrune int // backup runt from input
-var retnode1 Node
-var retnode2 Node
-var retnode Node
-var sym string
-var vflag bool
-
-%}
-
-%union
-{
- node Node
- vvar *Var
- numb int
- vval float64
-}
-
-%type <node> prog expr expr0 expr1 expr2 expr3 expr4
-
-%token <vval> VAL
-%token <vvar> VAR
-%token <numb> SUP
-%%
-prog:
- ':' VAR expr
- {
- var f int
-
- f = int($2.node.dim[0])
- $2.node = $3
- $2.node.dim[0] = 1
- if f != 0 {
- Errorf("redefinition of %v", $2.name)
- } else if vflag {
- fmt.Printf("%v\t%v\n", $2.name, &$2.node)
- }
- }
-| ':' VAR '#'
- {
- var f, i int
-
- for i=1; i<Ndim; i++ {
- if fund[i] == nil {
- break
- }
- }
- if i >= Ndim {
- Error("too many dimensions")
- i = Ndim-1
- }
- fund[i] = $2
-
- f = int($2.node.dim[0])
- $2.node = one
- $2.node.dim[0] = 1
- $2.node.dim[i] = 1
- if f != 0 {
- Errorf("redefinition of %v", $2.name)
- } else
- if vflag {
- fmt.Printf("%v\t#\n", $2.name)
- }
- }
-| ':'
- {
- }
-| '?' expr
- {
- retnode1 = $2
- }
-| '?'
- {
- retnode1 = one
- }
-
-expr:
- expr4
-| expr '+' expr4
- {
- add(&$$, &$1, &$3)
- }
-| expr '-' expr4
- {
- sub(&$$, &$1, &$3)
- }
-
-expr4:
- expr3
-| expr4 '*' expr3
- {
- mul(&$$, &$1, &$3)
- }
-| expr4 '/' expr3
- {
- div(&$$, &$1, &$3)
- }
-
-expr3:
- expr2
-| expr3 expr2
- {
- mul(&$$, &$1, &$2)
- }
-
-expr2:
- expr1
-| expr2 SUP
- {
- xpn(&$$, &$1, $2)
- }
-| expr2 '^' expr1
- {
- var i int
-
- for i=1; i<Ndim; i++ {
- if $3.dim[i] != 0 {
- Error("exponent has units")
- $$ = $1
- break
- }
- }
- if i >= Ndim {
- i = int($3.vval)
- if float64(i) != $3.vval {
- Error("exponent not integral")
- }
- xpn(&$$, &$1, i)
- }
- }
-
-expr1:
- expr0
-| expr1 '|' expr0
- {
- div(&$$, &$1, &$3)
- }
-
-expr0:
- VAR
- {
- if $1.node.dim[0] == 0 {
- Errorf("undefined %v", $1.name)
- $$ = one
- } else {
- $$ = $1.node
- }
- }
-| VAL
- {
- $$ = one
- $$.vval = $1
- }
-| '(' expr ')'
- {
- $$ = $2
- }
-%%
-
-type UnitsLex int
-
-func (UnitsLex) Lex(yylval *units_SymType) int {
- var c, i int
-
- c = peekrune
- peekrune = ' '
-
-loop:
- if (c >= '0' && c <= '9') || c == '.' {
- goto numb
- }
- if ralpha(c) {
- goto alpha
- }
- switch c {
- case ' ', '\t':
- c = getrune()
- goto loop
- case '×':
- return '*'
- case '÷':
- return '/'
- case '¹', 'ⁱ':
- yylval.numb = 1
- return SUP
- case '²', '⁲':
- yylval.numb = 2
- return SUP
- case '³', '⁳':
- yylval.numb = 3
- return SUP
- }
- return c
-
-alpha:
- sym = ""
- for i = 0; ; i++ {
- sym += string(c)
- c = getrune()
- if !ralpha(c) {
- break
- }
- }
- peekrune = c
- yylval.vvar = lookup(0)
- return VAR
-
-numb:
- sym = ""
- for i = 0; ; i++ {
- sym += string(c)
- c = getrune()
- if !rdigit(c) {
- break
- }
- }
- peekrune = c
- f, err := strconv.Atof64(sym)
- if err != nil {
- fmt.Printf("error converting %v\n", sym)
- f = 0
- }
- yylval.vval = f
- return VAL
-}
-
-func (UnitsLex) Error(s string) {
- Errorf("syntax error, last name: %v", sym)
-}
-
-func main() {
- var file string
-
- flag.BoolVar(&vflag, "v", false, "verbose")
-
- flag.Parse()
-
- file = os.Getenv("GOROOT") + "/src/cmd/goyacc/units.txt"
- if flag.NArg() > 0 {
- file = flag.Arg(0)
- }
-
- f, err := os.Open(file)
- if err != nil {
- fmt.Fprintf(os.Stderr, "error opening %v: %v\n", file, err)
- os.Exit(1)
- }
- fi = bufio.NewReader(f)
-
- one.vval = 1
-
- /*
- * read the 'units' file to
- * develope a database
- */
- lineno = 0
- for {
- lineno++
- if readline() {
- break
- }
- if len(line) == 0 || line[0] == '/' {
- continue
- }
- peekrune = ':'
- units_Parse(UnitsLex(0))
- }
-
- /*
- * read the console to
- * print ratio of pairs
- */
- fi = bufio.NewReader(os.NewFile(0, "stdin"))
-
- lineno = 0
- for {
- if (lineno & 1) != 0 {
- fmt.Printf("you want: ")
- } else {
- fmt.Printf("you have: ")
- }
- if readline() {
- break
- }
- peekrune = '?'
- nerrors = 0
- units_Parse(UnitsLex(0))
- if nerrors != 0 {
- continue
- }
- if (lineno & 1) != 0 {
- if specialcase(&retnode, &retnode2, &retnode1) {
- fmt.Printf("\tis %v\n", &retnode)
- } else {
- div(&retnode, &retnode2, &retnode1)
- fmt.Printf("\t* %v\n", &retnode)
- div(&retnode, &retnode1, &retnode2)
- fmt.Printf("\t/ %v\n", &retnode)
- }
- } else {
- retnode2 = retnode1
- }
- lineno++
- }
- fmt.Printf("\n")
- os.Exit(0)
-}
-
-/*
- * all characters that have some
- * meaning. rest are usable as names
- */
-func ralpha(c int) bool {
- switch c {
- case 0, '+', '-', '*', '/', '[', ']', '(', ')',
- '^', ':', '?', ' ', '\t', '.', '|', '#',
- '×', '÷', '¹', 'ⁱ', '²', '⁲', '³', '⁳':
- return false
- }
- return true
-}
-
-/*
- * number forming character
- */
-func rdigit(c int) bool {
- switch c {
- case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
- '.', 'e', '+', '-':
- return true
- }
- return false
-}
-
-func Errorf(s string, v ...interface{}) {
- fmt.Printf("%v: %v\n\t", lineno, line)
- fmt.Printf(s, v...)
- fmt.Printf("\n")
-
- nerrors++
- if nerrors > 5 {
- fmt.Printf("too many errors\n")
- os.Exit(1)
- }
-}
-
-func Error(s string) {
- Errorf("%s", s)
-}
-
-func add(c, a, b *Node) {
- var i int
- var d int8
-
- for i = 0; i < Ndim; i++ {
- d = a.dim[i]
- c.dim[i] = d
- if d != b.dim[i] {
- Error("add must be like units")
- }
- }
- c.vval = fadd(a.vval, b.vval)
-}
-
-func sub(c, a, b *Node) {
- var i int
- var d int8
-
- for i = 0; i < Ndim; i++ {
- d = a.dim[i]
- c.dim[i] = d
- if d != b.dim[i] {
- Error("sub must be like units")
- }
- }
- c.vval = fadd(a.vval, -b.vval)
-}
-
-func mul(c, a, b *Node) {
- var i int
-
- for i = 0; i < Ndim; i++ {
- c.dim[i] = a.dim[i] + b.dim[i]
- }
- c.vval = fmul(a.vval, b.vval)
-}
-
-func div(c, a, b *Node) {
- var i int
-
- for i = 0; i < Ndim; i++ {
- c.dim[i] = a.dim[i] - b.dim[i]
- }
- c.vval = fdiv(a.vval, b.vval)
-}
-
-func xpn(c, a *Node, b int) {
- var i int
-
- *c = one
- if b < 0 {
- b = -b
- for i = 0; i < b; i++ {
- div(c, c, a)
- }
- } else {
- for i = 0; i < b; i++ {
- mul(c, c, a)
- }
- }
-}
-
-func specialcase(c, a, b *Node) bool {
- var i int
- var d, d1, d2 int8
-
- d1 = 0
- d2 = 0
- for i = 1; i < Ndim; i++ {
- d = a.dim[i]
- if d != 0 {
- if d != 1 || d1 != 0 {
- return false
- }
- d1 = int8(i)
- }
- d = b.dim[i]
- if d != 0 {
- if d != 1 || d2 != 0 {
- return false
- }
- d2 = int8(i)
- }
- }
- if d1 == 0 || d2 == 0 {
- return false
- }
-
- if fund[d1].name == "°C" && fund[d2].name == "°F" &&
- b.vval == 1 {
- for ll := 0; ll < len(c.dim); ll++ {
- c.dim[ll] = b.dim[ll]
- }
- c.vval = a.vval*9./5. + 32.
- return true
- }
-
- if fund[d1].name == "°F" && fund[d2].name == "°C" &&
- b.vval == 1 {
- for ll := 0; ll < len(c.dim); ll++ {
- c.dim[ll] = b.dim[ll]
- }
- c.vval = (a.vval - 32.) * 5. / 9.
- return true
- }
- return false
-}
-
-func printdim(str string, d, n int) string {
- var v *Var
-
- if n != 0 {
- v = fund[d]
- if v != nil {
- str += fmt.Sprintf("%v", v.name)
- } else {
- str += fmt.Sprintf("[%d]", d)
- }
- switch n {
- case 1:
- break
- case 2:
- str += "²"
- case 3:
- str += "³"
- default:
- str += fmt.Sprintf("^%d", n)
- }
- }
- return str
-}
-
-func (n Node) String() string {
- var str string
- var f, i, d int
-
- str = fmt.Sprintf("%.7e ", n.vval)
-
- f = 0
- for i = 1; i < Ndim; i++ {
- d = int(n.dim[i])
- if d > 0 {
- str = printdim(str, i, d)
- } else if d < 0 {
- f = 1
- }
- }
-
- if f != 0 {
- str += " /"
- for i = 1; i < Ndim; i++ {
- d = int(n.dim[i])
- if d < 0 {
- str = printdim(str, i, -d)
- }
- }
- }
-
- return str
-}
-
-func (v *Var) String() string {
- var str string
- str = fmt.Sprintf("%v %v", v.name, v.node)
- return str
-}
-
-func readline() bool {
- s, err := fi.ReadString('\n')
- if err != nil {
- return true
- }
- line = s
- linep = 0
- return false
-}
-
-func getrune() int {
- var c, n int
-
- if linep >= len(line) {
- return 0
- }
- c, n = utf8.DecodeRuneInString(line[linep:len(line)])
- linep += n
- if c == '\n' {
- c = 0
- }
- return c
-}
-
-var symmap = make(map[string]*Var) // symbol table
-
-func lookup(f int) *Var {
- var p float64
- var w *Var
-
- v, ok := symmap[sym]
- if ok {
- return v
- }
- if f != 0 {
- return nil
- }
- v = new(Var)
- v.name = sym
- symmap[sym] = v
-
- p = 1
- for {
- p = fmul(p, pname())
- if p == 0 {
- break
- }
- w = lookup(1)
- if w != nil {
- v.node = w.node
- v.node.vval = fmul(v.node.vval, p)
- break
- }
- }
- return v
-}
-
-type Prefix struct {
- vval float64
- name string
-}
-
-var prefix = []Prefix{ // prefix table
- {1e-24, "yocto"},
- {1e-21, "zepto"},
- {1e-18, "atto"},
- {1e-15, "femto"},
- {1e-12, "pico"},
- {1e-9, "nano"},
- {1e-6, "micro"},
- {1e-6, "μ"},
- {1e-3, "milli"},
- {1e-2, "centi"},
- {1e-1, "deci"},
- {1e1, "deka"},
- {1e2, "hecta"},
- {1e2, "hecto"},
- {1e3, "kilo"},
- {1e6, "mega"},
- {1e6, "meg"},
- {1e9, "giga"},
- {1e12, "tera"},
- {1e15, "peta"},
- {1e18, "exa"},
- {1e21, "zetta"},
- {1e24, "yotta"},
-}
-
-func pname() float64 {
- var i, j, n int
- var s string
-
- /*
- * rip off normal prefixs
- */
- n = len(sym)
- for i = 0; i < len(prefix); i++ {
- s = prefix[i].name
- j = len(s)
- if j < n && sym[0:j] == s {
- sym = sym[j:n]
- return prefix[i].vval
- }
- }
-
- /*
- * rip off 's' suffixes
- */
- if n > 2 && sym[n-1] == 's' {
- sym = sym[0 : n-1]
- return 1
- }
-
- return 0
-}
-
-
-// careful multiplication
-// exponents (log) are checked before multiply
-func fmul(a, b float64) float64 {
- var l float64
-
- if b <= 0 {
- if b == 0 {
- return 0
- }
- l = math.Log(-b)
- } else {
- l = math.Log(b)
- }
-
- if a <= 0 {
- if a == 0 {
- return 0
- }
- l += math.Log(-a)
- } else {
- l += math.Log(a)
- }
-
- if l > Maxe {
- Error("overflow in multiply")
- return 1
- }
- if l < -Maxe {
- Error("underflow in multiply")
- return 0
- }
- return a * b
-}
-
-// careful division
-// exponents (log) are checked before divide
-func fdiv(a, b float64) float64 {
- var l float64
-
- if b <= 0 {
- if b == 0 {
- Errorf("division by zero: %v %v", a, b)
- return 1
- }
- l = math.Log(-b)
- } else {
- l = math.Log(b)
- }
-
- if a <= 0 {
- if a == 0 {
- return 0
- }
- l -= math.Log(-a)
- } else {
- l -= math.Log(a)
- }
-
- if l < -Maxe {
- Error("overflow in divide")
- return 1
- }
- if l > Maxe {
- Error("underflow in divide")
- return 0
- }
- return a / b
-}
-
-func fadd(a, b float64) float64 {
- return a + b
-}