]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/yacc: replace units example with simpler expr example
authorIan Lance Taylor <iant@golang.org>
Wed, 11 Sep 2013 16:01:47 +0000 (09:01 -0700)
committerIan Lance Taylor <iant@golang.org>
Wed, 11 Sep 2013 16:01:47 +0000 (09:01 -0700)
The units example is nice but is covered by the Lucent
license, which may be a concern for some people making a
commercial source code distribution of Go.

R=golang-dev, r
CC=golang-dev
https://golang.org/cl/13283045

src/cmd/yacc/Makefile
src/cmd/yacc/doc.go
src/cmd/yacc/expr.y [new file with mode: 0644]
src/cmd/yacc/units.txt [deleted file]
src/cmd/yacc/units.y [deleted file]

index 56e954289a0b5b946bbaf5a5f5e1fb2acfb86ceb..480844805ff1962c4ecfc3ec8953167e673900ed 100644 (file)
@@ -2,9 +2,9 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-units: yacc.go units.y
-       go run yacc.go -p units_ units.y
-       go build -o units y.go
+expr: yacc.go expr.y
+       go run yacc.go -p expr expr.y
+       go build -o expr y.go
 
 clean:
-       rm -f y.go y.output units
+       rm -f y.go y.output expr
index 792c104e3df27228086f7343e1f9678d524faa72..ceaaf2448daee0c289f5039e94d42a56787e60e8 100644 (file)
@@ -20,10 +20,8 @@ written in C and documented at
 Adepts of the original yacc 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 file expr.y in this directory is a yacc grammar for a very simple
+expression parser.  It needs the flag "-p expr" (see below).
 
 The generated parser is reentrant. Parse expects to be given an
 argument that conforms to the following interface:
