lexer: New lex_at_phrase(), lex_get_n() functions.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 6 Dec 2021 04:01:01 +0000 (20:01 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 6 Dec 2021 17:05:31 +0000 (09:05 -0800)
These will have their first users in upcoming commits.

src/language/lexer/lexer.c
src/language/lexer/lexer.h

index dd06eeee866b122a32957bf96711f79fbd7e41c5..27d5dedb5464728dd4186c2640b6d1f9531ef5d3 100644 (file)
@@ -379,6 +379,14 @@ lex_get (struct lexer *lexer)
           return;
       }
 }
+
+/* Advances LEXER by N tokens. */
+void
+lex_get_n (struct lexer *lexer, size_t n)
+{
+  while (n-- > 0)
+    lex_get (lexer);
+}
 \f
 /* Issuing errors. */
 
@@ -564,7 +572,8 @@ lex_next_error_valist (struct lexer *lexer, int n0, int n1,
           ds_put_cstr (&s, ": ");
           ds_put_vformat (&s, format, args);
         }
-      ds_put_byte (&s, '.');
+      if (ds_last (&s) != '.')
+        ds_put_byte (&s, '.');
       msg (SE, "%s", ds_cstr (&s));
       ds_destroy (&s);
     }
@@ -1136,32 +1145,49 @@ lex_tokens_match (const struct token *actual, const struct token *expected)
     }
 }
 
-/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
-   skips it and returns true.  Otherwise, returns false.
-
-   S may consist of an arbitrary sequence of tokens, e.g. "KRUSKAL-WALLIS",
-   "2SLS", or "END INPUT PROGRAM".  Identifiers may be abbreviated to their
-   first three letters. */
-bool
-lex_match_phrase (struct lexer *lexer, const char *s)
+static size_t
+lex_at_phrase__ (struct lexer *lexer, const char *s)
 {
   struct string_lexer slex;
   struct token token;
-  int i;
 
-  i = 0;
+  size_t i = 0;
   string_lexer_init (&slex, s, strlen (s), SEG_MODE_INTERACTIVE, true);
   while (string_lexer_next (&slex, &token))
     {
       bool match = lex_tokens_match (lex_next (lexer, i++), &token);
       token_uninit (&token);
       if (!match)
-        return false;
+        return 0;
     }
+  return i;
+}
 
-  while (i-- > 0)
-    lex_get (lexer);
-  return true;
+/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
+   returns true.  Otherwise, returns false.
+
+   S may consist of an arbitrary sequence of tokens, e.g. "KRUSKAL-WALLIS",
+   "2SLS", or "END INPUT PROGRAM".  Identifiers may be abbreviated to their
+   first three letters. */
+bool
+lex_at_phrase (struct lexer *lexer, const char *s)
+{
+  return lex_at_phrase__ (lexer, s) > 0;
+}
+
+/* If LEXER is positioned at the sequence of tokens that may be parsed from S,
+   skips it and returns true.  Otherwise, returns false.
+
+   S may consist of an arbitrary sequence of tokens, e.g. "KRUSKAL-WALLIS",
+   "2SLS", or "END INPUT PROGRAM".  Identifiers may be abbreviated to their
+   first three letters. */
+bool
+lex_match_phrase (struct lexer *lexer, const char *s)
+{
+  size_t n = lex_at_phrase__ (lexer, s);
+  if (n > 0)
+    lex_get_n (lexer, n);
+  return n > 0;
 }
 
 static int
index 6aa900e8df70b9bbbb77da7d2c12919ff9ef15cc..1282b6946b732e451ca080cd3b1cf50e621557a1 100644 (file)
@@ -100,6 +100,7 @@ void lex_append (struct lexer *, struct lex_reader *);
 
 /* Advancing. */
 void lex_get (struct lexer *);
+void lex_get_n (struct lexer *, size_t n);
 
 /* Token testing functions. */
 bool lex_is_number (const struct lexer *);
@@ -120,6 +121,7 @@ bool lex_match (struct lexer *, enum token_type);
 bool lex_match_id (struct lexer *, const char *);
 bool lex_match_id_n (struct lexer *, const char *, size_t n);
 bool lex_match_int (struct lexer *, int);
+bool lex_at_phrase (struct lexer *, const char *s);
 bool lex_match_phrase (struct lexer *, const char *s);
 
 /* Forcible matching functions. */