]> granicus.if.org Git - graphviz/commitdiff
implement string mapping of expr parser's token table using Bison feature
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Mon, 14 Sep 2020 03:02:48 +0000 (20:02 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Sun, 20 Sep 2020 22:36:28 +0000 (15:36 -0700)
This removes some juggling to construct a string table of the tokens in the
expr parser, to replace it with native Bison functionality. Loosely related to
#1806.

.gitignore
lib/expr/Makefile.am
lib/expr/exeval.c
lib/expr/exlexname.c
lib/expr/exop.h [new file with mode: 0644]
lib/expr/exparse.y
windows/include/expr/exop.h [deleted file]

index 44977ad766669358add43d9e59daca0f9b46bfe6..b3f996c7950e475a8076063251fc226b378da525 100644 (file)
@@ -173,7 +173,6 @@ lib/common/htmlparse.c
 lib/common/htmlparse.h
 lib/common/ps_font_equiv.h
 lib/common/svgcolor_lib
-lib/expr/exop.h
 lib/expr/exparse.c
 lib/expr/exparse.h
 lib/graph/parser.c
index f022ec69dcb1ca299af94d878a6acc216b6129cb..e0912a432acbe8c1a55ba5591899ede3e83240e6 100644 (file)
@@ -13,7 +13,7 @@ AM_CPPFLAGS = \
        -I$(top_srcdir)/lib/ast \
        -I$(top_srcdir)/lib/cdt
 
-noinst_HEADERS = exgram.h exlib.h expr.h
+noinst_HEADERS = exgram.h exlib.h exop.h expr.h
 noinst_LTLIBRARIES = libexpr_C.la
 
 ### expr.h includes ast.h and vmalloc.h which we don't install
@@ -43,12 +43,6 @@ libexpr_C_la_LIBADD = \
 $(libexpr_C_la_OBJECTS) $(libexpr_la_OBJECTS): \
        exparse.h exparse.c exgram.h exop.h
 
-exop.h: exparse.h
-       echo "static const char* exop[] = {" > exop.h
-       echo "  \"MINTOKEN\"," >> exop.h
-       $(SED) -e '1,/^[   ]*#[    ]*define[   ][  ]*MINTOKEN/d' -e '/MAXTOKEN/,$$d' -e '/^[    ]*#[    ]*define[       ][      ]*[A-Z]/!d' -e 's/^[    ]*#[    ]*define[       ]*\([A-Z0-9_]*\).*/     "\1",/' < exparse.h >> exop.h
-       echo "};" >> exop.h
-
 exparse.c: y.tab.c 
        @SED@ "s/fprintf/sfprintf/g" <y.tab.c | \
                @SED@ "s/FILE/Sfio_t/g" | \
@@ -73,7 +67,7 @@ expr.3.ps: $(srcdir)/expr.3
 
 EXTRA_DIST = $(man_MANS) $(pdf_DATA) \
        Makefile.nmake Makefile.orig \
-       exparse.c exparse.h exop.h \
+       exparse.c exparse.h \
        y.tab.c y.tab.h y.output expr.vcxproj*
 
-DISTCLEANFILES = $(pdf_DATA) exparse.[ch] exop.h y.tab.[ch] y.output expr.3.ps
+DISTCLEANFILES = $(pdf_DATA) exparse.[ch] y.tab.[ch] y.output expr.3.ps
index 73d5530c3adf3ed2077bd4e91c65c75395f21bef..d3a3792ec50ffbb8b7150f4584bd77084d0423e0 100644 (file)
 
 #include <expr/exlib.h>
 #include <expr/exop.h>
+#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 #include <time.h>
 #ifdef _WIN32
-#include <stdlib.h>
 #define srand48 srand
 #define drand48 rand
 #endif
@@ -51,14 +51,14 @@ lexname(int op, int subop)
        static char     buf[TOTNAME][MAXNAME];
 
        if (op > MINTOKEN && op < MAXTOKEN)
-               return (char*)exop[op - MINTOKEN];
+               return (char*)exop((size_t)op - MINTOKEN);
        if (++n >= TOTNAME)
                n = 0;
        b = buf[n];
        if (op == '=')
        {
                if (subop > MINTOKEN && subop < MAXTOKEN)
-                       sfsprintf(b, MAXNAME, "%s=", exop[subop - MINTOKEN]);
+                       sfsprintf(b, MAXNAME, "%s=", exop((size_t)subop - MINTOKEN));
                else if (subop > ' ' && subop <= '~')
                        sfsprintf(b, MAXNAME, "%c=", subop);
                else
index dbc5aa01e12011808974c37afff566f31285160c..154374d0f34e8f8fe6412d2d1e043862f9f752ae 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <expr/exlib.h>
 #include <expr/exop.h>
+#include <stddef.h>
 
 #define TOTNAME                3
 #define MAXNAME                16
@@ -32,14 +33,14 @@ exlexname(int op, int subop)
        static char     buf[TOTNAME][MAXNAME];
 
        if (op > MINTOKEN && op < MAXTOKEN)
-               return (char*)exop[op - MINTOKEN];
+               return (char*)exop((size_t)op - MINTOKEN);
        if (++n > TOTNAME)
                n = 0;
        b = buf[n];
        if (op == '=')
        {
                if (subop > MINTOKEN && subop < MAXTOKEN)
-                       sfsprintf(b, MAXNAME, "%s=", exop[subop - MINTOKEN]);
+                       sfsprintf(b, MAXNAME, "%s=", exop((size_t)subop - MINTOKEN));
                else if (subop > ' ' && subop <= '~')
                        sfsprintf(b, MAXNAME, "%c=", subop);
                else sfsprintf(b, MAXNAME, "(%d)=", subop);
diff --git a/lib/expr/exop.h b/lib/expr/exop.h
new file mode 100644 (file)
index 0000000..e4a5d72
--- /dev/null
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <stddef.h>
+
+/** retrieve a string representation of a lexer token
+ *
+ * \param id The numerical identifier of the sought token as an offset from
+ *   MINTOKEN
+ * \return The string name of the token or NULL if id is invalid
+ */
+const char *exop(size_t id);
index 1a4ef29597f9f0dc2b127cdb17d789963706fa1e..aa375ebcd77a199104824c9375236e18a099c058 100644 (file)
 #endif
 #endif
 
+#include <assert.h>
+#include <ctype.h>
+#include <expr/exop.h>
 #include <stdio.h>
+#include <string.h>
 #include <ast/ast.h>
 
 #undef RS      /* hp.pa <signal.h> grabs this!! */
 
 %token MAXTOKEN
 
+  /* ask Bison to generate a table, yytname, containing string representations
+   * of all the above tokens
+   */
+%token-table
+
 %{
 
 #include "exgram.h"
@@ -1276,4 +1285,48 @@ initialize       :       assign
 
 %%
 
+const char *exop(size_t index) {
+
+  /* yytname is generated by the %token-table directive */
+
+  /* find the index of MINTOKEN */
+  size_t minid;
+  for (minid = 0; yytname[minid] != NULL; ++minid) {
+    if (strcmp(yytname[minid], "MINTOKEN") == 0) {
+      break;
+    }
+  }
+
+  assert(yytname[minid] != NULL
+    && "failed to find MINTOKEN; incorrect token list in exparse.y?");
+
+  /* find the requested token */
+  {
+    size_t i, j;
+    for (i = j = minid; yytname[i] != NULL; ++i) {
+
+      /* if this token is not a word, skip it */
+      {
+        size_t k;
+        for (k = 0; yytname[i][k] != '\0'; ++k) {
+          if (yytname[i][k] != '_' && !isalnum(yytname[i][k])) {
+            break;
+          }
+        }
+        if (yytname[i][k] != '\0') {
+          continue;
+        }
+      }
+
+      if (j == index + minid) {
+        return yytname[i];
+      }
+      ++j;
+    }
+  }
+
+  /* failed to find the requested token */
+  return NULL;
+}
+
 #include "exgram.h"
diff --git a/windows/include/expr/exop.h b/windows/include/expr/exop.h
deleted file mode 100644 (file)
index f37e9c9..0000000
+++ /dev/null
@@ -1,80 +0,0 @@
-static const char* exop[] = {
-       "MINTOKEN",
-       "INTEGER",
-       "UNSIGNED",
-       "CHARACTER",
-       "FLOATING",
-       "STRING",
-       "VOIDTYPE",
-       "STATIC",
-       "ADDRESS",
-       "ARRAY",
-       "BREAK",
-       "CALL",
-       "CASE",
-       "CONSTANT",
-       "CONTINUE",
-       "DECLARE",
-       "DEFAULT",
-       "DYNAMIC",
-       "ELSE",
-       "EXIT",
-       "FOR",
-       "FUNCTION",
-       "GSUB",
-       "ITERATE",
-       "ITERATER",
-       "ID",
-       "IF",
-       "LABEL",
-       "MEMBER",
-       "NAME",
-       "POS",
-       "PRAGMA",
-       "PRE",
-       "PRINT",
-       "PRINTF",
-       "PROCEDURE",
-       "QUERY",
-       "RAND",
-       "RETURN",
-       "SCANF",
-       "SPLIT",
-       "SPRINTF",
-       "SRAND",
-       "SSCANF",
-       "SUB",
-       "SUBSTR",
-       "SWITCH",
-       "TOKENS",
-       "UNSET",
-       "WHILE",
-       "F2I",
-       "F2S",
-       "I2F",
-       "I2S",
-       "S2B",
-       "S2F",
-       "S2I",
-       "F2X",
-       "I2X",
-       "S2X",
-       "X2F",
-       "X2I",
-       "X2S",
-       "X2X",
-       "XPRINT",
-       "OR",
-       "AND",
-       "EQ",
-       "NE",
-       "LE",
-       "GE",
-       "LS",
-       "RS",
-       "IN_OP",
-       "UNARY",
-       "INC",
-       "DEC",
-       "CAST",
-};