APC main driver
[henge/webcc.git] / src / apc / lexer.c
diff --git a/src/apc/lexer.c b/src/apc/lexer.c
new file mode 100644 (file)
index 0000000..0d408b9
--- /dev/null
@@ -0,0 +1,92 @@
+/*!@file
+  \brief   lexical analyzer implementation for APC
+  \details this lexer scans a root directory given from the command line
+           for subdirectories and files structured for the APC grammar.
+  \author  Jordan Lavatai
+  \date    Aug 2016
+  ----------------------------------------------------------------------------*/
+//stdc
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+//posix
+#include <unistd.h>
+#include <stdlib.h>
+//bison
+#include "fileparser.tab.h"
+#define TOKEN_BUF_SIZE 1024
+#define DIRP_STACK_SIZE 512
+
+int lexer_init(void);
+int lexer(void);
+
+static
+int lexer_scan(void);
+
+static
+int  token_buf[TOKEN_BUF_SIZE], *tbp, *tbx;
+static
+DIR* dirp_stack[DIRP_STACK_SIZE], *dsp;
+
+/* Initialize pointers */
+int
+lexer_init()
+{ tbp = tbx = token_buf;
+  dsp = dirp_stack;
+  return 0;
+}
+
+/* Returns a token identifier and sets yylval */
+int
+lexer()
+{ if (lexer_scan() == 0)
+    return 0;
+  yylval = *tbp++;
+  return *tbp++;
+}
+
+/* Scanner
+   Scans a filename from its alphabetically ordered list of file elements
+   and tokenizes the result.  If the file list is empty, then the stack of
+   directory elements will be popped and processed as they are encountered.
+
+   Returns the number of tokens generated.
+*/
+#define MAX_ENTITIES 256
+static
+int lexer_scan()
+{ static struct dirent* entity;
+  static struct dirent* files[MAX_ENTITIES];
+  static struct dirent* dirs = files + MAX_ENTITIES - 1;
+  static int            num_files = 0;
+  static int            num_dirs = 0;
+
+  //sort out files and directories, grow directories from bottom up
+  while ((entity = readdir(dirp)) != NULL)
+    { switch (entity->d_type)
+        { case DT_LNK:
+          case DT_REG:
+            files[num_files++] = entity;
+            break;
+          case DT_DIR:
+            *(dirs - num_dirs++) = entity;
+            break;
+          case DT_UNKNOWN:
+          default:
+            printf("Ignoring unknown file: %s\n", entity->d_name);
+            break;
+        }
+    }
+  if (errno)
+    perror("readdir");
+  qsort(&files[0], num_files, sizeof struct dirent*, qalpha);
+  num_ents = scandirat(dirfd, ".", &namelist, scanfilter, scancompar);
+  if (num_ents < 0)
+    { perror("scandirat");
+      return -1;
+    }
+  //process files
+
+  //recurse into directories
+
+}