]> git.saurik.com Git - bison.git/commitdiff
* src/muscle_tab.h (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING)
authorRobert Anisko <robert@lrde.epita.fr>
Sun, 30 Dec 2001 15:01:06 +0000 (15:01 +0000)
committerRobert Anisko <robert@lrde.epita.fr>
Sun, 30 Dec 2001 15:01:06 +0000 (15:01 +0000)
(MUSCLE_INSERT_PREFIX): ...to there.
* src/output.c (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING)
(MUSCLE_INSERT_PREFIX): Move from here...
* src/bison.hairy: Add a section directive.  Put braces around muscle
names.  This parser skeleton is still broken, but Bison should not
choke on a bad muscle 'syntax'.
* src/bison.simple: Add a section directive.  Put braces around muscle
names.
* src/files.h (strsuffix, stringappend): Add declarations.
(tab_extension): Add declaration.
(short_base_name): Add declaration.
* src/files.c (strsuffix, stringappend): No longer static.  These
functions are used in the skeleton parser.
(tab_extension): New.
(compute_base_names): Use the computations done in this function
to guess if the generated parsers should have '.tab' in their
names.
(short_base_name): No longer static.
* src/output.c (output_skeleton): New.
(output): Disable call to output_master_parser, and give a try to
a new skeleton handling system.
(guards_output, actions_output): No longer static.
(token_definitions_output, get_lines_number): No longer static.
* configure.in: Use AM_PROG_LEX and AC_PROG_YACC.
* src/Makefile.am (bison_SOURCES): Add scan-skel.l and
parse-skel.y.
* src/parse-skel.y: New file.
* src/scan-skel.l: New file.

ChangeLog
configure.in
src/Makefile.am
src/bison.hairy
src/bison.simple
src/files.c
src/files.h
src/muscle_tab.h
src/output.c
src/parse-skel.y [new file with mode: 0644]
src/scan-skel.l [new file with mode: 0644]

index 397f44dab11cd387f38a94e2bf05fe4cf708a011..1c5ca441889accb294b2096a0251b9a020ca48c2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,42 @@
+2001-12-30  Robert Anisko  <robert.anisko@epita.fr>
+
+       * src/muscle_tab.h (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING)
+       (MUSCLE_INSERT_PREFIX): ...to there.
+       * src/output.c (MUSCLE_INSERT_INT, MUSCLE_INSERT_STRING)
+       (MUSCLE_INSERT_PREFIX): Move from here...
+
+       * src/bison.hairy: Add a section directive.  Put braces around muscle
+       names.  This parser skeleton is still broken, but Bison should not
+       choke on a bad muscle 'syntax'.
+       * src/bison.simple: Add a section directive.  Put braces around muscle
+       names.
+
+       * src/files.h (strsuffix, stringappend): Add declarations.
+       (tab_extension): Add declaration.
+       (short_base_name): Add declaration.
+
+       * src/files.c (strsuffix, stringappend): No longer static.  These
+       functions are used in the skeleton parser.
+       (tab_extension): New.
+       (compute_base_names): Use the computations done in this function
+       to guess if the generated parsers should have '.tab' in their 
+       names.
+       (short_base_name): No longer static.
+
+       * src/output.c (output_skeleton): New.
+       (output): Disable call to output_master_parser, and give a try to
+       a new skeleton handling system.
+       (guards_output, actions_output): No longer static.
+       (token_definitions_output, get_lines_number): No longer static.
+
+       * configure.in: Use AM_PROG_LEX and AC_PROG_YACC.
+
+       * src/Makefile.am (bison_SOURCES): Add scan-skel.l and 
+       parse-skel.y.
+
+       * src/parse-skel.y: New file.
+       * src/scan-skel.l: New file.
+
 2001-12-29  Akim Demaille  <akim@epita.fr>
 
        %name-prefix is broken.
index 654b3a913d7941ce8aa8aff9b05802f66038ed93..2cad57616b92b1657c65288f6c3e922b78b8cdb7 100644 (file)
@@ -35,6 +35,8 @@ AC_SUBST([GCC])
 
 # Checks for programs.
 AC_PROG_CC
+AM_PROG_LEX
+AC_PROG_YACC
 AC_MINIX
 AC_ISC_POSIX
 AM_PROG_CC_STDC
index 05a89fe81134f3735388f5fb0f25c9bd62b5e008..62a1c603bca308d61dd1aea32169f080ad82efdc 100644 (file)
@@ -23,6 +23,7 @@ DEFS = @DEFS@ \
   -DLOCALEDIR=\"$(datadir)/locale\"
 
 CFLAGS = @CFLAGS@ $(WARNING_CFLAGS)
