diff options
Diffstat (limited to 'test/ken/rob2.go')
-rw-r--r-- | test/ken/rob2.go | 280 |
1 files changed, 280 insertions, 0 deletions
diff --git a/test/ken/rob2.go b/test/ken/rob2.go new file mode 100644 index 0000000..4b4410e --- /dev/null +++ b/test/ken/rob2.go @@ -0,0 +1,280 @@ +// run + +// Copyright 2009 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. + +// Test general operation using s-list. +// First Go program ever run (although not in this exact form). + +package main + +import "fmt" + +const nilchar = 0 + +type Atom struct { + str string + integer int + next *Slist /* in hash bucket */ +} + +type List struct { + car *Slist + cdr *Slist +} + +type Slist struct { + isatom bool + isstring bool + //union { + atom Atom + list List + //} u; + +} + +func (this *Slist) Car() *Slist { + return this.list.car +} + +func (this *Slist) Cdr() *Slist { + return this.list.cdr +} + +func (this *Slist) String() string { + return this.atom.str +} + +func (this *Slist) Integer() int { + return this.atom.integer +} + +func (slist *Slist) Free() { + if slist == nil { + return + } + if slist.isatom { + // free(slist.String()); + } else { + slist.Car().Free() + slist.Cdr().Free() + } + // free(slist); +} + +//Slist* atom(byte *s, int i); + +var token int +var peekc int = -1 +var lineno int32 = 1 + +var input string +var inputindex int = 0 +var tokenbuf [100]byte +var tokenlen int = 0 + +const EOF int = -1 + +func main() { + var list *Slist + + OpenFile() + for { + list = Parse() + if list == nil { + break + } + r := list.Print() + list.Free() + if r != "(defn foo (add 12 34))" { + panic(r) + } + break + } +} + +func (slist *Slist) PrintOne(doparen bool) string { + if slist == nil { + return "" + } + var r string + if slist.isatom { + if slist.isstring { + r = slist.String() + } else { + r = fmt.Sprintf("%v", slist.Integer()) + } + } else { + if doparen { + r += "(" + } + r += slist.Car().PrintOne(true) + if slist.Cdr() != nil { + r += " " + r += slist.Cdr().PrintOne(false) + } + if doparen { + r += ")" + } + } + return r +} + +func (slist *Slist) Print() string { + return slist.PrintOne(true) +} + +func Get() int { + var c int + + if peekc >= 0 { + c = peekc + peekc = -1 + } else { + c = int(input[inputindex]) + inputindex++ + if c == '\n' { + lineno = lineno + 1 + } + if c == nilchar { + inputindex = inputindex - 1 + c = EOF + } + } + return c +} + +func WhiteSpace(c int) bool { + return c == ' ' || c == '\t' || c == '\r' || c == '\n' +} + +func NextToken() { + var i, c int + + tokenbuf[0] = nilchar // clear previous token + c = Get() + for WhiteSpace(c) { + c = Get() + } + switch c { + case EOF: + token = EOF + case '(', ')': + token = c + break + default: + for i = 0; i < 100-1; { // sizeof tokenbuf - 1 + tokenbuf[i] = byte(c) + i = i + 1 + c = Get() + if c == EOF { + break + } + if WhiteSpace(c) || c == ')' { + peekc = c + break + } + } + if i >= 100-1 { // sizeof tokenbuf - 1 + panic("atom too long\n") + } + tokenlen = i + tokenbuf[i] = nilchar + if '0' <= tokenbuf[0] && tokenbuf[0] <= '9' { + token = '0' + } else { + token = 'A' + } + } +} + +func Expect(c int) { + if token != c { + print("parse error: expected ", c, "\n") + panic("parse") + } + NextToken() +} + +// Parse a non-parenthesized list up to a closing paren or EOF +func ParseList() *Slist { + var slist, retval *Slist + + slist = new(Slist) + slist.list.car = nil + slist.list.cdr = nil + slist.isatom = false + slist.isstring = false + + retval = slist + for { + slist.list.car = Parse() + if token == ')' || token == EOF { // empty cdr + break + } + slist.list.cdr = new(Slist) + slist = slist.list.cdr + } + return retval +} + +func atom(i int) *Slist { // BUG: uses tokenbuf; should take argument) + var slist *Slist + + slist = new(Slist) + if token == '0' { + slist.atom.integer = i + slist.isstring = false + } else { + slist.atom.str = string(tokenbuf[0:tokenlen]) + slist.isstring = true + } + slist.isatom = true + return slist +} + +func atoi() int { // BUG: uses tokenbuf; should take argument) + var v int = 0 + for i := 0; i < tokenlen && '0' <= tokenbuf[i] && tokenbuf[i] <= '9'; i = i + 1 { + v = 10*v + int(tokenbuf[i]-'0') + } + return v +} + +func Parse() *Slist { + var slist *Slist + + if token == EOF || token == ')' { + return nil + } + if token == '(' { + NextToken() + slist = ParseList() + Expect(')') + return slist + } else { + // Atom + switch token { + case EOF: + return nil + case '0': + slist = atom(atoi()) + case '"', 'A': + slist = atom(0) + default: + slist = nil + print("unknown token: ", token, "\n") + } + NextToken() + return slist + } + return nil +} + +func OpenFile() { + input = "(defn foo (add 12 34))\n\x00" + inputindex = 0 + peekc = -1 // BUG + NextToken() +} |