lexer testing complete
[henge/webcc.git] / src / apc / lexer.c
index 4e0a611..1abe5b5 100644 (file)
 #include <stdlib.h>
 #include <dirent.h>
 /* Local */
-//#include "parser.tab.h"
-#ifndef DP_STACKSIZE
-#define DP_STACKSIZE 1024
+#include "parser.tab.h"
+#ifndef DE_STACKSIZE
+#define DE_STACKSIZE 1024
 #endif
 #ifndef TK_STACKSIZE
 #define TK_STACKSIZE 1024
 #endif
 /* Public */
-struct tok
-{ int lval;
-  int tok;
-};
-int            lexer_init(void);
-int            lexer(void);
-inline
-void           lexer_pushtok(int int);
-struct dirent* lexer_direntpa[DP_STACKSIZE];
+int  lexer_init(void);
+int  lexer(void);
+int  lexer_lexfile(const char*);
+void lexer_pushtok(int, YYSTYPE);
+extern //lexer_lex.rl
+int lexer_lex(const char*);
+struct dirent* lexer_direntpa[DE_STACKSIZE], **lexer_direntpp;
 /* Private */
-static inline
-int scan(void);
+extern //scanner.c
+int scanner_init(void);
+extern //scanner.c
+int scanner(void);
 static inline
 int dredge_current_depth(void);
+extern //bison
+YYSTYPE yylval;
 static
-struct dirent** dps;
-static
-struct tok token_stack[TK_STACKSIZE];
+struct tok
+{ YYSTYPE lval;  //token val
+  int     tok_t; //token type
+} token_stack[TK_STACKSIZE];
 static
 union tokp