+YFLAGS = "-dv"
 
 # libintl.h in is build/intl, intl/libgettext.h in src/,
 # config.h in build/.
@@ -43,7 +44,8 @@ bison_SOURCES = LR0.c closure.c complain.c conflicts.c        \
     print_graph.h print_graph.c \
     muscle_tab.h muscle_tab.c \
     options.h options.c \
-    print.c reader.c reduce.c symtab.c warshall.c vcg.c
+    print.c reader.c reduce.c symtab.c warshall.c vcg.c \
+    parse-skel.y scan-skel.l
 
 EXTRA_bison_SOURCES = vmsgetargs.c
 
index fc6b68b104a17f76885343a859119a86fa012e7d..5371ea6f0bfcfa13011238e1213ccb22e51570ff 100644 (file)
@@ -1,3 +1,4 @@
+%%{section} %%{body} %%".c" %%{yacc}
                                                          /* -*- C -*- */
 
 /* YYERROR and YYCOST are set by guards. If yyerror is set to a
@@ -332,4 +333,4 @@ yyerrlab:
   goto yyresume;
 }
 
-%%actions
+%%{actions}
index 57190178353f8290b8cd76c749d601259c667049..0482a0ea24738255b3848769989fa94c756791cf 100644 (file)
@@ -1,7 +1,8 @@
+%%{section} %%{body} %%".c" %%{yacc}
 /* -*- C -*- */
 
-/* A Bison parser, made from %%filename
-   by GNU bison %%version.  */
+/* A Bison parser, made from %%{filename}
+   by GNU bison %%{version}.  */
 
 /* Skeleton output parser for bison,
    Copyright 1984, 1989, 1990, 2000, 2001 Free Software Foundation, Inc.
 #define YYBISON        1
 
 /* Pure parsers.  */
-#define YYPURE %%pure
+#define YYPURE %%{pure}
 
 /* Using locations.  */
-#define YYLSP_NEEDED %%locations-flag
+#define YYLSP_NEEDED %%{locations-flag}
 
 /* If NAME_PREFIX is specified substitute the variables and functions
    names.  */
-#define yyparse %%prefix##parse
-#define yylex   %%prefix##lex
-#define yyerror %%prefix##error
-#define yylval  %%prefix##lval
-#define yychar  %%prefix##char
-#define yydebug %%prefix##debug
-#define yynerrs %%prefix##nerrs
+#define yyparse %%{prefix}parse
+#define yylex   %%{prefix}lex
+#define yyerror %%{prefix}error
+#define yylval  %%{prefix}lval
+#define yychar  %%{prefix}char
+#define yydebug %%{prefix}debug
+#define yynerrs %%{prefix}nerrs
 #if YYLSP_NEEDED
-# define yylloc %%prefix##lloc
+# define yylloc %%{prefix}lloc
 #endif
 
 
 /* Copy the user declarations.  */
-%%prologue
+%%{prologue}
 
 /* Enabling traces.  */
 #ifndef YYDEBUG
-# define YYDEBUG %%debug
+# define YYDEBUG %%{debug}
 #endif
 
 /* Enabling verbose error messages.  */
 # undef YYERROR_VERBOSE
 # define YYERROR_VERBOSE 1
 #else
-# define YYERROR_VERBOSE %%error-verbose
+# define YYERROR_VERBOSE %%{error-verbose}
 #endif
 
 #ifndef YYSTYPE
-typedef %%stype yystype;
+typedef %%{stype} yystype;
 # define YYSTYPE yystype
 #endif
 
@@ -83,11 +84,11 @@ typedef struct yyltype
   int last_line;
   int last_column;
 } yyltype;
-# define YYLTYPE %%ltype
+# define YYLTYPE %%{ltype}
 #endif
 
-/* Line %%skeleton-line of %%skeleton.  */
-#line %%line "%%parser-file-name"
+/* Line %%{skeleton-line} of %%{skeleton}.  */
+#line %%{line} "%%{parser-file-name}"
 
 /* All symbols defined below should begin with yy or YY, to avoid
    infringing on user name space.  This should be done even for local
@@ -184,30 +185,30 @@ union yyalloc
 #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */
 
 /* Tokens.  */
-%%tokendef
+%%{tokendef}
 
 /* YYFINAL -- State number of the termination state. */
-#define YYFINAL  %%final
-#define YYFLAG  %%flag
-#define YYLAST   %%last
+#define YYFINAL  %%{final}
+#define YYFLAG  %%{flag}
+#define YYLAST   %%{last}
 
 /* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS  %%ntokens
+#define YYNTOKENS  %%{ntokens}
 /* YYNNTS -- Number of nonterminals. */
