diff options
Diffstat (limited to 'src/cmd/yacc/units.y')
-rw-r--r-- | src/cmd/yacc/units.y | 768 |
1 files changed, 0 insertions, 768 deletions
diff --git a/src/cmd/yacc/units.y b/src/cmd/yacc/units.y deleted file mode 100644 index 9c1b0b336..000000000 --- a/src/cmd/yacc/units.y +++ /dev/null @@ -1,768 +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_": -// go tool yacc -p "units_" - -%{ - -// 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 -// go tool yacc -p "units_" units.y (produces y.go) -// go build -o units y.go -// ./units $GOROOT/src/cmd/yacc/units.txt -// you have: c -// you want: furlongs/fortnight -// * 1.8026178e+12 -// / 5.5474878e-13 -// you have: - -package main - -import ( - "bufio" - "flag" - "fmt" - "math" - "runtime" - "os" - "path/filepath" - "strconv" - "unicode/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 rune // 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> VÄL // dieresis to test UTF-8 -%token <vvar> VAR -%token <numb> _SUP // tests leading underscore in token name -%% -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 - } - } -| VÄL - { - $$ = one - $$.vval = $1 - } -| '(' expr ')' - { - $$ = $2 - } -%% - -type UnitsLex int - -func (UnitsLex) Lex(yylval *units_SymType) int { - var c rune - var 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 int(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.ParseFloat(sym, 64) - if err != nil { - fmt.Printf("error converting %v\n", sym) - f = 0 - } - yylval.vval = f - return VÄL -} - -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 = filepath.Join(runtime.GOROOT(), "src/cmd/yacc/units.txt") - if flag.NArg() > 0 { - file = flag.Arg(0) - } else if file == "" { - fmt.Fprintf(os.Stderr, "cannot find data file units.txt; provide it as argument or set $GOROOT\n") - os.Exit(1) - } - - 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 - * develop 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 rune) bool { - switch c { - case 0, '+', '-', '*', '/', '[', ']', '(', ')', - '^', ':', '?', ' ', '\t', '.', '|', '#', - '×', '÷', '¹', 'ⁱ', '²', '', '³', '': - return false - } - return true -} - -/* - * number forming character - */ -func rdigit(c rune) 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() rune { - var c rune - var 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 -} |