fixes
[henge/apc.git] / src / lexer.rl
index 36a72ab..5e2fb77 100644 (file)
@@ -10,83 +10,94 @@ extern //lexer.c
 void lexer_pushtok(int, YYSTYPE);
 /* Public */
 int lexer_setdirection(uint8_t*, int);
+int lexer_lexfile(uint8_t*);
+int lexer_lexdir(uint8_t*);
 int lexer_lexstring(uint8_t*, int);
 int lexer_setstr(uint8_t*, int);
+//apc.c
+extern
+yypstate* apc_pstate;
+extern
+yycstate* apc_cstate;
+static
+YYSTYPE   lval_stack[1024], * lvalsp;
+#define PUSHTOK(T,L) yypush_parse(apc_pstate, T, (L), apc_cstate)
+#define LEXTOK(T,Y,L) do {                     \
+    lvalsp->Y = L;                             \
+    PUSHTOK(T,lvalsp);                         \
+    lvalsp++;                                  \
+    ntok++;                                    \
+  } while (0);
+#define PUSHFACE(F) LEXTOK(FACING, face, F)
+#define PUSHREF(R)  LEXTOK(REF, ref, R)
+#define PUSHLINK()  LEXTOK(LINK, val, 0)
+#define PUSHNUM(N)  LEXTOK(NUM, val, N)
+#define PUSHNAME(N) LEXTOK(NAME, str, N)
+#define PUSHOP(O)   LEXTOK(O, val, 0)
+#define PUSHPATH(P) LEXTOK(PATH, str, P)
+
+/* Lexstring is the main lexer for APC and is generated by ragel. It lexes file names of files 
+   that have been scanned and pushes their types and values into the tok_stack, which yyparse 
+   eventually calls during parsing. */
 
 %%{    
   machine lexstring;
 
   # set up yylval and tok_t to be pushed to stack
-  action push_ref       { te = NULL; errno = 0;
-                          yylval.ref = strtoll((char*)ts,(char**)&te,16);
-                         if (errno | (te != NULL))
+  action push_ref       { errno = 0;
+                          lval.ref = strtoll((char*)ts,NULL,16);
+                         if (errno)
                            { fprintf(stderr, "Invalid hex number in file %s\n",(char*)str);
-                             if (te != NULL)
-                               { while (str++ < te)
-                                   fputc(' ', stderr);
-                                 fputc('^', stderr);
-                               }
                              exit(1);
                            }
-                          lexer_pushtok(REF, yylval); ntok++;
+                         PUSHREF(lval.ref);
                        }
-  action push_link      { lexer_pushtok(LINK,(YYSTYPE)0); ntok++; }
-  action push_val       { te = NULL; errno = 0;
-                          yylval.val = strtoll((char*)ts,(char**)&te,10);
+  action push_link      { PUSHLINK(); }
+  action push_val       { errno = 0;
+                          lval.val = strtoll((char*)ts,NULL,10);
                          if (errno)
                            { fprintf(stderr, "strtoll could not parse %s\n", (char*)str);
                              exit(1);
                            }
-                         lexer_pushtok(NUM, yylval);
+                         PUSHNUM(lval.val);
                         }
   action push_name      { printf("Lexer_lexstring:: action:push_name: from %s to %s\n", ts, p);
-                          lexer_pushtok(NAME, yylval);
-                         ntok++;
+                         PUSHNAME(ts);
                         }
   action push_map       { printf("Lexer_lexstring:: action:push_map: pushing map token\n");
-                          yylval.str = (uint8_t*) '~';
-                          lexer_pushtok(MOPEN, yylval);
-                         ntok++;
+                         PUSHOP(MAP);
                        }
   action set_ts         { printf("Lexer_lexstring:: action:set_ts. ts = %s\n", p); ts = p; }
   action push_SS        { printf("Lexer_lexstring:: action:push_SS. p = %s\n",p);
-                          yylval.str = (uint8_t*) "SS";
-                          lexer_pushtok(SS, yylval);
-                         ntok++;
+                          PUSHOP(SS);
                         }
   action push_S         { printf("Lexer_lexstring:: action:push_S. p = %s\n", p);
-                          yylval.val = 0;
-                         lexer_pushtok(D, yylval);
+                         PUSHFACE(SFACE);
                         }
   action push_SW        { printf("Lexer_lexstring:: action:push_SW. p = %s\n", p);
-                          yylval.val = 1;
-                         lexer_pushtok(D, yylval);
-                        }
+                          PUSHFACE(SWFACE);
+                       }
   action push_W         { printf("Lexer_lexstring:: action:push_W. p = %s\n", p);
-                          yylval.val = 2;
-                         lexer_pushtok(D, yylval);
+                          PUSHFACE(WFACE);
                         }
   action push_NW        { printf("Lexer_lexstring:: action:push_NW. p = %s\n", p);
-                          yylval.val = 3;
-                         lexer_pushtok(D, yylval);
+                         PUSHFACE(NWFACE);
                         }
   action push_N         { printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
-                          yylval.val = 4;
-                         lexer_pushtok(D, yylval);
+                          PUSHFACE(NFACE);
                         }
   action push_NE        { printf("Lexer_lexstring:: action:push_NE. p = %s\n", p);
-                          yylval.val = 5;
-                         lexer_pushtok(D, yylval);
+                         PUSHFACE(NEFACE);
                         }
   action push_E         { printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
-                          yylval.val = 6;
-                         lexer_pushtok(D, yylval);
+                         PUSHFACE(EFACE);
                         }
   action push_SE        { printf("Lexer_lexstring:: action:push_N. p = %s\n", p);
-                          yylval.val = 7;
-                         lexer_pushtok(D, yylval);
+                         PUSHFACE(SEFACE);
+                        }
+  action ref_error      { printf("ref from %s to %s has an inappropriate amount of hex digits, it must have eight.\n", ts, p);
+                          exit(1);
                         }
-  #action lex_error      { printf("input error: character %c in filename %s is invalid\n p = %s\n", fc, str, p);}
   action p              { printf("Lexer_lexstring:: p = %s\n", p);}
     
   N = 'N' %push_N;
@@ -98,23 +109,20 @@ int lexer_setstr(uint8_t*, int);
   SW = 'SW' %push_SW;
   SE = 'SE' %push_SE;
 
-  #what goes in between tokens in a filename
   tok_delimiter = [_];
 
-  #types of tokes a filename can contain
   direction = (N | W | S | E | NW | NE | SW | SE) ;
-  #make sure 0x123123 doesnt get mistaken for a ref
   dimensions = (digit+ - '0') >set_ts %push_val 'x' (digit+ - '0') >set_ts  %push_val;
   link = '#'  %push_link;
   SS = ('+SS' %to(push_SS)) | ('+SS' %to(push_SS) link ) ;
-  ref = '0x' >set_ts alnum+ %push_ref;
+  ref = '0x' >set_ts alnum{8} $err(ref_error) %push_ref ;
   val = digit+ >set_ts %push_val ;
-  name = (lower+ >set_ts) %push_name ;
+  name = lower >set_ts (lower | digit)*  %push_name ;
   map = '+MAP' %to(push_map);
   tok = (name | val | ref | dimensions | map | link | SS | direction);
   
 
-  main := (tok tok_delimiter)+ tok [\0];
+  main := (tok tok_delimiter)* tok [\0];
 
   write data nofinal noerror noprefix;
   
@@ -125,12 +133,14 @@ int lexer_lexstring
   int size
 )
 { uint8_t *p; 
-  uint8_t *ts, *pe, *te;
-  int cs, ntok;//, tok_t;
+  uint8_t *ts, *pe, *eof;
+  int cs, ntok;
+  YYSTYPE lval;
 
+  lvalsp = lval_stack;
   ntok = 0;
   p = ts = str;
-  pe = p + size + 1;
+  pe = eof =  p + size + 1;
 
   printf("|---Begin lexstring on p = %s, pe = %s.\n",p, pe);
 
@@ -142,6 +152,57 @@ int lexer_lexstring
   return ntok;
 }
 
+/* Lexical analysis of a file
+   Strips a filename to its base name, then sends it to lexer_lexstring before
+   pushing a PATH token with the filename
+   Returns the number of tokens pushed to the parser.
+*/
+int lexer_lexfile
+( uint8_t* filename )
+{ uint8_t* last_period,* iter,* filename_end;
+  int            ntok;
+  last_period = NULL;
+  for (iter = filename; *iter; iter++)
+    switch (*iter)
+      { // Keep track of the last 'dot' in the name
+        case '.' : last_period = iter; continue;
+        // replace '_' with '\0' so bison can use strlen on them as tokens.
+        case '_' : *iter = '\0';
+        default: continue;
+      }
+  // Mark the end of the filename
+  filename_end = iter;
+  // Lex from either the last period, if present, or filename end
+  ntok = (last_period) ?
+    lexer_lexstring(filename, (int)(last_period - filename))
+  : lexer_lexstring(filename, (int)(iter - filename));
+  // Replace nulls with their original '_'
+  for (iter = filename; iter < filename_end; iter++)
+    if (*iter == '\0')
+      *iter = '_';
+  PUSHPATH(filename);
+  return ntok + 1;
+  return en_main == 1;
+}
+
+int lexer_lexdir
+( uint8_t* dirname )
+{ uint8_t* de = dirname;
+  int ntok;
+  ntok = 0;
+  de = dirname;
+  if (*de) while (*++de);
+  ntok = lexer_lexstring(dirname, (int)(de - dirname));
+  PUSHOP(CLOPEN);
+  return ntok;
+}
+
+int lexer_closedir
+( void )
+{ int ntok = 0;
+  PUSHOP(CLCLOSE);
+  return ntok;
+}
 
 /**************************/
 /****Abandon All Hope******/