Source file
test/ken/rob2.go
1
2
3
4
5
6
7
8
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
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
31 atom Atom
32 list List
33
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
59 } else {
60 slist.Car().Free()
61 slist.Cdr().Free()
62 }
63
64 }
65
66
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
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; {
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 {
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
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 {
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 {
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 {
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
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
279 NextToken()
280 }
281
View as plain text