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