diff --git a/src/cmd/yacc/expr.y b/src/cmd/yacc/expr.y
new file mode 100644 (file)
index 0000000..3afffe7
--- /dev/null
@@ -0,0 +1,205 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// This is an example of a goyacc program.
+// To build it:
+// go tool yacc -p "expr" expr.y (produces y.go)
+// go build -o expr y.go
+// expr
+// > <type an expression>
+
+%{
+
+// This tag will be copied to the generated file to prevent that file
+// confusing a future build.
+
+// +build ignore
+
+package main
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       "io"
+       "log"
+       "math/big"
+       "os"
+       "unicode/utf8"
+)
+
+%}
+
+%union {
+       num *big.Rat
+}
+
+%type  <num>   expr expr1 expr2 expr3
+
+%token <num>   NUM
+
+%%
+
+top:
+       expr
+       {
+               if $1.IsInt() {
+                       fmt.Println($1.Num().String())
+               } else {
+                       fmt.Println($1.String())
+               }
+       }
+
+expr:
+       expr1
+|      '+' expr
+       {
+               $$ = $2
+       }
+|      '-' expr
+       {
+               $$.Neg($2)
+       }
+
+expr1:
+       expr2
+|      expr1 '+' expr2
+       {
+               $$.Add($1, $3)
+       }
+|      expr1 '-' expr2
+       {
+               $$.Sub($1, $3)
+       }
+
+expr2:
+       expr3
+|      expr2 '*' expr3
+       {
+               $$.Mul($1, $3)
+       }
+|      expr2 '/' expr3
+       {
+               $$.Quo($1, $3)
+       }
+
+expr3:
+       NUM
+|      '(' expr ')'
+       {
+               $$ = $2
+       }
+
+
+%%
+
+// The parser expects the lexer to return 0 on EOF.  Give it a name
+// for clarity.
+const eof = 0
+
+// The parser uses the type <prefix>Lex as a lexer.  It must provide
+// the methods Lex(*<prefix>SymType) int and Error(string).
+type exprLex struct {
+       line []byte
+       peek rune
+}
+
+// The parser calls this method to get each new token.  This
+// implementation returns operators and NUM.
+func (x *exprLex) Lex(yylval *exprSymType) int {
+       for {
+               c := x.next()
+               switch c {
+               case eof:
+                       return eof
+               case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+                       return x.num(c, yylval)
+               case '+', '-', '*', '/', '(', ')':
+                       return int(c)
+
+               // Recognize Unicode multiplication and division
+               // symbols, returning what the parser expects.
+               case '×':
+                       return '*'
+               case '÷':
+                       return '/'
+
+               case ' ', '\t', '\n':
+               default:
+                       log.Printf("unrecognized character %q", c)
+               }
+       }
+}
+
+// Lex a number.
+func (x *exprLex) num(c rune, yylval *exprSymType) int {
+       add := func(b *bytes.Buffer, c rune) {
+               if _, err := b.WriteRune(c); err != nil {
+                       log.Fatalf("WriteRune: %s", err)
+               }
+       }
+       var b bytes.Buffer
+       add(&b, c)
+       L: for {
+               c = x.next()
+               switch c {
+               case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'e', 'E':
+                       add(&b, c)
+               default:
+                       break L
+               }
+       }
+       if c != eof {
+               x.peek = c
+       }
+       yylval.num = &big.Rat{}
+       _, ok := yylval.num.SetString(b.String())
+       if !ok {
+               log.Printf("bad number %q", b.String())
+               return eof
+       }
+       return NUM
+}
+
+// Return the next rune for the lexer.
+func (x *exprLex) next() rune {
+       if x.peek != eof {
+               r := x.peek
+               x.peek = eof
+               return r
+       }
+       if len(x.line) == 0 {
+               return eof
+       }
+       c, size := utf8.DecodeRune(x.line)
+       x.line = x.line[size:]
+       if c == utf8.RuneError && size == 1 {
+               log.Print("invalid utf8")
+               return x.next()
+       }
+       return c
+}
+
+// The parser calls this method on a parse error.
+func (x *exprLex) Error(s string) {
+       log.Printf("parse error: %s", s)
+}
+
+func main() {
+       in := bufio.NewReader(os.Stdin)
+       for {
+               if _, err := os.Stdout.WriteString("> "); err != nil {
+                       log.Fatalf("WriteString: %s", err)
+               }
+               line, err := in.ReadBytes('\n')
+               if err == io.EOF {
+                       return
+               }
+               if err != nil {
+                       log.Fatalf("ReadBytes: %s", err)
+               }
+
+               exprParse(&exprLex{line: line})
+       }
+}
diff --git a/src/cmd/yacc/units.txt b/src/cmd/yacc/units.txt
deleted file mode 100644 (file)
index 7df2371..0000000
+++ /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
-/ Wed Aug 29, 2012
-
-argentinapeso                  $ 0.2160
-australiadollar                        $ 1.0372
-boliviaboliviano               $ 0.1427
-brazilreal                     $ 0.4872
-britainpound                   $ 1.5843
-canadadollar                   $ 1.0117
-chilepeso                      $ 1 | 480.6
-chinayuan                      $ 0.1574
-colombiapeso                   $ 1 | 1834
-czechkoruna                    $ 0.0506
-denmarkkrone                   $ 0.1681
-dominicanpeso                  $ 0.0256
-egyptpound                     $ 0.1640
-elsalvadorcolon                        $ 1 | 8.75
-europeuro                      $ 1.2528
-guatemalaquetzal               $ 0.1290
-honduraslempira                        $ 0.0511
-hongkongdollar                 $ 0.1289
-hungaryforint                  $ 1 | 226.5
-indiarupee                     $ 0.0180
-indonesiarupiah                        $ 1 | 9540
-israelshekel                   $ 0.2479
-japanyen                       $ 0.0127
-kenyashilling                  $ 0.0119
-kuwaitdinar                    $ 3.5456
-lebanonpound                   $ 1 | 1505.5
-malaysiaringgit                        $ 0.3204
-mexicopeso                     $ 0.0754
-newzealanddollar               $ 0.8035
-nicaraguacordoba               $ 0.0421
-norwaykrone                    $ 0.1717
-pakistanrupee                  $ 0.0106
-paraguayguarani                        $ 1 | 4415
-perunewsol                     $ 0.3832
-philippinespeso                        $ 0.0236
-polandzloty                    $ 0.3001
-russiaruble                    $ 0.0311
-saudiarabiariyal               $ 1 | 3.75
-singaporedollar                        $ 0.7976
-slovakkoruna                   1 | 30.126 europeuro
-southafricarand                        $ 0.1188
-southkoreawon                  $ 1 | 1135
-swedenkrona                    $ 0.1502
-switzerlandfranc               $ 1.0431
-taiwandollar                   $ 0.0334
-thailandbaht                   $ 0.0319
-turkeynewlira                  $ 0.5504
-uaedirham                      $ 0.2723
-uruguaynewpeso                 $ 0.0465
-vietnamdong                    $ 1 | 20865
-
-/ END MONEY
-€                    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
-millennium             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/yacc/units.y b/src/cmd/yacc/units.y
deleted file mode 100644 (file)
index 9c1b0b3..0000000
+++ /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
-}