]> git.saurik.com Git - bison.git/blobdiff - src/parse-skel.y
* src/muscle_tab.h (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING)
[bison.git] / src / parse-skel.y
diff --git a/src/parse-skel.y b/src/parse-skel.y
new file mode 100644 (file)
index 0000000..9223485
--- /dev/null
@@ -0,0 +1,176 @@
+%{
+
+#include "system.h"
+#include "obstack.h"
+#include "files.h"
+
+#include "muscle_tab.h"
+
+#define YYDEBUG 1
+#define YYERROR_VERBOSE 1
+
+extern FILE* yyin;
+extern int   yylineno;
+
+char* prefix = NULL;
+FILE* parser = NULL;
+
+size_t output_line;
+size_t skeleton_line;
+
+extern struct obstack muscle_obstack;
+
+%}
+
+%union
+{
+  char* muscle;
+  char* string;
+  char character;
+  int yacc;
+}
+
+%token< muscle > MUSCLE
+%token< string > STRING
+%token< character > CHARACTER
+
+%token LINE
+%token SLINE
+
+%token YACC
+%token SECTION
+
+%token GUARDS
+%token TOKENS
+%token ACTIONS
+
+%type< yacc > section.yacc
+
+%start skeleton
+
+%%
+
+skeleton : /* Empty.  */    { }
+         | section skeleton { }
+;
+
+section : section.header section.body { }
+;
+
+section.header : SECTION gb MUSCLE gb STRING gb section.yacc gb '\n'
+{
+  char* name = 0;
+  char* limit = 0;
+  char* suffix = $5;
+
+  /* Close the previous parser.  */
+  if (parser)
+    parser = (xfclose (parser), NULL);
+
+  /* If the following section should be named with the yacc-style, and it's
+     suffix is of the form 'something.h' or 'something.c', then add '.tab' in
+     the middle of the suffix.  */
+  if (tab_extension && $7 && (strsuffix (suffix, ".h") || 
+                             strsuffix (suffix, ".c")))
+    {
+      size_t prefix_len = strlen (prefix);
+      size_t suffix_len = strlen (suffix);
+
+      /* Allocate enough space to insert '.tab'.  */
+      name = XMALLOC (char, prefix_len + suffix_len + 5);
+      limit = strrchr (suffix, '.');
+      if (!limit)
+       limit = suffix;
+
+      /* Prefix is 'X', suffix is 'Y.Z'.  Name will be 'XY.tab.Z'.  */
+      {
+       char* cp = 0;
+       cp = stpcpy (name, prefix);
+       cp = stpncpy (cp, suffix, limit - suffix);
+       cp = stpcpy (cp, ".tab");
+       cp = stpcpy (cp, limit);
+      }
+    }
+  else
+    name = stringappend (prefix, suffix);
+  
+  /* Prepare the next parser to be output.  */
+  parser = xfopen (name, "w");
+  MUSCLE_INSERT_STRING ("parser-file-name", name);
+  XFREE (name);
+
+  ++skeleton_line;
+}
+;
+
+section.yacc : /* Empty.  */ { $$ = 0; }
+             | YACC          { $$ = 1; }
+;
+
+section.body 
+: /* Empty.  */ { }
+| section.body '\n' { fputc ('\n', parser); ++output_line; ++skeleton_line; }
+| section.body LINE  { fprintf (parser, "%d", output_line); }
+| section.body SLINE { fprintf (parser, "%d", skeleton_line); }
+| section.body GUARDS { guards_output (parser, &output_line); }
+| section.body TOKENS { token_definitions_output (parser, &output_line); }
+| section.body ACTIONS { actions_output (parser, &output_line); }
+| section.body CHARACTER { fputc ($2, parser); }
+| section.body MUSCLE { 
+  const char* value = muscle_find ($2);
+  if (value)
+    {
+      fputs (value, parser);
+      output_line += get_lines_number (value);
+    }
+  else
+    {
+      fprintf (parser, "%%{%s}", $2);
+      merror ($2);
+    }
+}
+;
+
+gb : /* Empty.  */ { }
+   | gb CHARACTER  { /* Do not echo garbage characters.  */ }
+;
+
+%%
+
+int
+merror (const char* error)
+{
+  printf ("line %d: %%{%s} undeclared.\n", skeleton_line, error);
+  return 0;
+}
+
+int
+yyerror (const char* error)
+{
+  printf ("line %d: %s.\n", yylineno, error);
+  return 0;
+}
+
+int
+process_skeleton (const char* grammar,
+                 const char* skeleton)
+{
+  const char* limit = 0;
+
+  /* Compute prefix.  Actually, it seems that the processing I need here is
+     done in compute_base_names, and the result stored in short_base_name.  */
+  prefix = short_base_name;
+
+  /* Prepare a few things.  */
+  output_line = 1;
+  skeleton_line = 1;
+
+  /* Output.  */
+  yyin = fopen (skeleton, "r");
+  yydebug = 0;
+  yyparse ();
+
+  /* Close the last parser.  */
+  if (parser)
+    parser = (xfclose (parser), NULL);
+}