Allow value labels for non integer values.
[pspp-builds.git] / src / language / lexer / lexer.c
index 7d5ece79b9cb983c01c7b8d939e15038b7f22125..cc8cab808948973b08e9145f337edf8028afb70b 100644 (file)
@@ -22,8 +22,8 @@
 #include <limits.h>
 #include <math.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <stdlib.h>
-#include <libpspp/alloc.h>
 #include <libpspp/assertion.h>
 #include <language/command.h>
 #include <libpspp/message.h>
@@ -32,7 +32,7 @@
 #include <libpspp/str.h>
 #include <output/journal.h>
 
-#include "size_max.h"
+#include "xalloc.h"
 
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
@@ -52,7 +52,7 @@ struct lexer
   int token;      /* Current token. */
   double tokval;  /* T_POS_NUM, T_NEG_NUM: the token's value. */
 
-  char tokid [LONG_NAME_LEN + 1];   /* T_ID: the identifier. */
+  char tokid [VAR_NAME_LEN + 1];   /* T_ID: the identifier. */
 
   struct string tokstr;   /* T_ID, T_STRING: token string value.
                            For T_ID, this is not truncated as is
@@ -295,6 +295,7 @@ lex_get (struct lexer *lexer)
          break;
 
        case '(': case ')': case ',': case '=': case '+': case '/':
+        case '[': case ']':
          lexer->token = *lexer->prog++;
          break;
 
@@ -548,9 +549,19 @@ lex_match (struct lexer *lexer, int t)
    Otherwise, returns false. */
 bool
 lex_match_id (struct lexer *lexer, const char *s)
+{
+  return lex_match_id_n (lexer, s, 3);
+}
+
+/* If the current token is the identifier S, skips it and returns
+   true.  The identifier may be abbreviated to its first N
+   letters.
+   Otherwise, returns false. */
+bool
+lex_match_id_n (struct lexer *lexer, const char *s, size_t n)
 {
   if (lexer->token == T_ID
-      && lex_id_match (ss_cstr (s), ss_cstr (lexer->tokid)))
+      && lex_id_match_n (ss_cstr (s), ss_cstr (lexer->tokid), n))
     {
       lex_get (lexer);
       return true;
@@ -849,8 +860,8 @@ lex_preprocess_line (struct string *line,
 {
   strip_comments (line);
   ds_rtrim (line, ss_cstr (CC_SPACES));
-  *line_ends_command = (ds_chomp (line, get_endcmd ())
-                        || (ds_is_empty (line) && get_nulline ()));
+  *line_ends_command = (ds_chomp (line, settings_get_endcmd ())
+                        || (ds_is_empty (line) && settings_get_nulline ()));
   *line_starts_command = false;
   if (syntax == GETL_BATCH)
     {
@@ -1069,9 +1080,9 @@ convert_numeric_string_to_char_string (struct lexer *lexer,
 
   byte_cnt = ds_length (&lexer->tokstr) / chars_per_byte;
   if (ds_length (&lexer->tokstr) % chars_per_byte)
-    msg (SE, _("String of %s digits has %d characters, which is not a "
+    msg (SE, _("String of %s digits has %zu characters, which is not a "
               "multiple of %d."),
-        base_name, (int) ds_length (&lexer->tokstr), chars_per_byte);
+        base_name, ds_length (&lexer->tokstr), chars_per_byte);
 
   p = ds_cstr (&lexer->tokstr);
   for (i = 0; i < byte_cnt; i++)
@@ -1207,8 +1218,8 @@ finish:
 
   if (ds_length (&lexer->tokstr) > 255)
     {
-      msg (SE, _("String exceeds 255 characters in length (%d characters)."),
-          (int) ds_length (&lexer->tokstr));
+      msg (SE, _("String exceeds 255 characters in length (%zu characters)."),
+          ds_length (&lexer->tokstr));
       ds_truncate (&lexer->tokstr, 255);
     }
 
@@ -1294,3 +1305,28 @@ lex_tokstr (const struct lexer *lexer)
 {
   return &lexer->tokstr;
 }
+
+/* If the lexer is positioned at the (pseudo)identifier S, which
+   may contain a hyphen ('-'), skips it and returns true.  Each
+   half of the identifier may be abbreviated to its first three
+   letters.
+   Otherwise, returns false. */
+bool
+lex_match_hyphenated_word (struct lexer *lexer, const char *s)
+{
+  const char *hyphen = strchr (s, '-');
+  if (hyphen == NULL)
+    return lex_match_id (lexer, s);
+  else if (lexer->token != T_ID
+          || !lex_id_match (ss_buffer (s, hyphen - s), ss_cstr (lexer->tokid))
+          || lex_look_ahead (lexer) != '-')
+    return false;
+  else
+    {
+      lex_get (lexer);
+      lex_force_match (lexer, '-');
+      lex_force_match_id (lexer, hyphen + 1);
+      return true;
+    }
+}
+