-{ int*        i;
-  struct tok* t;
+{ int*        tpt; //token pointer type
+  struct tok* tok;
+  YYSTYPE*    tvp; //token value pointer
 } tks, tkx;
 
 /* Directory Entity Array/Stack
    Simple array for keeping track of dirents yet to be processed by the scanner.
    If this list is empty and there are no tokens, the lexer is done.
+   This array is populated by the scanner as an array, and popped locally by the
+   lexer as a stack.
 */
-#define DP_STACK    (lexer_direntpa)
-#define DP_STACKP   (dps)
-#define DP_LEN()    (DP_STACKP - DP_STACK)
-#define DP_INIT()   (DP_STACKP = DP_STACK)
-#define DP_POP()    (*--DP_STACKP)
+#define DE_STACK    (lexer_direntpa)
+#define DE_STACKP   (lexer_direntpp)
+#define DE_LEN()    (DE_STACKP - DE_STACK)
+#define DE_INIT()   (DE_STACKP = DE_STACK)
+#define DE_POP()    (*--DE_STACKP)
 
 /* Token Stack
    This is a FIFO stack whose pointers are a union of either a pointer to an
@@ -70,25 +76,18 @@ union tokp
    An alignment error will occur if IPOP or IPUSH are used a non-even number of
    times in a sequence!
 */
-#define TK_STACK          (token_stack)
-#define TK_STACKP   (tks.t)
-#define TK_STACKPI  (tks.i)
-#define TK_STACKX   (tkx.t)
-#define TK_STACKXI  (tkx.i)
-#define TK_LEN()    (TK_STACKP - TK_STACKX)
-#define TK_INIT()   (TK_STACKP = TK_STACKX = TK_STACK)
-#define TK_POP()    (*TK_STACKP++)
-#define TK_POPI()   (*TK_STACKPI++);
-#define TK_PUSH(T)  (*TKSTACKX++ = T)
-#define TK_PUSHI(I) (*TKSTACKXI++ = (I))
-
-extern //main.c
-const char* cargs['Z'];
-
-extern //scanner.c
-int scanner_init(void);
-extern //scanner.c
-int scanner(struct dirent**);
+#define TK_STACK     (token_stack)
+#define TK_STACKP    (tks.tok)
+#define TK_STACKPI   (tks.tpt)
+#define TK_STACKPL   (tks.tvp)
+#define TK_STACKX    (tkx.tok)
+#define TK_STACKXI   (tkx.tpt)
+#define TK_LEN()     (TK_STACKX - TK_STACKP)
+#define TK_INIT()    (TK_STACKP = TK_STACKX = TK_STACK)
+#define TK_POP()     (*TK_STACKP++)
+#define TK_POPI()    (*TK_STACKPI++);
+#define TK_POPL()    (*TK_STACKPL++);
+#define TK_PUSH(T,L) (*TK_STACKX++ = (struct tok){L,T})
 
 /* Initializer
    The initializer returns boolean true if an error occurs, which may be handled   with standard errno.
@@ -96,74 +95,86 @@ int scanner(struct dirent**);
 int lexer_init
 ()
 { TK_INIT();
-  DP_INIT();
+  DE_INIT();
   return scanner_init();
 }
 
 /* Lexer
    If the token buffer is empty, 'lexer' will initialize the token buffer and
-   call 'lexer_scandir'.  If #SCANDIR_ERROR is returned, an error is printed
+   call 'lexer_scandir'.  If SCAN_ERROR is returned, an error is printed
    before sending a null return to bison.  If 0 tokens are generated, the error
    printing is skipped.  In all other cases, 'yylval' is set, and the token's
    integer representation is returned.
 */
 int lexer
+#define $($)#$
 #define SCAN_ERROR -1
 #define TK_EMPTY   (TK_STACKP == TK_STACKX)
+#define FAIL(...)                              \
+  do {                                         \
+    fprintf(stderr,__VA_ARGS__);               \
+    goto done;                                 \
+  } while (0)
 ()
-{ if (TK_EMPTY)
-    { switch (parsedir())
-        { case SCAN_ERROR:
-            perror("lexer_scan");
-          case 0:
-            yylval = 0;
-            return 0;
-          default:
-            break;
+{start:
+  while (DE_LEN() > 0)    //lex any directory entries in our stack
+    if (lexer_lexfile(DE_POP()->d_name) == 0)
+      FAIL("Lexer failed to tokenize [%s]\n",(*DE_STACKP)->d_name);
+  if (TK_EMPTY)           //if there are no tokens,
+    { TK_INIT();            //initialize the token stack back to 0
+      switch (scanner())
+        { case SCAN_ERROR:    //if an error occurred,
+           FAIL("Scanner error\n");
+         case 0:             //if the the scanner finds no dirents,
+           goto done;        //then we are done
+          default:            //if we found some elements to scan,
+           goto start;       //start over and lex them
         }
     }
-  yylval = TK_IPOP();
-  return TK_IPOP();
+  yylval = TK_POPL();
+  return TK_POPI();
+ done:
+  yylval.val = 0;
+  return 0;
 }
 
+
 /* Token Receiver
    This receiver takes a struct tok and pushes it to the FIFO stack.
 */
-inline
 void lexer_pushtok
-#define ERR_TK "Fatal: Generated over " S(TK_STACKSIZE) " tokens in one pass."
-( struct tok token )
-{ if (TK_LEN >= TK_STACKSIZE)
+#define $($)#$ //stringifier
+#define ERR_TK "Fatal: Generated over " $(TK_STACKSIZE) " tokens in one pass."
+( int tok, YYSTYPE lval )
+{ if (TK_LEN() >= TK_STACKSIZE)
     { fprintf(stderr, ERR_TK);
       exit(EXIT_FAILURE);
     }
-  TK_PUSH(token);
+  TK_PUSH(tok, lval);
+  printf("Pushed Token  %i | %i\n", TK_STACK[TK_LEN() - 1].tok_t, TK_STACK[TK_LEN() - 1].lval.val);
 }
 
-/* Lexical Analysis
-   Ragel state machine for tokenizing text.
- */
-void lexer_lex
-(const char* str)
-{ struct tok token;
-  token.TOK = 1;
-  token.LVAL = 2;
-  lexer_pushtok(token);
-  printf (str);
-}
+/* Lexical analysis of a file
+   Strips a filename to its base name, then sends it to lexer_lex
+*/
+int lexer_lexfile
+#define MAX_FNAME 2048
+#define HIDDEN_WARNING "%s is hidden and will not be parsed!\n", filename
+( const char  *filename
+)
+{ static char fname[MAX_FNAME];
+  char        *last_period = NULL, *iter;
 
-/*  init_file:
-    if (lsp != NULL)
-    while ((c = *lsp++) == *csp)
-    { switch (c)
-    { case DELIM:
-    delimeters_skipped++;
-    default:
-    csp++; //delayed to ensure csp is the start of scannable text
-    break;
-    }
+  if (*filename == '.')
+    { fprintf (stderr, HIDDEN_WARNING);
+      return 0;
     }
-    last_string = string;
-    scan_text:
-    return scanner_tokenize(csp);
-*/
+  strncpy(fname,filename,MAX_FNAME);
+  last_period = NULL;
+  for (iter = fname; *iter; iter++)
+    if (*iter == '.')
+      last_period = iter;
+  if (last_period)
+    *last_period = '\0';
+  return lexer_lex(fname);
+}