]> Cypherpunks repositories - gostls13.git/commitdiff
sample goyacc program
authorKen Thompson <ken@golang.org>
Thu, 10 Sep 2009 20:53:35 +0000 (13:53 -0700)
committerKen Thompson <ken@golang.org>
Thu, 10 Sep 2009 20:53:35 +0000 (13:53 -0700)
R=rsc
OCL=34526
CL=34526

src/cmd/goyacc/units [new file with mode: 0644]
src/cmd/goyacc/units.y [new file with mode: 0644]

diff --git a/src/cmd/goyacc/units b/src/cmd/goyacc/units
new file mode 100644 (file)
index 0000000..bee3649
--- /dev/null
@@ -0,0 +1,604 @@
+/ 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
+/ Fri Oct 27 15:52:13 EDT 2000
+
+/ MONEY START
+argentpeso             1 | .9998 $
+australiadollar                1 | 1.9175 $
+brazilreal             1 | 1.9300 $
+britainpound           1 | .6972 $
+canadadollar           1 | 1.5237 $
+chilepeso              1 | 576.45 $
+chinayuan              1 | 8.2782 $
+colombiapeso           1 | 2165.00 $
+czechrepkoruna         1 | 42.11 $
+denmarkkrone           1 | 9.0134 $
+dominicanpeso          1 | 16.00 $
+egyptpound             1 | 3.6750 $
+euro                   1 | 1.08863 $
+hongkongdollar         1 | 7.7991 $
+hungaryforint          1 | 317.59 $
+indiarupee             1 | 46.600 $
+indnsiarupiah          1 | 9025.00 $
+israelshekel           1 | 4.1450 $
+japanyen               1 | 108.34 $
+jordandinar            1 | .71098 $
+lebanonpound           1 | 1514.00 $
+malaysiaringgit                1 | 3.7996 $
+mexicopeso             1 | 9.6850 $
+newzealanddollar       1 | 2.4938 $
+norwaykrone            1 | 9.5940 $
+pakistanrupee          1 | 57.75 $
+perunewsol             1 | 3.510 $
+philpinspeso           1 | 50.10 $
+polandzloty            1 | 4.70 $
+russiaruble            1 | 27.9200 $
+sdr                    1 | .7841 $
+saudiarabriyal         1 | 3.7508 $
+singaporedollar                1 | 1.7546 $
+slovakrepkoruna                1 | 52.65 $
+southafricarand                1 | 7.6725 $
+southkoreawon          1 | 1137.20 $
+swedenkrona            1 | 10.2621 $
+switzerlndfranc                1 | 1.8195 $
+taiwandollar           1 | 32.09 $
+thailandbaht           1 | 43.58 $
+turkeylira             1 | 687860 $
+uaedirham              1 | 3.6728 $
+uruguaynewpeso         1 | 12.4180 $
+venezuelabolivar       1 | 693.2500 $
+/ MONEY END
+
+€                    euro
+£                     britainpound
+¥                     japanyen
+dollar                 $
+
+bef                    1 | 40.3399 €
+belgiumfranc   bef
+dem                    1 | 1.95583 €
+germanymark    dem
+grd                    1 | 340.750 €
+greecedrachma  grd
+esp                    1 | 166.386 €
+spainpeseta            esp
+frf                    1 | 6.55957 €
+francefranc    frf
+iep                    1 | .787564 €
+irelandpunt    iep
+itl                    1 | 1936.27 €
+italylira              itl
+luf                    1 | 40.3399 €
+luxembourgfranc        luf
+nlg                    1 | 2.20371 €
+netherlandsguilder     nlg
+ats                    1 | 13.7603 €
+austriaschilling       ats
+pte                    1 | 200.482 €
+portugalescudo pte
+fim                    1 | 5.94573 €
+finlandmark    fim
+
+baht                   thailandbaht
+bolivar                        venezuelabolivar
+brpound                        britainpound
+dinar                  jordandinar
+dirham                 uaedirham
+drachma                        greecedrachma
+escudo                 portugalescudo
+forint                 hungaryforint
+franc                  francefranc
+guilder                        netherlandsguilder
+krona                  swedenkrona
+lira                   italylira
+mark                   germanymark
+peseta                 spainpeseta
+peso                   mexicopeso
+punt                   irelandpunt
+rand                   southafricarand
+real                   brazilreal
+yuan                   chinayuan
+ringgit                        malaysiaringgit
+riyal                  saudiarabriyal
+ruble                  russiaruble
+rupee                  indiarupee
+rupiah                 indnsiarupiah
+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
new file mode 100644 (file)
index 0000000..a5510fb
--- /dev/null
@@ -0,0 +1,802 @@
+// 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
+
+%{
+
+// 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:
+
+import
+(
+       "flag";
+       "io";
+       "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 {
+                       Error("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 {
+                       Error("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 {
+                       Error("undefined %v", $1.name);
+                       $$ = one;
+               } else
+                       $$ = $1.node;
+       }
+|      VAL
+       {
+               $$ = one;
+               $$.vval = $1;
+       }
+|      '(' expr ')'
+       {
+               $$ = $2;
+       }
+%%
+
+func
+Lex() 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", sym);
+               f = 0;
+       }
+       yylval.vval = f;
+       return VAL;
+}
+
+func
+main()
+{
+       var file string;
+
+       flag.BoolVar(&vflag, "v", false, "verbose");
+
+       flag.Parse();
+
+       file = "units";
+       if flag.NArg() > 0 {
+               file = flag.Arg(0);
+       }
+
+       f,err := os.Open(file, os.O_RDONLY, 0);
+       if err != nil {
+               fmt.Printf("error opening %v: %v", 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 = ':';
+               Parse();
+       }
+
+       /*
+        * 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;
+               Parse();
+               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
+Error(s string, v ...)
+{
+
+       /*
+        * hack to intercept message from yaccpar
+        */
+       if s == "syntax error" {
+               Error("syntax error, last name: %v", sym);
+               return;
+       }
+       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
+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
+       Prefix { 1e-24,         "yocto" },
+       Prefix { 1e-21,         "zepto" },
+       Prefix { 1e-18,         "atto"  },
+       Prefix { 1e-15,         "femto" },
+       Prefix { 1e-12,         "pico"  },
+       Prefix { 1e-9,          "nano"  },
+       Prefix { 1e-6,          "micro" },
+       Prefix { 1e-6,          "μ"     },
+       Prefix { 1e-3,          "milli" },
+       Prefix { 1e-2,          "centi" },
+       Prefix { 1e-1,          "deci"  },
+       Prefix { 1e1,           "deka"  },
+       Prefix { 1e2,           "hecta" },
+       Prefix { 1e2,           "hecto" },
+       Prefix { 1e3,           "kilo"  },
+       Prefix { 1e6,           "mega"  },
+       Prefix { 1e6,           "meg"   },
+       Prefix { 1e9,           "giga"  },
+       Prefix { 1e12,          "tera"  },
+       Prefix { 1e15,          "peta"  },
+       Prefix { 1e18,          "exa"   },
+       Prefix { 1e21,          "zetta" },
+       Prefix { 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 {
+                       Error("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;
+}