Source file test/ken/rob2.go

     1  // run
     2  
     3  // Copyright 2009 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  // Test general operation using s-list.
     8  // First Go program ever run (although not in this exact form).
     9  
    10  package main
    11  
    12  import "fmt"
    13  
    14  const nilchar = 0
    15  
    16  type Atom struct {
    17  	str     string
    18  	integer int
    19  	next    *Slist /* in hash bucket */
    20  }
    21  
    22  type List struct {
    23  	car *Slist
    24  	cdr *Slist
    25  }
    26  
    27  type Slist struct {
    28  	isatom   bool
    29  	isstring bool
    30  	//union {
    31  	atom Atom
    32  	list List
    33  	//} u;
    34  
    35  }
    36  
    37  func (this *Slist) Car() *Slist {
    38  	return this.list.car
    39  }
    40  
    41  func (this *Slist) Cdr() *Slist {
    42  	return this.list.cdr
    43  }
    44  
    45  func (this *Slist) String() string {
    46  	return this.atom.str
    47  }
    48  
    49  func (this *Slist) Integer() int {
    50  	return this.atom.integer
    51  }
    52  
    53  func (slist *Slist) Free() {
    54  	if slist == nil {
    55  		return
    56  	}
    57  	if slist.isatom {
    58  		//		free(slist.String());
    59  	} else {
    60  		slist.Car().Free()
    61  		slist.Cdr().Free()
    62  	}
    63  	//	free(slist);
    64  }
    65  
    66  //Slist* atom(byte *s, int i);
    67  
    68  var token int
    69  var peekc int = -1
    70  var lineno int32 = 1
    71  
    72  var input string
    73  var inputindex int = 0
    74  var tokenbuf [100]byte
    75  var tokenlen int = 0
    76  
    77  const EOF int = -1
    78  
    79  func main() {
    80  	var list *Slist
    81  
    82  	OpenFile()
    83  	for {
    84  		list = Parse()
    85  		if list == nil {
    86  			break
    87  		}
    88  		r := list.Print()
    89  		list.Free()
    90  		if r != "(defn foo (add 12 34))" {
    91  			panic(r)
    92  		}
    93  		break
    94  	}
    95  }
    96  
    97  func (slist *Slist) PrintOne(doparen bool) string {
    98  	if slist == nil {
    99  		return ""
   100  	}
   101  	var r string
   102  	if slist.isatom {
   103  		if slist.isstring {
   104  			r = slist.String()
   105  		} else {
   106  			r = fmt.Sprintf("%v", slist.Integer())
   107  		}
   108  	} else {
   109  		if doparen {
   110  			r += "("
   111  		}
   112  		r += slist.Car().PrintOne(true)
   113  		if slist.Cdr() != nil {
   114  			r += " "
   115  			r += slist.Cdr().PrintOne(false)
   116  		}
   117  		if doparen {
   118  			r += ")"
   119  		}
   120  	}
   121  	return r
   122  }
   123  
   124  func (slist *Slist) Print() string {
   125  	return slist.PrintOne(true)
   126  }
   127  
   128  func Get() int {
   129  	var c int
   130  
   131  	if peekc >= 0 {
   132  		c = peekc
   133  		peekc = -1
   134  	} else {
   135  		c = int(input[inputindex])
   136  		inputindex++
   137  		if c == '\n' {
   138  			lineno = lineno + 1
   139  		}
   140  		if c == nilchar {
   141  			inputindex = inputindex - 1
   142  			c = EOF
   143  		}
   144  	}
   145  	return c
   146  }
   147  
   148  func WhiteSpace(c int) bool {
   149  	return c == ' ' || c == '\t' || c == '\r' || c == '\n'
   150  }
   151  
   152  func NextToken() {
   153  	var i, c int
   154  
   155  	tokenbuf[0] = nilchar // clear previous token
   156  	c = Get()
   157  	for WhiteSpace(c) {
   158  		c = Get()
   159  	}
   160  	switch c {
   161  	case EOF:
   162  		token = EOF
   163  	case '(', ')':
   164  		token = c
   165  		break
   166  	default:
   167  		for i = 0; i < 100-1; { // sizeof tokenbuf - 1
   168  			tokenbuf[i] = byte(c)
   169  			i = i + 1
   170  			c = Get()
   171  			if c == EOF {
   172  				break
   173  			}
   174  			if WhiteSpace(c) || c == ')' {
   175  				peekc = c
   176  				break
   177  			}
   178  		}
   179  		if i >= 100-1 { // sizeof tokenbuf - 1
   180  			panic("atom too long\n")
   181  		}
   182  		tokenlen = i
   183  		tokenbuf[i] = nilchar
   184  		if '0' <= tokenbuf[0] && tokenbuf[0] <= '9' {
   185  			token = '0'
   186  		} else {
   187  			token = 'A'
   188  		}
   189  	}
   190  }
   191  
   192  func Expect(c int) {
   193  	if token != c {
   194  		print("parse error: expected ", c, "\n")
   195  		panic("parse")
   196  	}
   197  	NextToken()
   198  }
   199  
   200  // Parse a non-parenthesized list up to a closing paren or EOF
   201  func ParseList() *Slist {
   202  	var slist, retval *Slist
   203  
   204  	slist = new(Slist)
   205  	slist.list.car = nil
   206  	slist.list.cdr = nil
   207  	slist.isatom = false
   208  	slist.isstring = false
   209  
   210  	retval = slist
   211  	for {
   212  		slist.list.car = Parse()
   213  		if token == ')' || token == EOF { // empty cdr
   214  			break
   215  		}
   216  		slist.list.cdr = new(Slist)
   217  		slist = slist.list.cdr
   218  	}
   219  	return retval
   220  }
   221  
   222  func atom(i int) *Slist { // BUG: uses tokenbuf; should take argument)
   223  	var slist *Slist
   224  
   225  	slist = new(Slist)
   226  	if token == '0' {
   227  		slist.atom.integer = i
   228  		slist.isstring = false
   229  	} else {
   230  		slist.atom.str = string(tokenbuf[0:tokenlen])
   231  		slist.isstring = true
   232  	}
   233  	slist.isatom = true
   234  	return slist
   235  }
   236  
   237  func atoi() int { // BUG: uses tokenbuf; should take argument)
   238  	var v int = 0
   239  	for i := 0; i < tokenlen && '0' <= tokenbuf[i] && tokenbuf[i] <= '9'; i = i + 1 {
   240  		v = 10*v + int(tokenbuf[i]-'0')
   241  	}
   242  	return v
   243  }
   244  
   245  func Parse() *Slist {
   246  	var slist *Slist
   247  
   248  	if token == EOF || token == ')' {
   249  		return nil
   250  	}
   251  	if token == '(' {
   252  		NextToken()
   253  		slist = ParseList()
   254  		Expect(')')
   255  		return slist
   256  	} else {
   257  		// Atom
   258  		switch token {
   259  		case EOF:
   260  			return nil
   261  		case '0':
   262  			slist = atom(atoi())
   263  		case '"', 'A':
   264  			slist = atom(0)
   265  		default:
   266  			slist = nil
   267  			print("unknown token: ", token, "\n")
   268  		}
   269  		NextToken()
   270  		return slist
   271  	}
   272  	return nil
   273  }
   274  
   275  func OpenFile() {
   276  	input = "(defn foo (add 12 34))\n\x00"
   277  	inputindex = 0
   278  	peekc = -1 // BUG
   279  	NextToken()
   280  }
   281  

View as plain text