mirror of
https://github.com/golang/go
synced 2024-11-24 21:10:04 -07:00
Change goyacc to be reentrant.
Instead of calling the package scope Lex function, Parse now takes an argument which is used to do the lexing. I reverted to having the generated switch code inside Parse rather than a separate function because the function needs 7 arguments or a context structure, which seems unnecessary. I used yyrun(), not the original $A so that it's possible to run the backquoted code through gofmt. R=rsc, ken2, ken3 CC=golang-dev https://golang.org/cl/879041
This commit is contained in:
parent
29c6c09f71
commit
6c3befc824
@ -19,5 +19,18 @@ 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.
|
||||
|
||||
The generated parser is reentrant. Parse expects to be given an
|
||||
argument that conforms to the following interface:
|
||||
|
||||
type yyLexer interface {
|
||||
Lex(lval *yySymType) int
|
||||
}
|
||||
|
||||
Lex should return the token identifier, and place other token
|
||||
information in lval (which replaces the usual yylval).
|
||||
|
||||
Code inside the parser may refer to the variable yylex
|
||||
which holds the yyLexer passed to Parse.
|
||||
|
||||
*/
|
||||
package documentation
|
||||
|
@ -49,6 +49,8 @@ import (
|
||||
"fmt"
|
||||
"bufio"
|
||||
"os"
|
||||
"strings"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
// the following are adjustable
|
||||
@ -104,7 +106,7 @@ const (
|
||||
)
|
||||
|
||||
// output parser flags
|
||||
const YYFLAG = -1000
|
||||
const yyFlag = -1000
|
||||
|
||||
// parse tokens
|
||||
const (
|
||||
@ -147,8 +149,9 @@ func SETTYPE(i, j int) int { return i | (j << 10) }
|
||||
// I/O descriptors
|
||||
var finput *bufio.Reader // input file
|
||||
var stderr *bufio.Writer
|
||||
var ftable *bufio.Writer // y.go file
|
||||
var foutput *bufio.Writer // y.output file
|
||||
var ftable *bufio.Writer // y.go file
|
||||
var fcode = &bytes.Buffer{} // saved code
|
||||
var foutput *bufio.Writer // y.output file
|
||||
|
||||
var oflag string // -o [y.go] - y.go file
|
||||
var vflag string // -v [y.output] - y.output file
|
||||
@ -503,22 +506,20 @@ outer:
|
||||
}
|
||||
|
||||
// put out names of token names
|
||||
fmt.Fprintf(ftable, "var\tToknames\t =[]string {\n")
|
||||
fmt.Fprintf(ftable, "var\tyyToknames\t =[]string {\n")
|
||||
for i := TOKSTART; i <= ntokens; i++ {
|
||||
fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name)
|
||||
}
|
||||
fmt.Fprintf(ftable, "}\n")
|
||||
|
||||
// put out names of state names
|
||||
fmt.Fprintf(ftable, "var\tStatenames\t =[]string {\n")
|
||||
fmt.Fprintf(ftable, "var\tyyStatenames\t =[]string {\n")
|
||||
// for i:=TOKSTART; i<=ntokens; i++ {
|
||||
// fmt.Fprintf(ftable, "\t\"%v\",\n", tokset[i].name);
|
||||
// }
|
||||
fmt.Fprintf(ftable, "}\n")
|
||||
|
||||
fmt.Fprintf(ftable, "\nfunc\n")
|
||||
fmt.Fprintf(ftable, "yyrun(p int, yypt int) {\n")
|
||||
fmt.Fprintf(ftable, "switch p {\n")
|
||||
fmt.Fprintf(fcode, "switch yynt {\n")
|
||||
|
||||
moreprod()
|
||||
prdptr[0] = []int{NTBASE, start, 1, 0}
|
||||
@ -589,7 +590,7 @@ outer:
|
||||
break
|
||||
}
|
||||
levprd[nprod] |= ACTFLAG
|
||||
fmt.Fprintf(ftable, "\ncase %v:", nprod)
|
||||
fmt.Fprintf(fcode, "\ncase %v:", nprod)
|
||||
cpyact(curprod, mem)
|
||||
|
||||
// action within rule...
|
||||
@ -646,8 +647,8 @@ outer:
|
||||
if tempty != nontrst[curprod[0]-NTBASE].value {
|
||||
error("default action causes potential type clash")
|
||||
}
|
||||
fmt.Fprintf(ftable, "\ncase %v:", nprod)
|
||||
fmt.Fprintf(ftable, "\n\tYYVAL.%v = YYS[yypt-0].%v;",
|
||||
fmt.Fprintf(fcode, "\ncase %v:", nprod)
|
||||
fmt.Fprintf(fcode, "\n\tYYVAL.%v = YYS[yypt-0].%v;",
|
||||
typeset[tempty], typeset[tempty])
|
||||
}
|
||||
moreprod()
|
||||
@ -663,12 +664,11 @@ outer:
|
||||
// dump out the prefix code
|
||||
//
|
||||
|
||||
fmt.Fprintf(ftable, "\n\t}")
|
||||
fmt.Fprintf(ftable, "\n}\n")
|
||||
fmt.Fprintf(fcode, "\n\t}")
|
||||
|
||||
fmt.Fprintf(ftable, "const YYEOFCODE = 1\n")
|
||||
fmt.Fprintf(ftable, "const YYERRCODE = 2\n")
|
||||
fmt.Fprintf(ftable, "const YYMAXDEPTH = %v\n", stacksize)
|
||||
fmt.Fprintf(ftable, "const yyEofCode = 1\n")
|
||||
fmt.Fprintf(ftable, "const yyErrCode = 2\n")
|
||||
fmt.Fprintf(ftable, "const yyMaxDepth = %v\n", stacksize)
|
||||
|
||||
//
|
||||
// copy any postfix code
|
||||
@ -682,7 +682,7 @@ outer:
|
||||
if c == EOF {
|
||||
break
|
||||
}
|
||||
putrune(ftable, c)
|
||||
ftable.WriteRune(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1034,7 +1034,7 @@ func cpyunion() {
|
||||
if !lflag {
|
||||
fmt.Fprintf(ftable, "\n//line %v %v\n", lineno, infile)
|
||||
}
|
||||
fmt.Fprintf(ftable, "type\tYYSTYPE\tstruct")
|
||||
fmt.Fprintf(ftable, "type\tyySymType\tstruct")
|
||||
|
||||
level := 0
|
||||
|
||||
@ -1044,7 +1044,7 @@ out:
|
||||
if c == EOF {
|
||||
error("EOF encountered while processing %%union")
|
||||
}
|
||||
putrune(ftable, c)
|
||||
ftable.WriteRune(c)
|
||||
switch c {
|
||||
case '\n':
|
||||
lineno++
|
||||
@ -1061,9 +1061,6 @@ out:
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(ftable, "\n")
|
||||
fmt.Fprintf(ftable, "var\tyylval\tYYSTYPE\n")
|
||||
fmt.Fprintf(ftable, "var\tYYVAL\tYYSTYPE\n")
|
||||
fmt.Fprintf(ftable, "var\tYYS\t[%v]YYSTYPE\n", stacksize)
|
||||
}
|
||||
|
||||
//
|
||||
@ -1086,9 +1083,9 @@ func cpycode() {
|
||||
if c == '}' {
|
||||
return
|
||||
}
|
||||
putrune(ftable, '%')
|
||||
ftable.WriteRune('%')
|
||||
}
|
||||
putrune(ftable, c)
|
||||
ftable.WriteRune(c)
|
||||
if c == '\n' {
|
||||
lineno++
|
||||
}
|
||||
@ -1098,74 +1095,6 @@ func cpycode() {
|
||||
error("eof before %%}")
|
||||
}
|
||||
|
||||
//func
|
||||
//addcode(k int, s string)
|
||||
//{
|
||||
// for i := 0; i < len(s); i++ {
|
||||
// addcodec(k, int(s[i]));
|
||||
// }
|
||||
//}
|
||||
|
||||
//func
|
||||
//addcodec(k, c int)
|
||||
//{
|
||||
// if codehead == nil || k != codetail.kind || codetail.ndata >= NCode {
|
||||
// cd := new(Code);
|
||||
// cd.kind = k;
|
||||
// cd.data = make([]byte, NCode+UTFmax);
|
||||
// cd.ndata = 0;
|
||||
// cd.next = nil;
|
||||
//
|
||||
// if codehead == nil {
|
||||
// codehead = cd;
|
||||
// } else
|
||||
// codetail.next = cd;
|
||||
// codetail = cd;
|
||||
// }
|
||||
//
|
||||
////!! codetail.ndata += sys->char2byte(c, codetail.data, codetail.ndata);
|
||||
//}
|
||||
|
||||
//func
|
||||
//dumpcode(til int)
|
||||
//{
|
||||
// for ; codehead != nil; codehead = codehead.next {
|
||||
// if codehead.kind == til {
|
||||
// return;
|
||||
// }
|
||||
// if write(ftable, codehead.data, codehead.ndata) != codehead.ndata {
|
||||
// error("can't write output file");
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//
|
||||
// write out the module declaration and any token info
|
||||
//
|
||||
//func
|
||||
//dumpmod()
|
||||
//{
|
||||
//
|
||||
// for ; codehead != nil; codehead = codehead.next {
|
||||
// if codehead.kind != CodeMod {
|
||||
// break;
|
||||
// }
|
||||
// if write(ftable, codehead.data, codehead.ndata) != codehead.ndata {
|
||||
// error("can't write output file");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// for i:=TOKSTART; i<=ntokens; i++ {
|
||||
// // non-literals
|
||||
// c := tokset[i].name[0];
|
||||
// if c != ' ' && c != '$' {
|
||||
// fmt.Fprintf(ftable, "vonst %v %v\n",
|
||||
// tokset[i].name, tokset[i].value);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
|
||||
//
|
||||
// skip over comments
|
||||
// skipcom is called after reading a '/'
|
||||
@ -1229,7 +1158,7 @@ func dumpprod(curprod []int, max int) {
|
||||
func cpyact(curprod []int, max int) {
|
||||
|
||||
if !lflag {
|
||||
fmt.Fprintf(ftable, "\n//line %v %v\n", lineno, infile)
|
||||
fmt.Fprintf(fcode, "\n//line %v %v\n", lineno, infile)
|
||||
}
|
||||
|
||||
lno := lineno
|
||||
@ -1243,14 +1172,14 @@ loop:
|
||||
switch c {
|
||||
case ';':
|
||||
if brac == 0 {
|
||||
putrune(ftable, c)
|
||||
ftable.WriteRune(c)
|
||||
return
|
||||
}
|
||||
|
||||
case '{':
|
||||
if brac == 0 {
|
||||
}
|
||||
putrune(ftable, '\t')
|
||||
ftable.WriteRune('\t')
|
||||
brac++
|
||||
|
||||
case '$':
|
||||
@ -1268,14 +1197,14 @@ loop:
|
||||
c = getrune(finput)
|
||||
}
|
||||
if c == '$' {
|
||||
fmt.Fprintf(ftable, "YYVAL")
|
||||
fmt.Fprintf(fcode, "YYVAL")
|
||||
|
||||
// put out the proper tag...
|
||||
if ntypes != 0 {
|
||||
if tok < 0 {
|
||||
tok = fdtype(curprod[0])
|
||||
}
|
||||
fmt.Fprintf(ftable, ".%v", typeset[tok])
|
||||
fmt.Fprintf(fcode, ".%v", typeset[tok])
|
||||
}
|
||||
continue loop
|
||||
}
|
||||
@ -1322,14 +1251,14 @@ loop:
|
||||
error("$name or $name@number not found")
|
||||
}
|
||||
} else {
|
||||
putrune(ftable, '$')
|
||||
fcode.WriteRune('$')
|
||||
if s < 0 {
|
||||
putrune(ftable, '-')
|
||||
fcode.WriteRune('-')
|
||||
}
|
||||
ungetrune(finput, c)
|
||||
continue loop
|
||||
}
|
||||
fmt.Fprintf(ftable, "YYS[yypt-%v]", max-j-1)
|
||||
fmt.Fprintf(fcode, "YYS[yypt-%v]", max-j-1)
|
||||
|
||||
// put out the proper tag
|
||||
if ntypes != 0 {
|
||||
@ -1339,7 +1268,7 @@ loop:
|
||||
if tok < 0 {
|
||||
tok = fdtype(curprod[j])
|
||||
}
|
||||
fmt.Fprintf(ftable, ".%v", typeset[tok])
|
||||
fmt.Fprintf(fcode, ".%v", typeset[tok])
|
||||
}
|
||||
continue loop
|
||||
|
||||
@ -1348,7 +1277,7 @@ loop:
|
||||
if brac != 0 {
|
||||
break
|
||||
}
|
||||
putrune(ftable, c)
|
||||
fcode.WriteRune(c)
|
||||
return
|
||||
|
||||
case '/':
|
||||
@ -1358,8 +1287,8 @@ loop:
|
||||
break
|
||||
}
|
||||
// a comment
|
||||
putrune(ftable, c)
|
||||
putrune(ftable, nc)
|
||||
fcode.WriteRune(c)
|
||||
fcode.WriteRune(nc)
|
||||
c = getrune(finput)
|
||||
for c != EOF {
|
||||
switch {
|
||||
@ -1371,14 +1300,14 @@ loop:
|
||||
case c == '*' && nc == '*': // end of /* comment?
|
||||
nnc := getrune(finput)
|
||||
if nnc == '/' {
|
||||
putrune(ftable, '*')
|
||||
putrune(ftable, '/')
|
||||
fcode.WriteRune('*')
|
||||
fcode.WriteRune('/')
|
||||
c = getrune(finput)
|
||||
break swt
|
||||
}
|
||||
ungetrune(finput, nnc)
|
||||
}
|
||||
putrune(ftable, c)
|
||||
fcode.WriteRune(c)
|
||||
c = getrune(finput)
|
||||
}
|
||||
error("EOF inside comment")
|
||||
@ -1386,11 +1315,11 @@ loop:
|
||||
case '\'', '"':
|
||||
// character string or constant
|
||||
match := c
|
||||
putrune(ftable, c)
|
||||
fcode.WriteRune(c)
|
||||
c = getrune(finput)
|
||||
for c != EOF {
|
||||
if c == '\\' {
|
||||
putrune(ftable, c)
|
||||
fcode.WriteRune(c)
|
||||
c = getrune(finput)
|
||||
if c == '\n' {
|
||||
lineno++
|
||||
@ -1401,7 +1330,7 @@ loop:
|
||||
if c == '\n' {
|
||||
error("newline in string or char const")
|
||||
}
|
||||
putrune(ftable, c)
|
||||
fcode.WriteRune(c)
|
||||
c = getrune(finput)
|
||||
}
|
||||
error("EOF in string or character constant")
|
||||
@ -1414,7 +1343,7 @@ loop:
|
||||
lineno++
|
||||
}
|
||||
|
||||
putrune(ftable, c)
|
||||
fcode.WriteRune(c)
|
||||
}
|
||||
}
|
||||
|
||||
@ -2137,7 +2066,7 @@ nextk:
|
||||
func output() {
|
||||
var c, u, v int
|
||||
|
||||
fmt.Fprintf(ftable, "var\tYYEXCA = []int {\n")
|
||||
fmt.Fprintf(ftable, "var\tyyExca = []int {\n")
|
||||
|
||||
noset := mkset()
|
||||
|
||||
@ -2210,10 +2139,10 @@ func output() {
|
||||
}
|
||||
|
||||
fmt.Fprintf(ftable, "}\n")
|
||||
fmt.Fprintf(ftable, "const\tYYNPROD\t= %v\n", nprod)
|
||||
fmt.Fprintf(ftable, "const\tYYPRIVATE\t= %v\n", PRIVATE)
|
||||
fmt.Fprintf(ftable, "var\tYYTOKENNAMES []string\n")
|
||||
fmt.Fprintf(ftable, "var\tYYSTATES []string\n")
|
||||
fmt.Fprintf(ftable, "const\tyyNprod\t= %v\n", nprod)
|
||||
fmt.Fprintf(ftable, "const\tyyPrivate\t= %v\n", PRIVATE)
|
||||
fmt.Fprintf(ftable, "var\tyyTokenNames []string\n")
|
||||
fmt.Fprintf(ftable, "var\tyyStates []string\n")
|
||||
}
|
||||
|
||||
//
|
||||
@ -2616,7 +2545,7 @@ func callopt() {
|
||||
if tystate[i] == 0 && adb > 1 {
|
||||
fmt.Fprintf(ftable, "State %v: null\n", i)
|
||||
}
|
||||
indgo[i] = YYFLAG
|
||||
indgo[i] = yyFlag
|
||||
}
|
||||
|
||||
i = nxti()
|
||||
@ -2636,7 +2565,7 @@ func callopt() {
|
||||
for i = 0; i < 10; i++ {
|
||||
fmt.Fprintf(ftable, "%v ", amem[p+i])
|
||||
}
|
||||
putrune(ftable, '\n')
|
||||
ftable.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
||||
@ -2788,10 +2717,10 @@ nextn:
|
||||
// write out the optimized parser
|
||||
//
|
||||
func aoutput() {
|
||||
fmt.Fprintf(ftable, "const\tYYLAST\t= %v\n", maxa+1)
|
||||
arout("YYACT", amem, maxa+1)
|
||||
arout("YYPACT", indgo, nstate)
|
||||
arout("YYPGO", pgo, nnonter+1)
|
||||
fmt.Fprintf(ftable, "const\tyyLast\t= %v\n", maxa+1)
|
||||
arout("yyAct", amem, maxa+1)
|
||||
arout("yyPact", indgo, nstate)
|
||||
arout("yyPgo", pgo, nnonter+1)
|
||||
}
|
||||
|
||||
//
|
||||
@ -2800,7 +2729,7 @@ func aoutput() {
|
||||
func others() {
|
||||
var i, j int
|
||||
|
||||
arout("YYR1", levprd, nprod)
|
||||
arout("yyR1", levprd, nprod)
|
||||
aryfil(temp1, nprod, 0)
|
||||
|
||||
//
|
||||
@ -2809,7 +2738,7 @@ func others() {
|
||||
for i = 1; i < nprod; i++ {
|
||||
temp1[i] = len(prdptr[i]) - 2
|
||||
}
|
||||
arout("YYR2", temp1, nprod)
|
||||
arout("yyR2", temp1, nprod)
|
||||
|
||||
aryfil(temp1, nstate, -1000)
|
||||
for i = 0; i <= ntokens; i++ {
|
||||
@ -2822,8 +2751,8 @@ func others() {
|
||||
temp1[j] = -i
|
||||
}
|
||||
}
|
||||
arout("YYCHK", temp1, nstate)
|
||||
arout("YYDEF", defact, nstate)
|
||||
arout("yyChk", temp1, nstate)
|
||||
arout("yyDef", defact, nstate)
|
||||
|
||||
// put out token translation tables
|
||||
// table 1 has 0-256
|
||||
@ -2848,7 +2777,7 @@ func others() {
|
||||
temp1[i] = YYLEXUNK
|
||||
}
|
||||
}
|
||||
arout("YYTOK1", temp1, c+1)
|
||||
arout("yyTok1", temp1, c+1)
|
||||
|
||||
// table 2 has PRIVATE-PRIVATE+256
|
||||
aryfil(temp1, 256, 0)
|
||||
@ -2867,10 +2796,10 @@ func others() {
|
||||
}
|
||||
}
|
||||
}
|
||||
arout("YYTOK2", temp1, c+1)
|
||||
arout("yyTok2", temp1, c+1)
|
||||
|
||||
// table 3 has everything else
|
||||
fmt.Fprintf(ftable, "var\tYYTOK3\t= []int {\n")
|
||||
fmt.Fprintf(ftable, "var\tyyTok3\t= []int {\n")
|
||||
c = 0
|
||||
for i = 1; i <= ntokens; i++ {
|
||||
j = tokset[i].value
|
||||
@ -2884,7 +2813,7 @@ func others() {
|
||||
fmt.Fprintf(ftable, "%4d,%4d,", j, i)
|
||||
c++
|
||||
if c%5 == 0 {
|
||||
putrune(ftable, '\n')
|
||||
ftable.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(ftable, "%4d,\n };\n", 0)
|
||||
@ -2892,22 +2821,25 @@ func others() {
|
||||
// copy parser text
|
||||
c = getrune(finput)
|
||||
for c != EOF {
|
||||
putrune(ftable, c)
|
||||
ftable.WriteRune(c)
|
||||
c = getrune(finput)
|
||||
}
|
||||
|
||||
parts := strings.Split(yaccpar, "yyrun()", 2)
|
||||
// copy yaccpar
|
||||
fmt.Fprintf(ftable, "%v", yaccpar)
|
||||
fmt.Fprintf(ftable, "%v", parts[0])
|
||||
ftable.Write(fcode.Bytes())
|
||||
fmt.Fprintf(ftable, "%v", parts[1])
|
||||
}
|
||||
|
||||
func arout(s string, v []int, n int) {
|
||||
fmt.Fprintf(ftable, "var\t%v\t= []int {\n", s)
|
||||
for i := 0; i < n; i++ {
|
||||
if i%10 == 0 {
|
||||
putrune(ftable, '\n')
|
||||
ftable.WriteRune('\n')
|
||||
}
|
||||
fmt.Fprintf(ftable, "%4d", v[i])
|
||||
putrune(ftable, ',')
|
||||
ftable.WriteRune(',')
|
||||
}
|
||||
fmt.Fprintf(ftable, "\n};\n")
|
||||
}
|
||||
@ -2978,7 +2910,7 @@ func chcopy(q string) string {
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(stderr, "usage: gacc [-o output] [-v parsetable] input\n")
|
||||
fmt.Fprintf(stderr, "usage: goyacc [-o output] [-v parsetable] input\n")
|
||||
exit(1)
|
||||
}
|
||||
|
||||
@ -3144,224 +3076,228 @@ func exit(status int) {
|
||||
var yaccpar = `
|
||||
/* parser for yacc output */
|
||||
|
||||
var Nerrs = 0 /* number of errors */
|
||||
var Errflag = 0 /* error recovery flag */
|
||||
var Debug = 0
|
||||
const YYFLAG = -1000
|
||||
var yyDebug = 0
|
||||
|
||||
func
|
||||
Tokname(yyc int) string {
|
||||
if yyc > 0 && yyc <= len(Toknames) {
|
||||
if Toknames[yyc-1] != "" {
|
||||
return Toknames[yyc-1];
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("tok-%v", yyc);
|
||||
type yyLexer interface {
|
||||
Lex(lval *yySymType) int
|
||||
}
|
||||
|
||||
func
|
||||
Statname(yys int) string {
|
||||
if yys >= 0 && yys < len(Statenames) {
|
||||
if Statenames[yys] != "" {
|
||||
return Statenames[yys];
|
||||
const yyFlag = -1000
|
||||
|
||||
func yyTokname(yyc int) string {
|
||||
if yyc > 0 && yyc <= len(yyToknames) {
|
||||
if yyToknames[yyc-1] != "" {
|
||||
return yyToknames[yyc-1]
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("state-%v", yys);
|
||||
return fmt.Sprintf("tok-%v", yyc)
|
||||
}
|
||||
|
||||
func
|
||||
lex1() int {
|
||||
var yychar int;
|
||||
var c int;
|
||||
func yyStatname(yys int) string {
|
||||
if yys >= 0 && yys < len(yyStatenames) {
|
||||
if yyStatenames[yys] != "" {
|
||||
return yyStatenames[yys]
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("state-%v", yys)
|
||||
}
|
||||
|
||||
yychar = Lex();
|
||||
func yylex1(yylex yyLexer, lval *yySymType) int {
|
||||
var yychar int
|
||||
var c int
|
||||
|
||||
yychar = yylex.Lex(lval)
|
||||
if yychar <= 0 {
|
||||
c = YYTOK1[0];
|
||||
goto out;
|
||||
c = yyTok1[0]
|
||||
goto out
|
||||
}
|
||||
if yychar < len(YYTOK1) {
|
||||
c = YYTOK1[yychar];
|
||||
goto out;
|
||||
if yychar < len(yyTok1) {
|
||||
c = yyTok1[yychar]
|
||||
goto out
|
||||
}
|
||||
if yychar >= YYPRIVATE {
|
||||
if yychar < YYPRIVATE+len(YYTOK2) {
|
||||
c = YYTOK2[yychar-YYPRIVATE];
|
||||
goto out;
|
||||
if yychar >= yyPrivate {
|
||||
if yychar < yyPrivate+len(yyTok2) {
|
||||
c = yyTok2[yychar-yyPrivate]
|
||||
goto out
|
||||
}
|
||||
}
|
||||
for i:=0; i<len(YYTOK3); i+=2 {
|
||||
c = YYTOK3[i+0];
|
||||
for i := 0; i < len(yyTok3); i += 2 {
|
||||
c = yyTok3[i+0]
|
||||
if c == yychar {
|
||||
c = YYTOK3[i+1];
|
||||
goto out;
|
||||
c = yyTok3[i+1]
|
||||
goto out
|
||||
}
|
||||
}
|
||||
c = 0;
|
||||
c = 0
|
||||
|
||||
out:
|
||||
if c == 0 {
|
||||
c = YYTOK2[1]; /* unknown char */
|
||||
c = yyTok2[1] /* unknown char */
|
||||
}
|
||||
if Debug >= 3 {
|
||||
fmt.Printf("lex %.4lux %s\n", yychar, Tokname(c));
|
||||
if yyDebug >= 3 {
|
||||
fmt.Printf("lex %.4x %s\n", uint(yychar), yyTokname(c))
|
||||
}
|
||||
return c;
|
||||
return c
|
||||
}
|
||||
|
||||
func
|
||||
Parse() int {
|
||||
var yyj, yystate, yyn, yyg, yyxi, yyp int;
|
||||
var yychar int;
|
||||
var yypt, yynt int;
|
||||
func yyParse(yylex yyLexer) int {
|
||||
var yyn int
|
||||
var yylval yySymType
|
||||
var YYVAL yySymType
|
||||
YYS := make([]yySymType, yyMaxDepth)
|
||||
|
||||
yystate = 0;
|
||||
yychar = -1;
|
||||
Nerrs = 0;
|
||||
Errflag = 0;
|
||||
yyp = -1;
|
||||
goto yystack;
|
||||
Nerrs := 0 /* number of errors */
|
||||
Errflag := 0 /* error recovery flag */
|
||||
yystate := 0
|
||||
yychar := -1
|
||||
yyp := -1
|
||||
goto yystack
|
||||
|
||||
ret0:
|
||||
return 0;
|
||||
return 0
|
||||
|
||||
ret1:
|
||||
return 1;
|
||||
return 1
|
||||
|
||||
yystack:
|
||||
/* put a state and value onto the stack */
|
||||
if Debug >= 4 {
|
||||
fmt.Printf("char %v in %v", Tokname(yychar), Statname(yystate));
|
||||
if yyDebug >= 4 {
|
||||
fmt.Printf("char %v in %v", yyTokname(yychar), yyStatname(yystate))
|
||||
}
|
||||
|
||||
yyp++;
|
||||
yyp++
|
||||
if yyp >= len(YYS) {
|
||||
Error("yacc stack overflow");
|
||||
goto ret1;
|
||||
nyys := make([]yySymType, len(YYS)*2)
|
||||
copy(nyys, YYS)
|
||||
YYS = nyys
|
||||
}
|
||||
YYS[yyp] = YYVAL;
|
||||
YYS[yyp].yys = yystate;
|
||||
YYS[yyp] = YYVAL
|
||||
YYS[yyp].yys = yystate
|
||||
|
||||
yynewstate:
|
||||
yyn = YYPACT[yystate];
|
||||
if yyn <= YYFLAG {
|
||||
goto yydefault; /* simple state */
|
||||
yyn = yyPact[yystate]
|
||||
if yyn <= yyFlag {
|
||||
goto yydefault /* simple state */
|
||||
}
|
||||
if yychar < 0 {
|
||||
yychar = lex1();
|
||||
yychar = yylex1(yylex, &yylval)
|
||||
}
|
||||
yyn += yychar;
|
||||
if yyn < 0 || yyn >= YYLAST {
|
||||
goto yydefault;
|
||||
yyn += yychar
|
||||
if yyn < 0 || yyn >= yyLast {
|
||||
goto yydefault
|
||||
}
|
||||
yyn = YYACT[yyn];
|
||||
if YYCHK[yyn] == yychar { /* valid shift */
|
||||
yychar = -1;
|
||||
YYVAL = yylval;
|
||||
yystate = yyn;
|
||||
yyn = yyAct[yyn]
|
||||
if yyChk[yyn] == yychar { /* valid shift */
|
||||
yychar = -1
|
||||
YYVAL = yylval
|
||||
yystate = yyn
|
||||
if Errflag > 0 {
|
||||
Errflag--;
|
||||
Errflag--
|
||||
}
|
||||
goto yystack;
|
||||
goto yystack
|
||||
}
|
||||
|
||||
yydefault:
|
||||
/* default state action */
|
||||
yyn = YYDEF[yystate];
|
||||
yyn = yyDef[yystate]
|
||||
if yyn == -2 {
|
||||
if yychar < 0 {
|
||||
yychar = lex1();
|
||||
yychar = yylex1(yylex, &yylval)
|
||||
}
|
||||
|
||||
/* look through exception table */
|
||||
for yyxi=0;; yyxi+=2 {
|
||||
if YYEXCA[yyxi+0] == -1 && YYEXCA[yyxi+1] == yystate {
|
||||
break;
|
||||
yyxi := 0
|
||||
for {
|
||||
if yyExca[yyxi+0] == -1 && yyExca[yyxi+1] == yystate {
|
||||
break
|
||||
}
|
||||
yyxi += 2
|
||||
}
|
||||
for yyxi += 2;; yyxi += 2 {
|
||||
yyn = YYEXCA[yyxi+0];
|
||||
for yyxi += 2; ; yyxi += 2 {
|
||||
yyn = yyExca[yyxi+0]
|
||||
if yyn < 0 || yyn == yychar {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
yyn = YYEXCA[yyxi+1];
|
||||
yyn = yyExca[yyxi+1]
|
||||
if yyn < 0 {
|
||||
goto ret0;
|
||||
goto ret0
|
||||
}
|
||||
}
|
||||
if yyn == 0 {
|
||||
/* error ... attempt to resume parsing */
|
||||
switch Errflag {
|
||||
case 0: /* brand new error */
|
||||
Error("syntax error");
|
||||
Nerrs++;
|
||||
if Debug >= 1 {
|
||||
fmt.Printf("%s", Statname(yystate));
|
||||
fmt.Printf("saw %s\n", Tokname(yychar));
|
||||
case 0: /* brand new error */
|
||||
yyError("syntax error")
|
||||
Nerrs++
|
||||
if yyDebug >= 1 {
|
||||
fmt.Printf("%s", yyStatname(yystate))
|
||||
fmt.Printf("saw %s\n", yyTokname(yychar))
|
||||
}
|
||||
fallthrough;
|
||||
fallthrough
|
||||
|
||||
case 1,2: /* incompletely recovered error ... try again */
|
||||
Errflag = 3;
|
||||
case 1, 2: /* incompletely recovered error ... try again */
|
||||
Errflag = 3
|
||||
|
||||
/* find a state where "error" is a legal shift action */
|
||||
for yyp >= len(YYS) {
|
||||
yyn = YYPACT[YYS[yyp].yys] + YYERRCODE;
|
||||
if yyn >= 0 && yyn < YYLAST {
|
||||
yystate = YYACT[yyn]; /* simulate a shift of "error" */
|
||||
if YYCHK[yystate] == YYERRCODE {
|
||||
goto yystack;
|
||||
yyn = yyPact[YYS[yyp].yys] + yyErrCode
|
||||
if yyn >= 0 && yyn < yyLast {
|
||||
yystate = yyAct[yyn] /* simulate a shift of "error" */
|
||||
if yyChk[yystate] == yyErrCode {
|
||||
goto yystack
|
||||
}
|
||||
}
|
||||
|
||||
/* the current yyp has no shift onn "error", pop stack */
|
||||
if Debug >= 2 {
|
||||
if yyDebug >= 2 {
|
||||
fmt.Printf("error recovery pops state %d, uncovers %d\n",
|
||||
YYS[yyp].yys, YYS[yyp-1].yys );
|
||||
YYS[yyp].yys, YYS[yyp-1].yys)
|
||||
}
|
||||
yyp--;
|
||||
yyp--
|
||||
}
|
||||
/* there is no state on the stack with an error shift ... abort */
|
||||
goto ret1;
|
||||
goto ret1
|
||||
|
||||
case 3: /* no shift yet; clobber input char */
|
||||
if Debug >= 2 {
|
||||
fmt.Printf("error recovery discards %s\n", Tokname(yychar));
|
||||
case 3: /* no shift yet; clobber input char */
|
||||
if yyDebug >= 2 {
|
||||
fmt.Printf("error recovery discards %s\n", yyTokname(yychar))
|
||||
}
|
||||
if yychar == YYEOFCODE {
|
||||
goto ret1;
|
||||
if yychar == yyEofCode {
|
||||
goto ret1
|
||||
}
|
||||
yychar = -1;
|
||||
goto yynewstate; /* try again in the same state */
|
||||
yychar = -1
|
||||
goto yynewstate /* try again in the same state */
|
||||
}
|
||||
}
|
||||
|
||||
/* reduction by production yyn */
|
||||
if Debug >= 2 {
|
||||
fmt.Printf("reduce %v in:\n\t%v", yyn, Statname(yystate));
|
||||
if yyDebug >= 2 {
|
||||
fmt.Printf("reduce %v in:\n\t%v", yyn, yyStatname(yystate))
|
||||
}
|
||||
|
||||
yynt = yyn;
|
||||
yypt = yyp;
|
||||
yynt := yyn
|
||||
yypt := yyp
|
||||
_ = yypt // guard against "declared and not used"
|
||||
|
||||
yyp -= YYR2[yyn];
|
||||
YYVAL = YYS[yyp+1];
|
||||
yyp -= yyR2[yyn]
|
||||
YYVAL = YYS[yyp+1]
|
||||
|
||||
/* consult goto table to find next state */
|
||||
yyn = YYR1[yyn];
|
||||
yyg = YYPGO[yyn];
|
||||
yyj = yyg + YYS[yyp].yys + 1;
|
||||
yyn = yyR1[yyn]
|
||||
yyg := yyPgo[yyn]
|
||||
yyj := yyg + YYS[yyp].yys + 1
|
||||
|
||||
if yyj >= YYLAST {
|
||||
yystate = YYACT[yyg];
|
||||
if yyj >= yyLast {
|
||||
yystate = yyAct[yyg]
|
||||
} else {
|
||||
yystate = YYACT[yyj];
|
||||
if YYCHK[yystate] != -yyn {
|
||||
yystate = YYACT[yyg];
|
||||
yystate = yyAct[yyj]
|
||||
if yyChk[yystate] != -yyn {
|
||||
yystate = yyAct[yyg]
|
||||
}
|
||||
}
|
||||
|
||||
yyrun(yynt, yypt);
|
||||
goto yystack; /* stack new state and value */
|
||||
// dummy call; replaced with literal code
|
||||
yyrun()
|
||||
goto yystack /* stack new state and value */
|
||||
}
|
||||
`
|
||||
|
@ -23,48 +23,44 @@
|
||||
|
||||
package main
|
||||
|
||||
import
|
||||
(
|
||||
"flag";
|
||||
"fmt";
|
||||
"bufio";
|
||||
"os";
|
||||
"math";
|
||||
"strconv";
|
||||
"utf8";
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"bufio"
|
||||
"os"
|
||||
"math"
|
||||
"strconv"
|
||||
"utf8"
|
||||
)
|
||||
|
||||
const
|
||||
(
|
||||
Ndim = 15; // number of dimensions
|
||||
Maxe = 695; // log of largest number
|
||||
const (
|
||||
Ndim = 15 // number of dimensions
|
||||
Maxe = 695 // log of largest number
|
||||
)
|
||||
|
||||
type
|
||||
Node struct {
|
||||
vval float64;
|
||||
dim [Ndim]int8;
|
||||
type Node struct {
|
||||
vval float64
|
||||
dim [Ndim]int8
|
||||
}
|
||||
|
||||
type
|
||||
Var struct {
|
||||
name string;
|
||||
node Node;
|
||||
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
|
||||
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
|
||||
|
||||
%}
|
||||
|
||||
@ -217,481 +213,462 @@ expr0:
|
||||
}
|
||||
%%
|
||||
|
||||
func
|
||||
Lex() int {
|
||||
var c, i int;
|
||||
type UnitsLex int
|
||||
|
||||
c = peekrune;
|
||||
peekrune = ' ';
|
||||
func (l UnitsLex) Lex(yylval *yySymType) int {
|
||||
var c, i int
|
||||
|
||||
c = peekrune
|
||||
peekrune = ' '
|
||||
|
||||
loop:
|
||||
if (c >= '0' && c <= '9') || c == '.' {
|
||||
goto numb;
|
||||
goto numb
|
||||
}
|
||||
if ralpha(c) {
|
||||
goto alpha;
|
||||
goto alpha
|
||||
}
|
||||
switch c {
|
||||
case ' ', '\t':
|
||||
c = getrune();
|
||||
goto loop;
|
||||
c = getrune()
|
||||
goto loop
|
||||
case '×':
|
||||
return '*';
|
||||
return '*'
|
||||
case '÷':
|
||||
return '/';
|
||||
return '/'
|
||||
case '¹', 'ⁱ':
|
||||
yylval.numb = 1;
|
||||
return SUP;
|
||||
yylval.numb = 1
|
||||
return SUP
|
||||
case '²', '':
|
||||
yylval.numb = 2;
|
||||
return SUP;
|
||||
yylval.numb = 2
|
||||
return SUP
|
||||
case '³', '':
|
||||
yylval.numb = 3;
|
||||
return SUP;
|
||||
yylval.numb = 3
|
||||
return SUP
|
||||
}
|
||||
return c;
|
||||
return c
|
||||
|
||||
alpha:
|
||||
sym = "";
|
||||
for i=0;; i++ {
|
||||
sym += string(c);
|
||||
c = getrune();
|
||||
sym = ""
|
||||
for i = 0; ; i++ {
|
||||
sym += string(c)
|
||||
c = getrune()
|
||||
if !ralpha(c) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
peekrune = c;
|
||||
yylval.vvar = lookup(0);
|
||||
return VAR;
|
||||
peekrune = c
|
||||
yylval.vvar = lookup(0)
|
||||
return VAR
|
||||
|
||||
numb:
|
||||
sym = "";
|
||||
for i=0;; i++ {
|
||||
sym += string(c);
|
||||
c = getrune();
|
||||
sym = ""
|
||||
for i = 0; ; i++ {
|
||||
sym += string(c)
|
||||
c = getrune()
|
||||
if !rdigit(c) {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
peekrune = c;
|
||||
f, err := strconv.Atof64(sym);
|
||||
peekrune = c
|
||||
f, err := strconv.Atof64(sym)
|
||||
if err != nil {
|
||||
fmt.Printf("error converting %v", sym);
|
||||
f = 0;
|
||||
fmt.Printf("error converting %v\n", sym)
|
||||
f = 0
|
||||
}
|
||||
yylval.vval = f;
|
||||
return VAL;
|
||||
yylval.vval = f
|
||||
return VAL
|
||||
}
|
||||
|
||||
func
|
||||
main() {
|
||||
var file string;
|
||||
func main() {
|
||||
var file string
|
||||
|
||||
flag.BoolVar(&vflag, "v", false, "verbose");
|
||||
flag.BoolVar(&vflag, "v", false, "verbose")
|
||||
|
||||
flag.Parse();
|
||||
flag.Parse()
|
||||
|
||||
file = os.Getenv("GOROOT") + "/src/cmd/goyacc/units.txt";
|
||||
file = os.Getenv("GOROOT") + "/src/cmd/goyacc/units.txt"
|
||||
if flag.NArg() > 0 {
|
||||
file = flag.Arg(0);
|
||||
file = flag.Arg(0)
|
||||
}
|
||||
|
||||
f,err := os.Open(file, os.O_RDONLY, 0);
|
||||
f, err := os.Open(file, os.O_RDONLY, 0)
|
||||
if err != nil {
|
||||
fmt.Printf("error opening %v: %v", file, err);
|
||||
os.Exit(1);
|
||||
fmt.Printf("error opening %v: %v\n", file, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fi = bufio.NewReader(f);
|
||||
fi = bufio.NewReader(f)
|
||||
|
||||
one.vval = 1;
|
||||
one.vval = 1
|
||||
|
||||
/*
|
||||
* read the 'units' file to
|
||||
* develope a database
|
||||
*/
|
||||
lineno = 0;
|
||||
lineno = 0
|
||||
for {
|
||||
lineno++;
|
||||
lineno++
|
||||
if readline() {
|
||||
break;
|
||||
break
|
||||
}
|
||||
if len(line) == 0 || line[0] == '/' {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
peekrune = ':';
|
||||
Parse();
|
||||
peekrune = ':'
|
||||
yyParse(UnitsLex(0))
|
||||
}
|
||||
|
||||
/*
|
||||
* read the console to
|
||||
* print ratio of pairs
|
||||
*/
|
||||
fi = bufio.NewReader(os.NewFile(0, "stdin"));
|
||||
fi = bufio.NewReader(os.NewFile(0, "stdin"))
|
||||
|
||||
lineno = 0;
|
||||
lineno = 0
|
||||
for {
|
||||
if (lineno & 1) != 0 {
|
||||
fmt.Printf("you want: ");
|
||||
} else
|
||||
fmt.Printf("you have: ");
|
||||
if readline() {
|
||||
break;
|
||||
fmt.Printf("you want: ")
|
||||
} else {
|
||||
fmt.Printf("you have: ")
|
||||
}
|
||||
peekrune = '?';
|
||||
nerrors = 0;
|
||||
Parse();
|
||||
if readline() {
|
||||
break
|
||||
}
|
||||
peekrune = '?'
|
||||
nerrors = 0
|
||||
yyParse(UnitsLex(0))
|
||||
if nerrors != 0 {
|
||||
continue;
|
||||
continue
|
||||
}
|
||||
if (lineno & 1) != 0 {
|
||||
if specialcase(&retnode, &retnode2, &retnode1) {
|
||||
fmt.Printf("\tis %v\n", &retnode);
|
||||
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);
|
||||
div(&retnode, &retnode2, &retnode1)
|
||||
fmt.Printf("\t* %v\n", &retnode)
|
||||
div(&retnode, &retnode1, &retnode2)
|
||||
fmt.Printf("\t/ %v\n", &retnode)
|
||||
}
|
||||
} else
|
||||
retnode2 = retnode1;
|
||||
lineno++;
|
||||
} else {
|
||||
retnode2 = retnode1
|
||||
}
|
||||
lineno++
|
||||
}
|
||||
fmt.Printf("\n");
|
||||
os.Exit(0);
|
||||
fmt.Printf("\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
/*
|
||||
* all characters that have some
|
||||
* meaning. rest are usable as names
|
||||
*/
|
||||
func
|
||||
ralpha(c int) bool {
|
||||
func ralpha(c int) bool {
|
||||
switch c {
|
||||
case 0, '+', '-', '*', '/', '[', ']', '(', ')',
|
||||
case 0, '+', '-', '*', '/', '[', ']', '(', ')',
|
||||
'^', ':', '?', ' ', '\t', '.', '|', '#',
|
||||
'×', '÷', '¹', 'ⁱ', '²', '', '³', '':
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
|
||||
/*
|
||||
* number forming character
|
||||
*/
|
||||
func
|
||||
rdigit(c int) bool {
|
||||
func rdigit(c int) bool {
|
||||
switch c {
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'.', 'e', '+', '-':
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
func
|
||||
Error(s string, v ...interface{}) {
|
||||
func yyError(s string) {
|
||||
Error("syntax error, last name: %v", sym)
|
||||
}
|
||||
|
||||
/*
|
||||
* 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");
|
||||
func Error(s string, v ...interface{}) {
|
||||
fmt.Printf("%v: %v\n\t", lineno, line)
|
||||
fmt.Printf(s, v)
|
||||
fmt.Printf("\n")
|
||||
|
||||
nerrors++;
|
||||
nerrors++
|
||||
if nerrors > 5 {
|
||||
fmt.Printf("too many errors\n");
|
||||
os.Exit(1);
|
||||
fmt.Printf("too many errors\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func
|
||||
add(c,a,b *Node) {
|
||||
var i int;
|
||||
var d int8;
|
||||
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;
|
||||
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");
|
||||
Error("add must be like units")
|
||||
}
|
||||
}
|
||||
c.vval = fadd(a.vval, b.vval);
|
||||
c.vval = fadd(a.vval, b.vval)
|
||||
}
|
||||
|
||||
func
|
||||
sub(c,a,b *Node) {
|
||||
var i int;
|
||||
var d int8;
|
||||
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;
|
||||
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");
|
||||
Error("sub must be like units")
|
||||
}
|
||||
}
|
||||
c.vval = fadd(a.vval, -b.vval);
|
||||
c.vval = fadd(a.vval, -b.vval)
|
||||
}
|
||||
|
||||
func
|
||||
mul(c,a,b *Node) {
|
||||
var i int;
|
||||
func mul(c, a, b *Node) {
|
||||
var i int
|
||||
|
||||
for i=0; i<Ndim; i++ {
|
||||
c.dim[i] = a.dim[i] + b.dim[i];
|
||||
for i = 0; i < Ndim; i++ {
|
||||
c.dim[i] = a.dim[i] + b.dim[i]
|
||||
}
|
||||
c.vval = fmul(a.vval, b.vval);
|
||||
c.vval = fmul(a.vval, b.vval)
|
||||
}
|
||||
|
||||
func
|
||||
div(c,a,b *Node) {
|
||||
var i int;
|
||||
func div(c, a, b *Node) {
|
||||
var i int
|
||||
|
||||
for i=0; i<Ndim; i++ {
|
||||
c.dim[i] = a.dim[i] - b.dim[i];
|
||||
for i = 0; i < Ndim; i++ {
|
||||
c.dim[i] = a.dim[i] - b.dim[i]
|
||||
}
|
||||
c.vval = fdiv(a.vval, b.vval);
|
||||
c.vval = fdiv(a.vval, b.vval)
|
||||
}
|
||||
|
||||
func
|
||||
xpn(c,a *Node, b int) {
|
||||
var i int;
|
||||
func xpn(c, a *Node, b int) {
|
||||
var i int
|
||||
|
||||
*c = one;
|
||||
*c = one
|
||||
if b < 0 {
|
||||
b = -b;
|
||||
for i=0; i<b; i++ {
|
||||
div(c, c, a);
|
||||
b = -b
|
||||
for i = 0; i < b; i++ {
|
||||
div(c, c, a)
|
||||
}
|
||||
} else {
|
||||
for i = 0; i < b; i++ {
|
||||
mul(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;
|
||||
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];
|
||||
d1 = 0
|
||||
d2 = 0
|
||||
for i = 1; i < Ndim; i++ {
|
||||
d = a.dim[i]
|
||||
if d != 0 {
|
||||
if d != 1 || d1 != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
d1 = int8(i);
|
||||
d1 = int8(i)
|
||||
}
|
||||
d = b.dim[i];
|
||||
d = b.dim[i]
|
||||
if d != 0 {
|
||||
if d != 1 || d2 != 0 {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
d2 = int8(i);
|
||||
d2 = int8(i)
|
||||
}
|
||||
}
|
||||
if d1 == 0 || d2 == 0 {
|
||||
return false;
|
||||
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];
|
||||
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;
|
||||
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];
|
||||
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;
|
||||
c.vval = (a.vval - 32.) * 5. / 9.
|
||||
return true
|
||||
}
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
|
||||
func
|
||||
printdim(str string, d, n int) string {
|
||||
var v *Var;
|
||||
func printdim(str string, d, n int) string {
|
||||
var v *Var
|
||||
|
||||
if n != 0 {
|
||||
v = fund[d];
|
||||
v = fund[d]
|
||||
if v != nil {
|
||||
str += fmt.Sprintf("%v", v.name);
|
||||
} else
|
||||
str += fmt.Sprintf("[%d]", d);
|
||||
str += fmt.Sprintf("%v", v.name)
|
||||
} else {
|
||||
str += fmt.Sprintf("[%d]", d)
|
||||
}
|
||||
switch n {
|
||||
case 1:
|
||||
break;
|
||||
break
|
||||
case 2:
|
||||
str += "²";
|
||||
str += "²"
|
||||
case 3:
|
||||
str += "³";
|
||||
str += "³"
|
||||
default:
|
||||
str += fmt.Sprintf("^%d", n);
|
||||
str += fmt.Sprintf("^%d", n)
|
||||
}
|
||||
}
|
||||
return str;
|
||||
return str
|
||||
}
|
||||
|
||||
func
|
||||
(n Node) String() string {
|
||||
var str string;
|
||||
var f, i, d int;
|
||||
func (n Node) String() string {
|
||||
var str string
|
||||
var f, i, d int
|
||||
|
||||
str = fmt.Sprintf("%.7e ", n.vval);
|
||||
str = fmt.Sprintf("%.7e ", n.vval)
|
||||
|
||||
f = 0;
|
||||
for i=1; i<Ndim; i++ {
|
||||
d = int(n.dim[i]);
|
||||
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;
|
||||
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]);
|
||||
str += " /"
|
||||
for i = 1; i < Ndim; i++ {
|
||||
d = int(n.dim[i])
|
||||
if d < 0 {
|
||||
str = printdim(str, i, -d);
|
||||
str = printdim(str, i, -d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str;
|
||||
return str
|
||||
}
|
||||
|
||||
func
|
||||
(v *Var) String() string {
|
||||
var str string;
|
||||
str = fmt.Sprintf("%v %v", v.name, v.node);
|
||||
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');
|
||||
func readline() bool {
|
||||
s, err := fi.ReadString('\n')
|
||||
if err != nil {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
line = s;
|
||||
linep = 0;
|
||||
return false;
|
||||
line = s
|
||||
linep = 0
|
||||
return false
|
||||
}
|
||||
|
||||
func
|
||||
getrune() int {
|
||||
var c,n int;
|
||||
func getrune() int {
|
||||
var c, n int
|
||||
|
||||
if linep >= len(line) {
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
c,n = utf8.DecodeRuneInString(line[linep:len(line)]);
|
||||
linep += n;
|
||||
c, n = utf8.DecodeRuneInString(line[linep:len(line)])
|
||||
linep += n
|
||||
if c == '\n' {
|
||||
c = 0;
|
||||
c = 0
|
||||
}
|
||||
return c;
|
||||
return c
|
||||
}
|
||||
|
||||
var symmap = make(map[string]*Var); // symbol table
|
||||
var symmap = make(map[string]*Var) // symbol table
|
||||
|
||||
func
|
||||
lookup(f int) *Var {
|
||||
var p float64;
|
||||
var w *Var;
|
||||
func lookup(f int) *Var {
|
||||
var p float64
|
||||
var w *Var
|
||||
|
||||
v,ok := symmap[sym];
|
||||
v, ok := symmap[sym]
|
||||
if ok {
|
||||
return v;
|
||||
return v
|
||||
}
|
||||
if f != 0 {
|
||||
return nil;
|
||||
return nil
|
||||
}
|
||||
v = new(Var);
|
||||
v.name = sym;
|
||||
symmap[sym] = v;
|
||||
v = new(Var)
|
||||
v.name = sym
|
||||
symmap[sym] = v
|
||||
|
||||
p = 1;
|
||||
p = 1
|
||||
for {
|
||||
p = fmul(p, pname());
|
||||
p = fmul(p, pname())
|
||||
if p == 0 {
|
||||
break;
|
||||
break
|
||||
}
|
||||
w = lookup(1);
|
||||
w = lookup(1)
|
||||
if w != nil {
|
||||
v.node = w.node;
|
||||
v.node.vval = fmul(v.node.vval, p);
|
||||
break;
|
||||
v.node = w.node
|
||||
v.node.vval = fmul(v.node.vval, p)
|
||||
break
|
||||
}
|
||||
}
|
||||
return v;
|
||||
return v
|
||||
}
|
||||
|
||||
type
|
||||
Prefix struct
|
||||
{
|
||||
vval float64;
|
||||
name string;
|
||||
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" },
|
||||
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;
|
||||
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);
|
||||
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;
|
||||
sym = sym[j:n]
|
||||
return prefix[i].vval
|
||||
}
|
||||
}
|
||||
|
||||
@ -699,82 +676,83 @@ pname() float64 {
|
||||
* rip off 's' suffixes
|
||||
*/
|
||||
if n > 2 && sym[n-1] == 's' {
|
||||
sym = sym[0:n-1];
|
||||
return 1;
|
||||
sym = sym[0 : n-1]
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
// careful multiplication
|
||||
// exponents (log) are checked before multiply
|
||||
func
|
||||
fmul(a, b float64) float64 {
|
||||
var l float64;
|
||||
func fmul(a, b float64) float64 {
|
||||
var l float64
|
||||
|
||||
if b <= 0 {
|
||||
if b == 0 {
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
l = math.Log(-b);
|
||||
} else
|
||||
l = math.Log(b);
|
||||
l = math.Log(-b)
|
||||
} else {
|
||||
l = math.Log(b)
|
||||
}
|
||||
|
||||
if a <= 0 {
|
||||
if a == 0 {
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
l += math.Log(-a);
|
||||
} else
|
||||
l += math.Log(a);
|
||||
l += math.Log(-a)
|
||||
} else {
|
||||
l += math.Log(a)
|
||||
}
|
||||
|
||||
if l > Maxe {
|
||||
Error("overflow in multiply");
|
||||
return 1;
|
||||
Error("overflow in multiply")
|
||||
return 1
|
||||
}
|
||||
if l < -Maxe {
|
||||
Error("underflow in multiply");
|
||||
return 0;
|
||||
Error("underflow in multiply")
|
||||
return 0
|
||||
}
|
||||
return a*b;
|
||||
return a * b
|
||||
}
|
||||
|
||||
// careful division
|
||||
// exponents (log) are checked before divide
|
||||
func
|
||||
fdiv(a, b float64) float64 {
|
||||
var l float64;
|
||||
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;
|
||||
Error("division by zero: %v %v", a, b)
|
||||
return 1
|
||||
}
|
||||
l = math.Log(-b);
|
||||
} else
|
||||
l = math.Log(b);
|
||||
l = math.Log(-b)
|
||||
} else {
|
||||
l = math.Log(b)
|
||||
}
|
||||
|
||||
if a <= 0 {
|
||||
if a == 0 {
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
l -= math.Log(-a);
|
||||
} else
|
||||
l -= math.Log(a);
|
||||
l -= math.Log(-a)
|
||||
} else {
|
||||
l -= math.Log(a)
|
||||
}
|
||||
|
||||
if l < -Maxe {
|
||||
Error("overflow in divide");
|
||||
return 1;
|
||||
Error("overflow in divide")
|
||||
return 1
|
||||
}
|
||||
if l > Maxe {
|
||||
Error("underflow in divide");
|
||||
return 0;
|
||||
Error("underflow in divide")
|
||||
return 0
|
||||
}
|
||||
return a/b;
|
||||
return a / b
|
||||
}
|
||||
|
||||
func
|
||||
fadd(a, b float64) float64 {
|
||||
return a + b;
|
||||
func fadd(a, b float64) float64 {
|
||||
return a + b
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user