]> git.saurik.com Git - bison.git/blame_incremental - src/parse-skel.y
Equip the skeleton chain with location tracking, runtime trace,
[bison.git] / src / parse-skel.y
... / ...
CommitLineData
1 /* -*- C -*- */
2/* Parse Bison Skeletons.
3 Copyright (C) 2001 Free Software Foundation, Inc.
4
5 This file is part of Bison, the GNU Compiler Compiler.
6
7 Bison is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 Bison is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Bison; see the file COPYING. If not, write to the Free
19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22%debug
23%defines
24%verbose
25%error-verbose
26%locations
27%name-prefix="skel_"
28%pure-parser
29
30%{
31#include "system.h"
32#include "obstack.h"
33#include "quotearg.h"
34#include "files.h"
35#include "getargs.h"
36#include "output.h"
37#include "skeleton.h"
38#include "muscle_tab.h"
39
40/* Pass the control structure to YYPARSE but not YYLEX (yet?). */
41#define YYPARSE_PARAM skel_control
42/* YYPARSE receives SKEL_CONTROL as a void *. Provide a correctly
43 typed access to it. */
44#define yycontrol ((skel_control_t *) skel_control)
45
46char* prefix = NULL;
47FILE* parser = NULL;
48
49size_t output_line;
50size_t skeleton_line;
51
52static void merror PARAMS ((const char* error));
53
54/* Request detailed parse error messages, and pass them to
55 YLEVAL_ERROR. */
56#undef yyerror
57#define yyerror(Msg) \
58 skel_error (yycontrol, &yylloc, Msg)
59
60/* When debugging our pure parser, we want to see values and locations
61 of the tokens. */
62#define YYPRINT(File, Type, Value) \
63 yyprint (File, &yylloc, Type, &Value)
64static void yyprint (FILE *file, const yyltype *loc,
65 int type, const yystype *value);
66%}
67
68%union
69{
70 char *string;
71 char character;
72 int boolean;
73}
74
75/* Name of a muscle. */
76%token <string> MUSCLE
77/* A string dedicated to Bison (%%"foo"). */
78%token <string> STRING
79/* Raw data, to output directly. */
80%token <string> RAW
81/* Spaces. */
82%token <string> BLANKS
83/* Raw data, but char by char. */
84%token <character> CHARACTER
85
86%token LINE
87%token SLINE
88
89%token YACC
90%token SECTION
91
92%token GUARDS
93%token TOKENS
94%token ACTIONS
95
96%type <boolean> section.yacc
97
98%start input
99
100%%
101input:
102 { LOCATION_RESET (yylloc) } skeleton
103 ;
104
105skeleton : /* Empty. */ { }
106 | section skeleton { }
107;
108
109section : section.header section.body { }
110;
111
112section.header : SECTION BLANKS MUSCLE BLANKS STRING BLANKS section.yacc '\n'
113{
114 char *name = 0;
115 char *limit = 0;
116 char *suffix = $5;
117
118 /* Close the previous parser. */
119 if (parser)
120 parser = (xfclose (parser), NULL);
121
122 /* If the following section should be named with the yacc-style, and it's
123 suffix is of the form 'something.h' or 'something.c', then add '.tab' in
124 the middle of the suffix. */
125 if (tab_extension && $7 && (strsuffix (suffix, ".h") ||
126 strsuffix (suffix, ".c")))
127 {
128 size_t prefix_len = strlen (prefix);
129 size_t suffix_len = strlen (suffix);
130
131 /* Allocate enough space to insert '.tab'. */
132 name = XMALLOC (char, prefix_len + suffix_len + 5);
133 limit = strrchr (suffix, '.');
134 if (!limit)
135 limit = suffix;
136
137 /* Prefix is 'X', suffix is 'Y.Z'. Name will be 'XY.tab.Z'. */
138 {
139 char* cp = 0;
140 cp = stpcpy (name, prefix);
141 cp = stpncpy (cp, suffix, limit - suffix);
142 cp = stpcpy (cp, ".tab");
143 cp = stpcpy (cp, limit);
144 }
145 }
146 else
147 name = stringappend (prefix, suffix);
148
149 /* Prepare the next parser to be output. */
150 parser = xfopen (name, "w");
151 MUSCLE_INSERT_STRING ("parser-file-name", name);
152 XFREE (name);
153
154 ++skeleton_line;
155}
156;
157
158section.yacc : /* Empty. */ { $$ = 0; }
159 | YACC { $$ = 1; }
160;
161
162section.body
163: /* Empty. */ { }
164| section.body '\n' { fputc ('\n', parser); ++output_line; ++skeleton_line; }
165| section.body LINE { fprintf (parser, "%d", output_line); }
166| section.body SLINE { fprintf (parser, "%d", skeleton_line); }
167| section.body GUARDS { guards_output (parser, &output_line); }
168| section.body TOKENS { token_definitions_output (parser, &output_line); }
169| section.body ACTIONS { actions_output (parser, &output_line); }
170| section.body CHARACTER { fputc ($2, parser); }
171| section.body RAW { fputs ($2, parser); }
172| section.body BLANKS { fputs ($2, parser); }
173| section.body MUSCLE {
174 const char* value = muscle_find ($2);
175 if (value)
176 {
177 fputs (value, parser);
178 output_line += get_lines_number (value);
179 }
180 else
181 {
182 fprintf (parser, "%%{%s}", $2);
183 merror ($2);
184 }
185}
186;
187%%
188/*------------------------------------------------------------------.
189| When debugging the parser, display tokens' locations and values. |
190`------------------------------------------------------------------*/
191
192static void
193yyprint (FILE *file,
194 const yyltype *loc, int type, const yystype *value)
195{
196 fputs (" (", file);
197 LOCATION_PRINT (file, *loc);
198 fputs (")", file);
199 switch (type)
200 {
201 case MUSCLE:
202 case STRING:
203 case RAW:
204 case BLANKS:
205 fprintf (file, " = %s", quotearg_style (c_quoting_style,
206 value->string));
207 break;
208
209 case CHARACTER:
210 fprintf (file, " = '%c'", value->character);
211 break;
212
213 case YACC:
214 fprintf (file, " = %s", value->boolean ? "true" : "false");
215 break;
216 }
217}
218
219
220static void
221merror (const char* error)
222{
223 printf ("line %d: %%{%s} undeclared.\n", skeleton_line, error);
224}
225
226void
227skel_error (skel_control_t *control,
228 const yyltype *loc, const char *msg)
229{
230 /* Neutralize GCC warnings for unused parameters. */
231 skel_control_t *c = control;
232 c++;
233 LOCATION_PRINT (stderr, *loc);
234 fprintf (stderr, "%s\n", msg);
235}
236
237void
238process_skeleton (const char* skel)
239{
240 /* Compute prefix. Actually, it seems that the processing I need here is
241 done in compute_base_names, and the result stored in short_base_name. */
242 prefix = short_base_name;
243
244 /* Prepare a few things. */
245 output_line = 1;
246 skeleton_line = 1;
247
248 /* Output. */
249 skel_in = fopen (skel, "r");
250 skel__flex_debug = 0;
251 skel_debug = trace_flag ? 1 : 0;
252 skel_parse (NULL);
253
254 /* Close the last parser. */
255 if (parser)
256 parser = (xfclose (parser), NULL);
257}