Commit 61f27d3c authored by Ken Thompson's avatar Ken Thompson

sample goyacc program

R=rsc
OCL=34526
CL=34526
parent 757fe32f
/ 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
// 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment