work on macros
[pspp] / src / language / lexer / lexer.c
index 1283c1b7847fb2b479a9df28f321e1a87840b2d7..bdbce65a8a0480f55179420e6091e4ba76fe2d62 100644 (file)
@@ -40,6 +40,7 @@
 #include "libpspp/i18n.h"
 #include "libpspp/ll.h"
 #include "libpspp/message.h"
+#include "libpspp/macro.h"
 #include "libpspp/misc.h"
 #include "libpspp/str.h"
 #include "libpspp/u8-istream.h"
@@ -77,6 +78,7 @@ struct lex_source
   {
     struct ll ll;               /* In lexer's list of sources. */
     struct lex_reader *reader;
+    struct lexer *lexer;
     struct segmenter segmenter;
     bool eof;                   /* True if T_STOP was read from 'reader'. */
 
@@ -113,7 +115,7 @@ static const struct lex_token *lex_next__ (const struct lexer *, int n);
 static void lex_source_push_endcmd__ (struct lex_source *);
 
 static void lex_source_pop__ (struct lex_source *);
-static bool lex_source_get__ (const struct lex_source *);
+static bool lex_source_get (const struct lex_source *);
 static void lex_source_error_valist (struct lex_source *, int n0, int n1,
                                      const char *format, va_list)
    PRINTF_FORMAT (4, 0);
@@ -174,7 +176,7 @@ void
 lex_include (struct lexer *lexer, struct lex_reader *reader)
 {
   assert (ll_is_empty (&lexer->sources) || lex_token (lexer) == T_ENDCMD);
-  ll_push_head (&lexer->sources, &lex_source_create (reader)->ll);
+  ll_push_head (&lexer->sources, &lex_source_create (lexer, reader)->ll);
 }
 
 /* Appends READER to LEXER, so that it will be read after all other current
@@ -182,7 +184,7 @@ lex_include (struct lexer *lexer, struct lex_reader *reader)
 void
 lex_append (struct lexer *lexer, struct lex_reader *reader)
 {
-  ll_push_tail (&lexer->sources, &lex_source_create (reader)->ll);
+  ll_push_tail (&lexer->sources, &lex_source_create (lexer, reader)->ll);
 }
 \f
 /* Advancing. */
@@ -226,7 +228,7 @@ lex_get (struct lexer *lexer)
     lex_source_pop__ (src);
 
   while (deque_is_empty (&src->deque))
-    if (!lex_source_get__ (src))
+    if (!lex_source_get (src))
       {
         lex_source_destroy (src);
         src = lex_source__ (lexer);
@@ -864,6 +866,12 @@ lex_next__ (const struct lexer *lexer_, int n)
     }
 }
 
+static const struct token *
+lex_source_front (const struct lex_source *src)
+{
+  return &src->tokens[deque_front (&src->deque, 0)].token;
+}
+
 static const struct lex_token *
 lex_source_next__ (const struct lex_source *src, int n)
 {
@@ -871,14 +879,12 @@ lex_source_next__ (const struct lex_source *src, int n)
     {
       if (!deque_is_empty (&src->deque))
         {
-          struct lex_token *front;
-
-          front = &src->tokens[deque_front (&src->deque, 0)];
-          if (front->token.type == T_STOP || front->token.type == T_ENDCMD)
+          const struct token *front = lex_source_front (src);
+          if (front->type == T_STOP || front->type == T_ENDCMD)
             return front;
         }
 
-      lex_source_get__ (src);
+      lex_source_get (src);
     }
 
   return &src->tokens[deque_back (&src->deque, n)];
@@ -1426,16 +1432,11 @@ lex_get_error (struct lex_source *src, const char *format, ...)
 }
 
 /* Attempts to append an additional token into SRC's deque, reading more from
-   the underlying lex_reader if necessary.  Returns true if successful, false
-   if the deque already represents (a suffix of) the whole lex_reader's
-   contents, */
+   the underlying lex_reader if necessary.  Returns true if a new token was
+   added to SRC's deque, false otherwise. */
 static bool
