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