github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/blog/content/first-go-program/slist.go (about) 1 // +build OMIT 2 3 package main 4 5 // fake stuff 6 type char uint8; 7 8 // const char TESTSTRING[] = "(defn foo (add 'a 'b))\n"; 9 10 type Atom struct { 11 string *[100]char; 12 integer int; 13 next *Slist; /* in hash bucket */ 14 } 15 16 type List struct { 17 car *Slist; 18 cdr *Slist; 19 } 20 21 type Slist struct { 22 isatom bool; 23 isstring bool; 24 //union { 25 atom Atom; 26 list List; 27 //} u; 28 29 Free method(); 30 Print method(); 31 PrintOne method(doparen bool); 32 String method(*char <-); 33 Integer method(int <-); 34 Car method(*Slist <-); 35 Cdr method(*Slist <-); 36 } 37 38 method (this *Slist) Car(*Slist <-) { 39 return this.list.car; 40 } 41 42 method (this *Slist) Cdr(*Slist <-) { 43 return this.list.cdr; 44 } 45 46 method (this *Slist) String(*[100]char <-) { 47 return this.atom.string; 48 } 49 50 method (this *Slist) Integer(int <-) { 51 return this.atom.integer; 52 } 53 54 function OpenFile(); 55 function Parse(*Slist <-); 56 57 //Slist* atom(char *s, int i); 58 59 var token int; 60 var peekc int = -1; 61 var lineno int32 = 1; 62 63 var input [100*1000]char; 64 var inputindex int = 0; 65 var tokenbuf [100]char; 66 67 var EOF int = -1; // BUG should be const 68 69 function main(int32 <-) { 70 var list *Slist; 71 72 OpenFile(); 73 for ;; { 74 list = Parse(); 75 if list == nil { 76 break; 77 } 78 list.Print(); 79 list.Free(); 80 break; 81 } 82 83 return 0; 84 } 85 86 method (slist *Slist) Free(<-) { 87 if slist == nil { 88 return; 89 } 90 if slist.isatom { 91 // free(slist.String()); 92 } else { 93 slist.Car().Free(); 94 slist.Cdr().Free(); 95 } 96 // free(slist); 97 } 98 99 method (slist *Slist) PrintOne(<- doparen bool) { 100 if slist == nil { 101 return; 102 } 103 if slist.isatom { 104 if slist.isstring { 105 print(slist.String()); 106 } else { 107 print(slist.Integer()); 108 } 109 } else { 110 if doparen { 111 print("("); 112 } 113 slist.Car().PrintOne(true); 114 if slist.Cdr() != nil { 115 print(" "); 116 slist.Cdr().PrintOne(false); 117 } 118 if doparen { 119 print(")"); 120 } 121 } 122 } 123 124 method (slist *Slist) Print() { 125 slist.PrintOne(true); 126 print "\n"; 127 } 128 129 function Get(int <-) { 130 var c int; 131 132 if peekc >= 0 { 133 c = peekc; 134 peekc = -1; 135 } else { 136 c = convert(int, input[inputindex]); 137 inputindex = inputindex + 1; // BUG should be incr one expr 138 if c == '\n' { 139 lineno = lineno + 1; 140 } 141 if c == '\0' { 142 inputindex = inputindex - 1; 143 c = EOF; 144 } 145 } 146 return c; 147 } 148 149 function WhiteSpace(bool <- c int) { 150 return c == ' ' || c == '\t' || c == '\r' || c == '\n'; 151 } 152 153 function NextToken() { 154 var i, c int; 155 var backslash bool; 156 157 tokenbuf[0] = '\0'; // clear previous token 158 c = Get(); 159 while WhiteSpace(c) { 160 c = Get(); 161 } 162 switch c { 163 case EOF: 164 token = EOF; 165 case '(': 166 case ')': 167 token = c; 168 break; 169 case: 170 for i = 0; i < 100 - 1; { // sizeof tokenbuf - 1 171 tokenbuf[i] = convert(char, c); 172 i = i + 1; 173 c = Get(); 174 if c == EOF { 175 break; 176 } 177 if WhiteSpace(c) || c == ')' { 178 peekc = c; 179 break; 180 } 181 } 182 if i >= 100 - 1 { // sizeof tokenbuf - 1 183 panic "atom too long\n"; 184 } 185 tokenbuf[i] = '\0'; 186 if '0' <= tokenbuf[0] && tokenbuf[0] <= '9' { 187 token = '0'; 188 } else { 189 token = 'A'; 190 } 191 } 192 } 193 194 function Expect(<- c int) { 195 if token != c { 196 print "parse error: expected ", c, "\n"; 197 panic "parse"; 198 } 199 NextToken(); 200 } 201 202 // Parse a non-parenthesized list up to a closing paren or EOF 203 function ParseList(*Slist <-) { 204 var slist, retval *Slist; 205 206 slist = new(Slist); 207 slist.list.car = nil; 208 slist.list.cdr = nil; 209 slist.isatom = false; 210 slist.isstring = false; 211 212 retval = slist; 213 for ;; { 214 slist.list.car = Parse(); 215 if token == ')' { // empty cdr 216 break; 217 } 218 if token == EOF { // empty cdr BUG SHOULD USE || 219 break; 220 } 221 slist.list.cdr = new(Slist); 222 slist = slist.list.cdr; 223 } 224 return retval; 225 } 226 227 function atom(*Slist <- i int) { // BUG: uses tokenbuf; should take argument 228 var h, length int; 229 var slist, tail *Slist; 230 231 slist = new(Slist); 232 if token == '0' { 233 slist.atom.integer = i; 234 slist.isstring = false; 235 } else { 236 slist.atom.string = new([100]char); 237 var i int; 238 for i = 0; ; i = i + 1 { 239 (*slist.atom.string)[i] = tokenbuf[i]; 240 if tokenbuf[i] == '\0' { 241 break; 242 } 243 } 244 //slist.atom.string = "hello"; // BUG! s; //= strdup(s); 245 slist.isstring = true; 246 } 247 slist.isatom = true; 248 return slist; 249 } 250 251 function atoi(int <-) { // BUG: uses tokenbuf; should take argument 252 var v int = 0; 253 for i := 0; '0' <= tokenbuf[i] && tokenbuf[i] <= '9'; i = i + 1 { 254 v = 10 * v + convert(int, tokenbuf[i] - '0'); 255 } 256 return v; 257 } 258 259 function Parse(*Slist <-) { 260 var slist *Slist; 261 262 if token == EOF || token == ')' { 263 return nil; 264 } 265 if token == '(' { 266 NextToken(); 267 slist = ParseList(); 268 Expect(')'); 269 return slist; 270 } else { 271 // Atom 272 switch token { 273 case EOF: 274 return nil; 275 case '0': 276 slist = atom(atoi()); 277 case '"': 278 case 'A': 279 slist = atom(0); 280 case: 281 slist = nil; 282 print "unknown token"; //, token, tokenbuf; 283 } 284 NextToken(); 285 return slist; 286 } 287 return nil; 288 } 289 290 function OpenFile() { 291 //strcpy(input, TESTSTRING); 292 //inputindex = 0; 293 // (defn foo (add 12 34))\n 294 inputindex = 0; 295 peekc = -1; // BUG 296 EOF = -1; // BUG 297 i := 0; 298 input[i] = '('; i = i + 1; 299 input[i] = 'd'; i = i + 1; 300 input[i] = 'e'; i = i + 1; 301 input[i] = 'f'; i = i + 1; 302 input[i] = 'n'; i = i + 1; 303 input[i] = ' '; i = i + 1; 304 input[i] = 'f'; i = i + 1; 305 input[i] = 'o'; i = i + 1; 306 input[i] = 'o'; i = i + 1; 307 input[i] = ' '; i = i + 1; 308 input[i] = '('; i = i + 1; 309 input[i] = 'a'; i = i + 1; 310 input[i] = 'd'; i = i + 1; 311 input[i] = 'd'; i = i + 1; 312 input[i] = ' '; i = i + 1; 313 input[i] = '1'; i = i + 1; 314 input[i] = '2'; i = i + 1; 315 input[i] = ' '; i = i + 1; 316 input[i] = '3'; i = i + 1; 317 input[i] = '4'; i = i + 1; 318 input[i] = ')'; i = i + 1; 319 input[i] = ')'; i = i + 1; 320 input[i] = '\n'; i = i + 1; 321 NextToken(); 322 }