-lex_source_get__ (const struct lex_source *src_)
+lex_source_try_get (struct lex_source *src)
 {
-  struct lex_source *src = CONST_CAST (struct lex_source *, src_);
-  if (src->eof)
-    return false;
-
   /* State maintained while scanning tokens.  Usually we only need a single
      state, but scanner_push() can return SCAN_SAVE to indicate that the state
      needs to be saved and possibly restored later with SCAN_BACK. */
@@ -1566,59 +1567,101 @@ lex_source_get__ (const struct lex_source *src_)
   switch (token->token.type)
     {
     default:
-      break;
+      return true;
 
     case T_STOP:
       token->token.type = T_ENDCMD;
       src->eof = true;
-      break;
+      return true;
 
     case SCAN_BAD_HEX_LENGTH:
       lex_get_error (src, _("String of hex digits has %d characters, which "
                             "is not a multiple of 2"),
                      (int) token->token.number);
-      break;
+      return false;
 
     case SCAN_BAD_HEX_DIGIT:
     case SCAN_BAD_UNICODE_DIGIT:
       lex_get_error (src, _("`%c' is not a valid hex digit"),
                      (int) token->token.number);
-      break;
+      return false;
 
     case SCAN_BAD_UNICODE_LENGTH:
       lex_get_error (src, _("Unicode string contains %d bytes, which is "
                             "not in the valid range of 1 to 8 bytes"),
                      (int) token->token.number);
-      break;
+      return false;
 
     case SCAN_BAD_UNICODE_CODE_POINT:
       lex_get_error (src, _("U+%04X is not a valid Unicode code point"),
                      (int) token->token.number);
-      break;
+      return false;
 
     case SCAN_EXPECTED_QUOTE:
       lex_get_error (src, _("Unterminated string constant"));
-      break;
+      return false;
 
     case SCAN_EXPECTED_EXPONENT:
       lex_get_error (src, _("Missing exponent following `%s'"),
                      token->token.string.string);
-      break;
+      return false;
 
     case SCAN_UNEXPECTED_CHAR:
       {
         char c_name[16];
         lex_get_error (src, _("Bad character %s in input"),
                        uc_name (token->token.number, c_name));
+        return false;
       }
-      break;
 
     case SCAN_SKIP:
       lex_source_pop_front (src);
-      break;
+      return false;
     }
 
-  return true;
+  NOT_REACHED ();
+}
+
+static bool
+lex_source_get__ (struct lex_source *src)
+{
+  for (;;) (
+    if (src->eof)
+      return false;
+    else if (lex_source_try_get (src))
+      return true;
+    }
+}
+
+static bool
+lex_source_get (const struct lex_source *src_)
+{
+  struct lex_source *src = CONST_CAST (struct lex_source *, src_);
+
+  if (!lex_source_get (src))
+    return false;
+
+  struct macro_expander *me = macro_expander_create (src->lexer,
+                                                     lex_source_front (src));
+  if (!me)
+    return true;
+
+  for (;;)
+    {
+      if (!lex_source_get (src))
+        {
+          /* This should not be reachable because we always get a T_STOP at the
+             end of input and the macro_expander should always terminate
+             expansion on T_STOP. */
+          NOT_REACHED ();
+        }
+
+      int retval = macro_expander_add (me, lex_source_front (src));
+      
+
+    }
+  
+
 }
 \f
 static void
@@ -1633,13 +1676,14 @@ lex_source_push_endcmd__ (struct lex_source *src)
 }
 
 static struct lex_source *
-lex_source_create (struct lex_reader *reader)
+lex_source_create (struct lexer *lexer, struct lex_reader *reader)
 {
   struct lex_source *src;
 
   src = xzalloc (sizeof *src);
   src->reader = reader;
   segmenter_init (&src->segmenter, reader->syntax);
+  src->lexer = lexer;
   src->tokens = deque_init (&src->deque, 4, sizeof *src->tokens);
 
   lex_source_push_endcmd__ (src);