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  }