--- /dev/null
+// 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})
+ }
+}
+++ /dev/null
-/ 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
+++ /dev/null
-// 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
-}