-#define YYNNTS  %%nnts
+#define YYNNTS  %%{nnts}
 /* YYNRULES -- Number of rules. */
-#define YYNRULES  %%nrules
+#define YYNRULES  %%{nrules}
 /* YYNRULES -- Number of states. */
-#define YYNSTATES  %%nstates
-#define YYMAXUTOK  %%maxtok
+#define YYNSTATES  %%{nstates}
+#define YYMAXUTOK  %%{maxtok}
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
-#define YYTRANSLATE(x) ((unsigned)(x) <= %%maxtok ? yytranslate[x] : %%nsym)
+#define YYTRANSLATE(x) ((unsigned)(x) <= %%{maxtok} ? yytranslate[x] : %%{nsym})
 
 /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
 static const char yytranslate[] =
 {
-  %%translate
+  %%{translate}
 };
 
 #if YYDEBUG
@@ -215,19 +216,19 @@ static const char yytranslate[] =
    YYRHS.  */
 static const short yyprhs[] =
 {
-  %%prhs
+  %%{prhs}
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS. */
 static const short yyrhs[] =
 {
-  %%rhs
+  %%{rhs}
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const short yyrline[] =
 {
-  %%rline
+  %%{rline}
 };
 #endif
 
@@ -236,26 +237,26 @@ static const short yyrline[] =
    First, the terminals, then, starting at YYNTOKENS, nonterminals. */
 static const char *const yytname[] =
 {
-  %%tname
+  %%{tname}
 };
 #endif
 
 /* YYTOKNUM[YYN] -- Index in YYTNAME corresponding to YYLEX.  */
 static const short yytoknum[] =
 {
-  %%toknum
+  %%{toknum}
 };
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const short yyr1[] =
 {
-  %%r1
+  %%{r1}
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
 static const short yyr2[] =
 {
-  %%r2
+  %%{r2}
 };
 
 /* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE
@@ -263,26 +264,26 @@ static const short yyr2[] =
    error.  */
 static const short yydefact[] =
 {
-  %%defact
+  %%{defact}
 };
 
 /* YYPGOTO[NTERM-NUM]. */
 static const short yydefgoto[] =
 {
-  %%defgoto
+  %%{defgoto}
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
 static const short yypact[] =
 {
-  %%pact
+  %%{pact}
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const short yypgoto[] =
 {
-  %%pgoto
+  %%{pgoto}
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
@@ -290,12 +291,12 @@ static const short yypgoto[] =
    number is the opposite.  If zero, do what YYDEFACT says.  */
 static const short yytable[] =
 {
-  %%table
+  %%{table}
 };
 
 static const short yycheck[] =
 {
-  %%check
+  %%{check}
 };
 
 
@@ -419,7 +420,7 @@ int yydebug;
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
 #ifndef        YYINITDEPTH
-# define YYINITDEPTH %%initdepth
+# define YYINITDEPTH %%{initdepth}
 #endif
 
 /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
@@ -434,7 +435,7 @@ int yydebug;
 #endif
 
 #ifndef YYMAXDEPTH
-# define YYMAXDEPTH %%maxdepth
+# define YYMAXDEPTH %%{maxdepth}
 #endif
 
 \f
@@ -903,11 +904,11 @@ yyreduce:
 #endif
   switch (yyn)
     {
-%%actions
+      %%{actions}
     }
 
-/* Line %%skeleton-line of %%skeleton.  */
-#line %%line "%%parser-file-name"
+/* Line %%{skeleton-line} of %%{skeleton}.  */
+#line %%{line} "%%{parser-file-name}"
 \f
   yyvsp -= yylen;
   yyssp -= yylen;
@@ -1138,4 +1139,4 @@ yyreturn:
   return yyresult;
 }
 
-%%epilogue
+%%{epilogue}
index dc886a0bf6a5aaac738621776e828b2098785a59..2e817b1ed18e247d5834989c6185e079b275403c 100644 (file)
@@ -51,19 +51,22 @@ char *infile = NULL;
 char *attrsfile = NULL;
 
 static char *base_name = NULL;
-static char *short_base_name = NULL;
+char *short_base_name = NULL;
 
 /* C source file extension (the parser source).  */
 const char *src_extension = NULL;
 /* Header file extension (if option ``-d'' is specified).  */
 const char *header_extension = NULL;
+
+/* Should we insert '.tab' in yacc-compatible parsers?  */
+int tab_extension = 0;
 \f
 
 /*--------------------------.
 | Is SUFFIX ending STRING?  |
 `--------------------------*/
 
-static int
+int
 strsuffix (const char *string, const char *suffix)
 {
   size_t string_len = strlen (string);
@@ -80,7 +83,7 @@ strsuffix (const char *string, const char *suffix)
 | STRING1, and STRING2.                                            |
 `-----------------------------------------------------------------*/
 
-static char *
+char*
 stringappend (const char *string1, const char *string2)
 {
   size_t len = strlen (string1) + strlen (string2);
@@ -334,6 +337,11 @@ compute_base_names (void)
        short_base_length -= 4;
       short_base_name = strndup (spec_outfile, short_base_length);
 
+      /* FIXME: This is a quick and dirty way for me to find out if we
+        should .tab or not, using the computations above.  */
+      if (strcmp (base_name, short_base_name))
+       tab_extension = 1;
+
       return;
     }
 
@@ -360,6 +368,10 @@ compute_base_names (void)
       if (ext_index)
        compute_exts_from_gf (infile + ext_index);
 
+      /* It seems that when only a prefix is given, '.tab' should always be
+        used.  */
+      tab_extension = 1;
+
       return;
     }
 
@@ -393,6 +405,9 @@ compute_base_names (void)
                         strlen (short_base_name) + strlen (EXT_TAB) + 1);
     stpcpy (stpcpy (base_name, short_base_name), EXT_TAB);
 
+    /* By default, Bison should insert '.tab' were needed.  */
+    tab_extension = 1;
+
     return;
   }
 }
index 5f02dca136fe833ef0283abf18e6157d696661d4..604216c57830e9557547c593b2fe90d9e1b6ac31 100644 (file)
@@ -68,4 +68,18 @@ char *compute_header_macro PARAMS ((void));
 
 const char *skeleton_find PARAMS ((const char *envvar,
                                   const char *skeleton_name));
+
+/* Is SUFFIX ending STRING?  */
+int strsuffix (const char* string, const char* suffix);
+
+/* Return a newly allocated string composed of the concatenation of
+   STRING1, and STRING2.  */
+char* stringappend (const char* string1, const char* string2);
+
+/* Should we insert '.tab' in yacc-compatible parsers?  */
+extern int tab_extension;
+
+/* Prefix used to generate output files names.  */
+extern char* short_base_name;
+
 #endif /* !FILES_H_ */
index c61c6b6ab1dbaa418e1a9d8b24bbcb65a8836cb4..da35bbd6d9b660df84202127365454a14ff712ba 100644 (file)
@@ -33,4 +33,26 @@ void muscle_init PARAMS ((void));
 void muscle_insert PARAMS ((const char *key, const char *value));
 const char *muscle_find PARAMS ((const char *key));
 
+#define MUSCLE_INSERT_INT(Key, Value)                          \
+{                                                              \
+  obstack_fgrow1 (&muscle_obstack, "%d", Value);               \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
+}
+
+#define MUSCLE_INSERT_STRING(Key, Value)                       \
+{                                                              \
+  obstack_sgrow (&muscle_obstack, Value);                      \
+  obstack_1grow (&muscle_obstack, 0);                          \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
+}
+
+#define MUSCLE_INSERT_PREFIX(Key, Value)                               \
+{                                                                      \
+  obstack_fgrow2 (&muscle_obstack, "%s%s",                             \
+                 spec_name_prefix ? spec_name_prefix : "yy", Value);   \
+  obstack_1grow (&muscle_obstack, 0);                                  \
+  muscle_insert (Key, obstack_finish (&muscle_obstack));               \
+}
+
 #endif /* not MUSCLE_TAB_H_ */
index 34d6b06ae840305bd98bcf1547af8b41e3a25eb3..80fc643b7aeabfa79a06b716c3b76eed2148362b 100644 (file)
@@ -125,7 +125,7 @@ static struct obstack format_obstack;
 int error_verbose = 0;
 
 /* Returns the number of lines of S.  */
-static size_t
+size_t
 get_lines_number (const char *s)
 {
   size_t lines = 0;
@@ -503,7 +503,7 @@ token_actions (void)
 | Output the actions to OOUT.  |
 `-----------------------------*/
 
-static void
+void
 actions_output (FILE *out, size_t *line)
 {
   int rule;
@@ -539,7 +539,7 @@ actions_output (FILE *out, size_t *line)
 | Output the guards to OOUT.  |
 `----------------------------*/
 
-static void
+void
 guards_output (FILE *out, size_t *line)
 {
   int rule;
@@ -571,7 +571,7 @@ guards_output (FILE *out, size_t *line)
 | Output the tokens definition to OOUT.  |
 `---------------------------------------*/
 
-static void
+void
 token_definitions_output (FILE *out, size_t *line)
 {
   int i;
@@ -1042,6 +1042,11 @@ static void
 output_master_parser (void)
 {
   FILE *parser = xfopen (parser_file_name, "w");
+
+  /* FIXME: Remove the two following lines.  */
+  printf ("Test: %s\n", infile);
+  printf ("Test: %s\n", parser_file_name);
+
   if (!skeleton)
     {
       if (semantic_parser)
@@ -1056,29 +1061,24 @@ output_master_parser (void)
   xfclose (parser);
 }
 
+/* Call the skeleton parser.  */
 
-/* FIXME. */
-
-#define MUSCLE_INSERT_INT(Key, Value)                          \
-{                                                              \
-  obstack_fgrow1 (&muscle_obstack, "%d", Value);               \
-  obstack_1grow (&muscle_obstack, 0);                          \
-  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
-}
-
-#define MUSCLE_INSERT_STRING(Key, Value)                       \
-{                                                              \
-  obstack_sgrow (&muscle_obstack, Value);                      \
-  obstack_1grow (&muscle_obstack, 0);                          \
-  muscle_insert (Key, obstack_finish (&muscle_obstack));       \
-}
+static 
+void
+output_skeleton ()
+{
+  /* Find the right skeleton file.  */
+  if (!skeleton)
+    {
+      if (semantic_parser)
+       skeleton = skeleton_find ("BISON_HAIRY", BISON_HAIRY);
+      else
+       skeleton = skeleton_find ("BISON_SIMPLE", BISON_SIMPLE);
+    }
 
-#define MUSCLE_INSERT_PREFIX(Key, Value)                               \
-{                                                                      \
-  obstack_fgrow2 (&muscle_obstack, "%s%s",                             \
-                 spec_name_prefix ? spec_name_prefix : "yy", Value);   \
-  obstack_1grow (&muscle_obstack, 0);                                  \
-  muscle_insert (Key, obstack_finish (&muscle_obstack));               \
+  /* Parse the skeleton file and output the needed parsers.  */
+  muscle_insert ("skeleton", skeleton);
+  process_skeleton (infile, skeleton);
 }
 
 static void
@@ -1102,7 +1102,6 @@ prepare (void)
   MUSCLE_INSERT_INT ("locations-flag", locations_flag);
 }
 
-
 /*-------------------------.
 | Output the header file.  |
 `-------------------------*/
@@ -1188,8 +1187,13 @@ output (void)
   obstack_1grow (&attrs_obstack, 0);
   muscle_insert ("prologue", obstack_finish (&attrs_obstack));
 
+  /* Process the selected skeleton file.  */
+  output_skeleton ();
+
   /* Output the parser. */
+#if 0
   output_master_parser ();
+#endif
   /* Output the header if needed. */
   if (defines_flag)
     header_output ();
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);
+}
diff --git a/src/scan-skel.l b/src/scan-skel.l
new file mode 100644 (file)
index 0000000..b78e02f
--- /dev/null
@@ -0,0 +1,55 @@
+%{
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "parse-skel.h"
+
+%}
+
+%option nounput
+%option noyywrap
+%option yylineno
+
+%%
+
+"%%{line}"          { return LINE; }
+"%%{skeleton-line}" { return SLINE; }
+
+"%%{yacc}"    { return YACC; }
+"%%{section}" { return SECTION; }
+
+"%%{guards}"   { return GUARDS; }
+"%%{actions}"  { return ACTIONS; }
+"%%{tokendef}" { return TOKENS; }
+
+"%%{"[a-zA-Z][0-9a-zA-Z_-]+"}" { /* Muscle.  */
+  size_t len = strlen (yytext);
+  yylval.string = (char*) malloc (len - 3);
+  strncpy (yylval.string, yytext + 3, len - 4);
+  yylval.string[len - 4] = 0;
+  return MUSCLE;
+}
+
+"%%\"".*"\"" { /* String.  */
+  size_t len = strlen (yytext);
+  yylval.string = (char*) malloc (len - 3);
+  strncpy (yylval.string, yytext + 3, len - 4);
+  yylval.string[len - 4] = 0;
+  return STRING;
+}
+
+<<EOF>> { /* End of file.  */
+  return 0;
+}
+
+"\n" { /* End of line.  */
+  return '\n';
+}
+
+. { /* Character.  */
+  yylval.character = *yytext;
+  return CHARACTER;
+}
+
+%%