blob: 96a3b3c9b833ba9f7e3a5ecd4718f96777526183 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossum1d5735e1994-08-30 08:27:36 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossum9bfef441993-03-29 10:43:31 +00003Amsterdam, The Netherlands.
Guido van Rossumf70e43a1991-02-19 12:39:46 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000025/* Parser generator main program */
26
Guido van Rossum3f5da241990-12-20 15:06:42 +000027/* This expects a filename containing the grammar as argv[1] (UNIX)
28 or asks the console for such a file name (THINK C).
29 It writes its output on two files in the current directory:
30 - "graminit.c" gets the grammar as a bunch of initialized data
31 - "graminit.h" gets the grammar's non-terminals as #defines.
32 Error messages and status info during the generation process are
33 written to stdout, or sometimes to stderr. */
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000034
Guido van Rossum1d5735e1994-08-30 08:27:36 +000035/* XXX TO DO:
36 - check for duplicate definitions of names (instead of fatal err)
37*/
38
Guido van Rossum3f5da241990-12-20 15:06:42 +000039#include "pgenheaders.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000040#include "grammar.h"
41#include "node.h"
42#include "parsetok.h"
43#include "pgen.h"
44
45int debugging;
46
Guido van Rossum3f5da241990-12-20 15:06:42 +000047/* Forward */
48grammar *getgrammar PROTO((char *filename));
Guido van Rossum1d5735e1994-08-30 08:27:36 +000049#ifdef THINK_C
Guido van Rossum3f5da241990-12-20 15:06:42 +000050int main PROTO((int, char **));
51char *askfile PROTO((void));
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000052#endif
53
Guido van Rossumf1dc5661993-07-05 10:31:29 +000054void
55goaway(sts)
56 int sts;
57{
58 exit(sts);
59}
60
Guido van Rossum3f5da241990-12-20 15:06:42 +000061int
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000062main(argc, argv)
63 int argc;
64 char **argv;
65{
66 grammar *g;
67 node *n;
68 FILE *fp;
69 char *filename;
70
Guido van Rossum1d5735e1994-08-30 08:27:36 +000071#ifdef THINK_C
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000072 filename = askfile();
73#else
74 if (argc != 2) {
75 fprintf(stderr, "usage: %s grammar\n", argv[0]);
Guido van Rossumf1dc5661993-07-05 10:31:29 +000076 goaway(2);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000077 }
78 filename = argv[1];
79#endif
80 g = getgrammar(filename);
81 fp = fopen("graminit.c", "w");
82 if (fp == NULL) {
83 perror("graminit.c");
Guido van Rossumf1dc5661993-07-05 10:31:29 +000084 goaway(1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000085 }
86 printf("Writing graminit.c ...\n");
87 printgrammar(g, fp);
88 fclose(fp);
89 fp = fopen("graminit.h", "w");
90 if (fp == NULL) {
91 perror("graminit.h");
Guido van Rossumf1dc5661993-07-05 10:31:29 +000092 goaway(1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000093 }
94 printf("Writing graminit.h ...\n");
95 printnonterminals(g, fp);
96 fclose(fp);
Guido van Rossumf1dc5661993-07-05 10:31:29 +000097 goaway(0);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000098}
99
Guido van Rossum3f5da241990-12-20 15:06:42 +0000100grammar *
101getgrammar(filename)
102 char *filename;
103{
104 FILE *fp;
105 node *n;
106 grammar *g0, *g;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000107 perrdetail err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000108
109 fp = fopen(filename, "r");
110 if (fp == NULL) {
111 perror(filename);
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000112 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000113 }
114 g0 = meta_grammar();
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000115 n = parsefile(fp, filename, g0, g0->g_start,
116 (char *)NULL, (char *)NULL, &err);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000117 fclose(fp);
118 if (n == NULL) {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000119 fprintf(stderr, "Parsing error %d, line %d.\n",
120 err.error, err.lineno);
121 if (err.text != NULL) {
122 int i;
123 fprintf(stderr, "%s", err.text);
124 i = strlen(err.text);
125 if (i == 0 || err.text[i-1] != '\n')
126 fprintf(stderr, "\n");
127 for (i = 0; i < err.offset; i++) {
128 if (err.text[i] == '\t')
129 putc('\t', stderr);
130 else
131 putc(' ', stderr);
132 }
133 fprintf(stderr, "^\n");
134 free(err.text);
135 }
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000136 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000137 }
138 g = pgen(n);
139 if (g == NULL) {
140 printf("Bad grammar.\n");
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000141 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000142 }
143 return g;
144}
145
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000146#ifdef THINK_C
Guido van Rossum3f5da241990-12-20 15:06:42 +0000147char *
148askfile()
149{
150 char buf[256];
151 static char name[256];
152 printf("Input file name: ");
153 if (fgets(buf, sizeof buf, stdin) == NULL) {
154 printf("EOF\n");
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000155 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000156 }
Guido van Rossum706eea81990-12-20 23:11:02 +0000157 /* XXX The (unsigned char *) case is needed by THINK C 3.0 */
158 if (sscanf(/*(unsigned char *)*/buf, " %s ", name) != 1) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000159 printf("No file\n");
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000160 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000161 }
162 return name;
163}
164#endif
165
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000166void
167fatal(msg)
168 char *msg;
169{
170 fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000171 goaway(1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000172}
173
Guido van Rossum7ebb23c1992-03-27 17:31:35 +0000174#ifdef macintosh
175/* ARGSUSED */
176int
177guesstabsize(path)
178 char *path;
179{
180 return 4;
181}
182#endif
183
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000184/* No-nonsense my_readline() for tokenizer.c */
185
186char *
187my_readline(prompt)
188 char *prompt;
189{
190 int n = 1000;
191 char *p = malloc(n);
192 char *q;
193 if (p == NULL)
194 return NULL;
195 fprintf(stderr, "%s", prompt);
196 q = fgets(p, n, stdin);
197 if (q == NULL) {
198 *p = '\0';
199 return p;
200 }
201 n = strlen(p);
202 if (n > 0 && p[n-1] != '\n')
203 p[n-1] = '\n';
204 return realloc(p, n+1);
205}