pure parser and scanner.
* src/parse-skel.y: Request a pure parser, locations, and prefix
renaming.
(%union): Having several members with the same type does not help
type mismatches, simplify.
(YYPRINT, yyprint): New.
(yyerror): ``Rename'' (there is a #define yyerror skel_error) as...
(skel_error): this.
Handle locations.
* src/scan-skel.l: Adjust to these changes.
* src/skeleton.h (LOCATION_RESET, LOCATION_LINES, LOCATION_STEP)
(LOCATION_PRINT, skel_control_t): New.
+2002-01-02 Akim Demaille <akim@epita.fr>
+
+ Equip the skeleton chain with location tracking, runtime trace,
+ pure parser and scanner.
+
+ * src/parse-skel.y: Request a pure parser, locations, and prefix
+ renaming.
+ (%union): Having several members with the same type does not help
+ type mismatches, simplify.
+ (YYPRINT, yyprint): New.
+ (yyerror): ``Rename'' (there is a #define yyerror skel_error) as...
+ (skel_error): this.
+ Handle locations.
+ * src/scan-skel.l: Adjust to these changes.
+ * src/skeleton.h (LOCATION_RESET, LOCATION_LINES, LOCATION_STEP)
+ (LOCATION_PRINT, skel_control_t): New.
+
2001-12-30 Akim Demaille <akim@epita.fr>
* src/parse-skel.y: Get rid of the shift/reduce conflict:
%defines
%verbose
%error-verbose
+%locations
+%name-prefix="skel_"
+%pure-parser
%{
#include "system.h"
#include "obstack.h"
+#include "quotearg.h"
#include "files.h"
+#include "getargs.h"
#include "output.h"
#include "skeleton.h"
#include "muscle_tab.h"
-extern FILE* yyin;
-extern int yylineno;
+/* Pass the control structure to YYPARSE but not YYLEX (yet?). */
+#define YYPARSE_PARAM skel_control
+/* YYPARSE receives SKEL_CONTROL as a void *. Provide a correctly
+ typed access to it. */
+#define yycontrol ((skel_control_t *) skel_control)
char* prefix = NULL;
FILE* parser = NULL;
size_t output_line;
size_t skeleton_line;
-static int merror PARAMS ((const char* error));
-static int yyerror PARAMS ((const char* error));
+static void merror PARAMS ((const char* error));
+/* Request detailed parse error messages, and pass them to
+ YLEVAL_ERROR. */
+#undef yyerror
+#define yyerror(Msg) \
+ skel_error (yycontrol, &yylloc, Msg)
+
+/* When debugging our pure parser, we want to see values and locations
+ of the tokens. */
+#define YYPRINT(File, Type, Value) \
+ yyprint (File, &yylloc, Type, &Value)
+static void yyprint (FILE *file, const yyltype *loc,
+ int type, const yystype *value);
%}
%union
{
- char *muscle;
char *string;
- char *literal;
char character;
- int yacc;
+ int boolean;
}
/* Name of a muscle. */
-%token <muscle> MUSCLE
+%token <string> MUSCLE
/* A string dedicated to Bison (%%"foo"). */
%token <string> STRING
/* Raw data, to output directly. */
-%token <literal> RAW
+%token <string> RAW
/* Spaces. */
-%token <literal> BLANKS
+%token <string> BLANKS
/* Raw data, but char by char. */
%token <character> CHARACTER
%token TOKENS
%token ACTIONS
-%type <yacc> section.yacc
+%type <boolean> section.yacc
-%start skeleton
+%start input
%%
+input:
+ { LOCATION_RESET (yylloc) } skeleton
+ ;
skeleton : /* Empty. */ { }
| section skeleton { }
}
;
%%
+/*------------------------------------------------------------------.
+| When debugging the parser, display tokens' locations and values. |
+`------------------------------------------------------------------*/
+
+static void
+yyprint (FILE *file,
+ const yyltype *loc, int type, const yystype *value)
+{
+ fputs (" (", file);
+ LOCATION_PRINT (file, *loc);
+ fputs (")", file);
+ switch (type)
+ {
+ case MUSCLE:
+ case STRING:
+ case RAW:
+ case BLANKS:
+ fprintf (file, " = %s", quotearg_style (c_quoting_style,
+ value->string));
+ break;
+
+ case CHARACTER:
+ fprintf (file, " = '%c'", value->character);
+ break;
+
+ case YACC:
+ fprintf (file, " = %s", value->boolean ? "true" : "false");
+ break;
+ }
+}
-static int
+
+static void
merror (const char* error)
{
printf ("line %d: %%{%s} undeclared.\n", skeleton_line, error);
- return 0;
}
-static int
-yyerror (const char* error)
+void
+skel_error (skel_control_t *control,
+ const yyltype *loc, const char *msg)
{
- fprintf (stderr, "%s\n", error);
- return 0;
+ /* Neutralize GCC warnings for unused parameters. */
+ skel_control_t *c = control;
+ c++;
+ LOCATION_PRINT (stderr, *loc);
+ fprintf (stderr, "%s\n", msg);
}
void
skeleton_line = 1;
/* Output. */
- yyin = fopen (skel, "r");
- yydebug = 0;
- yyparse ();
+ skel_in = fopen (skel, "r");
+ skel__flex_debug = 0;
+ skel_debug = trace_flag ? 1 : 0;
+ skel_parse (NULL);
/* Close the last parser. */
if (parser)
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-%{
-#include "system.h"
-#include "skeleton.h"
-#include "parse-skel.h"
-%}
+%option debug nodefault noyywrap nounput
+%option prefix="skel_" outfile="lex.yy.c"
-%option nounput
-%option noyywrap
/* If we enable
%option yylineno
Seems like a Flex bug to me: Why the heck yylineno would trigger
the REJECT exception??? */
+%{
+#include "system.h"
+#include "skeleton.h"
+#include "parse-skel.h"
+%}
+
+%{
+/* Each time we match a string, move the end cursor to its end. */
+#define YY_USER_ACTION yylloc->last_column += yyleng;
+%}
%%
+%{
+ /* At each yylex invocation, mark the current position as the
+ start of the next token. */
+ LOCATION_STEP (*yylloc);
+%}
"%%{line}" { return LINE; }
"%%{skeleton-line}" { return SLINE; }
/* Muscle. */
"%%{"[a-zA-Z][0-9a-zA-Z_-]+"}" {
- yylval.muscle = xstrndup (yytext + 3, yyleng - 4);
+ yylval->string = xstrndup (yytext + 3, yyleng - 4);
return MUSCLE;
}
/* String. */
"%%\"".*"\"" {
- yylval.string = xstrndup (yytext + 3, yyleng - 4);
+ yylval->string = xstrndup (yytext + 3, yyleng - 4);
return STRING;
}
/* End of line. */
"\n" {
+ LOCATION_LINES (*yylloc, yyleng);
return '\n';
}
/* White spaces. */
[\t ]+ {
- yylval.literal = yytext;
+ yylval->string = yytext;
return BLANKS;
}
+ /* Plain Characters. */
+[^%\n]+ {
+ yylval->string = yytext;
+ return RAW;
+}
+
/* Plain Character. */
. {
- yylval.character = *yytext;
+ yylval->character = *yytext;
return CHARACTER;
}
#ifndef SKELETON_H_
# define SKELETON_H_
-/* From parse-skel.y. */
+# include "parse-skel.h"
+
+/* Initialize LOC. */
+# define LOCATION_RESET(Loc) \
+ (Loc).first_column = (Loc).first_line = 1; \
+ (Loc).last_column = (Loc).last_line = 1;
+
+/* Advance of NUM lines. */
+# define LOCATION_LINES(Loc, Num) \
+ (Loc).last_column = 1; \
+ (Loc).last_line += Num;
+
+/* Restart: move the first cursor to the last position. */
+# define LOCATION_STEP(Loc) \
+ (Loc).first_column = (Loc).last_column; \
+ (Loc).first_line = (Loc).last_line;
+
+/* Output LOC on the stream OUT. */
+# define LOCATION_PRINT(Out, Loc) \
+ if ((Loc).first_line != (Loc).last_line) \
+ fprintf (Out, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column - 1); \
+ else if ((Loc).first_column < (Loc).last_column - 1) \
+ fprintf (Out, "%d.%d-%d", (Loc).first_line, \
+ (Loc).first_column, (Loc).last_column - 1); \
+ else \
+ fprintf (Out, "%d.%d", (Loc).first_line, (Loc).first_column)
+
+
+/* Pure parsers need to pass arguments to yyparse. */
+typedef struct skel_control_s
+{
+ /* For the time being, nothing. */
+} skel_control_t;
+
+/* From parse-skel.y. */
+extern int skel_debug;
+void skel_error PARAMS ((skel_control_t *control,
+ const yyltype *loc, const char *msg));
void process_skeleton PARAMS ((const char* skel));
/* From scan-skel.l. */
+extern int skel__flex_debug;
+
+/* Renamed yyin. */
+extern FILE* skel_in;
+
# define YY_DECL \
- int yylex PARAMS ((void))
+ int skel_lex PARAMS ((yystype *yylval, yyltype *yylloc))
YY_DECL;
#endif SKELETON_H_