(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-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.
# Checks for programs.
AC_PROG_CC
+AM_PROG_LEX
+AC_PROG_YACC
AC_MINIX
AC_ISC_POSIX
AM_PROG_CC_STDC
-DLOCALEDIR=\"$(datadir)/locale\"
CFLAGS = @CFLAGS@ $(WARNING_CFLAGS)
+YFLAGS = "-dv"
# libintl.h in is build/intl, intl/libgettext.h in src/,
# config.h in build/.
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
+%%{section} %%{body} %%".c" %%{yacc}
/* -*- C -*- */
/* YYERROR and YYCOST are set by guards. If yyerror is set to a
goto yyresume;
}
-%%actions
+%%{actions}
+%%{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
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
#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
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
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
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
number is the opposite. If zero, do what YYDEFACT says. */
static const short yytable[] =
{
- %%table
+ %%{table}
};
static const short yycheck[] =
{
- %%check
+ %%{check}
};
/* 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
#endif
#ifndef YYMAXDEPTH
-# define YYMAXDEPTH %%maxdepth
+# define YYMAXDEPTH %%{maxdepth}
#endif
\f
#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;
return yyresult;
}
-%%epilogue
+%%{epilogue}
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);
| STRING1, and STRING2. |
`-----------------------------------------------------------------*/
-static char *
+char*
stringappend (const char *string1, const char *string2)
{
size_t len = strlen (string1) + strlen (string2);
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;
}
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;
}
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;
}
}
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_ */
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_ */
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;
| Output the actions to OOUT. |
`-----------------------------*/
-static void
+void
actions_output (FILE *out, size_t *line)
{
int rule;
| Output the guards to OOUT. |
`----------------------------*/
-static void
+void
guards_output (FILE *out, size_t *line)
{
int rule;
| Output the tokens definition to OOUT. |
`---------------------------------------*/
-static void
+void
token_definitions_output (FILE *out, size_t *line)
{
int i;
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)
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
MUSCLE_INSERT_INT ("locations-flag", locations_flag);
}
-
/*-------------------------.
| Output the header file. |
`-------------------------*/
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 ();
--- /dev/null
+%{
+
+#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);
+}
--- /dev/null
+%{
+
+#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;
+}
+
+%%