]> git.saurik.com Git - bison.git/blob - src/parse-skel.y
* src/skeleton.h: New.
[bison.git] / src / parse-skel.y
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 %error-verbose
25
26 %{
27 #include "system.h"
28 #include "obstack.h"
29 #include "files.h"
30 #include "output.h"
31 #include "skeleton.h"
32 #include "muscle_tab.h"
33
34 extern FILE* yyin;
35 extern int yylineno;
36
37 char* prefix = NULL;
38 FILE* parser = NULL;
39
40 size_t output_line;
41 size_t skeleton_line;
42
43 static int merror PARAMS ((const char* error));
44 static int yyerror PARAMS ((const char* error));
45
46 %}
47
48 %union
49 {
50 char* muscle;
51 char* string;
52 char character;
53 int yacc;
54 }
55
56 %token <muscle> MUSCLE
57 %token <string> STRING
58 %token <character> CHARACTER
59
60 %token LINE
61 %token SLINE
62
63 %token YACC
64 %token SECTION
65
66 %token GUARDS
67 %token TOKENS
68 %token ACTIONS
69
70 %type <yacc> section.yacc
71
72 %start skeleton
73
74 %%
75
76 skeleton : /* Empty. */ { }
77 | section skeleton { }
78 ;
79
80 section : section.header section.body { }
81 ;
82
83 section.header : SECTION gb MUSCLE gb STRING gb section.yacc gb '\n'
84 {
85 char *name = 0;
86 char *limit = 0;
87 char *suffix = $5;
88
89 /* Close the previous parser. */
90 if (parser)
91 parser = (xfclose (parser), NULL);
92
93 /* If the following section should be named with the yacc-style, and it's
94 suffix is of the form 'something.h' or 'something.c', then add '.tab' in
95 the middle of the suffix. */
96 if (tab_extension && $7 && (strsuffix (suffix, ".h") ||
97 strsuffix (suffix, ".c")))
98 {
99 size_t prefix_len = strlen (prefix);
100 size_t suffix_len = strlen (suffix);
101
102 /* Allocate enough space to insert '.tab'. */
103 name = XMALLOC (char, prefix_len + suffix_len + 5);
104 limit = strrchr (suffix, '.');
105 if (!limit)
106 limit = suffix;
107
108 /* Prefix is 'X', suffix is 'Y.Z'. Name will be 'XY.tab.Z'. */
109 {
110 char* cp = 0;
111 cp = stpcpy (name, prefix);
112 cp = stpncpy (cp, suffix, limit - suffix);
113 cp = stpcpy (cp, ".tab");
114 cp = stpcpy (cp, limit);
115 }
116 }
117 else
118 name = stringappend (prefix, suffix);
119
120 /* Prepare the next parser to be output. */
121 parser = xfopen (name, "w");
122 MUSCLE_INSERT_STRING ("parser-file-name", name);
123 XFREE (name);
124
125 ++skeleton_line;
126 }
127 ;
128
129 section.yacc : /* Empty. */ { $$ = 0; }
130 | YACC { $$ = 1; }
131 ;
132
133 section.body
134 : /* Empty. */ { }
135 | section.body '\n' { fputc ('\n', parser); ++output_line; ++skeleton_line; }
136 | section.body LINE { fprintf (parser, "%d", output_line); }
137 | section.body SLINE { fprintf (parser, "%d", skeleton_line); }
138 | section.body GUARDS { guards_output (parser, &output_line); }
139 | section.body TOKENS { token_definitions_output (parser, &output_line); }
140 | section.body ACTIONS { actions_output (parser, &output_line); }
141 | section.body CHARACTER { fputc ($2, parser); }
142 | section.body MUSCLE {
143 const char* value = muscle_find ($2);
144 if (value)
145 {
146 fputs (value, parser);
147 output_line += get_lines_number (value);
148 }
149 else
150 {
151 fprintf (parser, "%%{%s}", $2);
152 merror ($2);
153 }
154 }
155 ;
156
157 gb : /* Empty. */ { }
158 | gb CHARACTER { /* Do not echo garbage characters. */ }
159 ;
160
161 %%
162
163 static int
164 merror (const char* error)
165 {
166 printf ("line %d: %%{%s} undeclared.\n", skeleton_line, error);
167 return 0;
168 }
169
170 static int
171 yyerror (const char* error)
172 {
173 fprintf (stderr, "%s\n", error);
174 return 0;
175 }
176
177 void
178 process_skeleton (const char* skel)
179 {
180 /* Compute prefix. Actually, it seems that the processing I need here is
181 done in compute_base_names, and the result stored in short_base_name. */
182 prefix = short_base_name;
183
184 /* Prepare a few things. */
185 output_line = 1;
186 skeleton_line = 1;
187
188 /* Output. */
189 yyin = fopen (skel, "r");
190 yydebug = 0;
191 yyparse ();
192
193 /* Close the last parser. */
194 if (parser)
195 parser = (xfclose (parser), NULL);
196 }