From aed7fd9b9736c68bf23bb42ab422baf1281acf32 Mon Sep 17 00:00:00 2001 From: Akim Demaille Date: Wed, 2 Jan 2002 14:56:12 +0000 Subject: [PATCH] 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. --- ChangeLog | 17 +++++++++ src/parse-skel.y | 97 +++++++++++++++++++++++++++++++++++++----------- src/scan-skel.l | 39 +++++++++++++------ src/skeleton.h | 48 +++++++++++++++++++++++- 4 files changed, 167 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index 69fb9fc5..b71d8909 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2002-01-02 Akim Demaille + + 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 * src/parse-skel.y: Get rid of the shift/reduce conflict: diff --git a/src/parse-skel.y b/src/parse-skel.y index 8cf7fcd5..2e115b30 100644 --- a/src/parse-skel.y +++ b/src/parse-skel.y @@ -23,17 +23,25 @@ %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; @@ -41,28 +49,37 @@ 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 +%token MUSCLE /* A string dedicated to Bison (%%"foo"). */ %token STRING /* Raw data, to output directly. */ -%token RAW +%token RAW /* Spaces. */ -%token BLANKS +%token BLANKS /* Raw data, but char by char. */ %token CHARACTER @@ -76,11 +93,14 @@ static int yyerror PARAMS ((const char* error)); %token TOKENS %token ACTIONS -%type section.yacc +%type section.yacc -%start skeleton +%start input %% +input: + { LOCATION_RESET (yylloc) } skeleton + ; skeleton : /* Empty. */ { } | section skeleton { } @@ -165,19 +185,53 @@ section.body } ; %% +/*------------------------------------------------------------------. +| 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 @@ -192,9 +246,10 @@ process_skeleton (const char* skel) 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) diff --git a/src/scan-skel.l b/src/scan-skel.l index fc88b4a1..b04968c4 100644 --- a/src/scan-skel.l +++ b/src/scan-skel.l @@ -19,14 +19,9 @@ 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 @@ -35,7 +30,22 @@ 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; } @@ -49,30 +59,37 @@ /* 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; } diff --git a/src/skeleton.h b/src/skeleton.h index b76ae333..fa328eaf 100644 --- a/src/skeleton.h +++ b/src/skeleton.h @@ -21,12 +21,56 @@ #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_ -- 2.45.2