blob: 77743e6cc361f7e596154abc38973eb1bf6c6013 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001/***********************************************************
Guido van Rossumb9f8d6e1995-01-04 19:08:09 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The 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;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000067 FILE *fp;
68 char *filename;
69
Guido van Rossum1d5735e1994-08-30 08:27:36 +000070#ifdef THINK_C
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000071 filename = askfile();
72#else
73 if (argc != 2) {
74 fprintf(stderr, "usage: %s grammar\n", argv[0]);
Guido van Rossumf1dc5661993-07-05 10:31:29 +000075 goaway(2);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000076 }
77 filename = argv[1];
78#endif
79 g = getgrammar(filename);
80 fp = fopen("graminit.c", "w");
81 if (fp == NULL) {
82 perror("graminit.c");
Guido van Rossumf1dc5661993-07-05 10:31:29 +000083 goaway(1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000084 }
85 printf("Writing graminit.c ...\n");
86 printgrammar(g, fp);
87 fclose(fp);
88 fp = fopen("graminit.h", "w");
89 if (fp == NULL) {
90 perror("graminit.h");
Guido van Rossumf1dc5661993-07-05 10:31:29 +000091 goaway(1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000092 }
93 printf("Writing graminit.h ...\n");
94 printnonterminals(g, fp);
95 fclose(fp);
Guido van Rossumf1dc5661993-07-05 10:31:29 +000096 goaway(0);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000097}
98
Guido van Rossum3f5da241990-12-20 15:06:42 +000099grammar *
100getgrammar(filename)
101 char *filename;
102{
103 FILE *fp;
104 node *n;
105 grammar *g0, *g;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000106 perrdetail err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000107
108 fp = fopen(filename, "r");
109 if (fp == NULL) {
110 perror(filename);
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000111 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000112 }
113 g0 = meta_grammar();
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000114 n = parsefile(fp, filename, g0, g0->g_start,
115 (char *)NULL, (char *)NULL, &err);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000116 fclose(fp);
117 if (n == NULL) {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000118 fprintf(stderr, "Parsing error %d, line %d.\n",
119 err.error, err.lineno);
120 if (err.text != NULL) {
121 int i;
122 fprintf(stderr, "%s", err.text);
123 i = strlen(err.text);
124 if (i == 0 || err.text[i-1] != '\n')
125 fprintf(stderr, "\n");
126 for (i = 0; i < err.offset; i++) {
127 if (err.text[i] == '\t')
128 putc('\t', stderr);
129 else
130 putc(' ', stderr);
131 }
132 fprintf(stderr, "^\n");
133 free(err.text);
134 }
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000135 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000136 }
137 g = pgen(n);
138 if (g == NULL) {
139 printf("Bad grammar.\n");
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000140 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000141 }
142 return g;
143}
144
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000145#ifdef THINK_C
Guido van Rossum3f5da241990-12-20 15:06:42 +0000146char *
147askfile()
148{
149 char buf[256];
150 static char name[256];
151 printf("Input file name: ");
152 if (fgets(buf, sizeof buf, stdin) == NULL) {
153 printf("EOF\n");
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000154 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000155 }
Guido van Rossum706eea81990-12-20 23:11:02 +0000156 /* XXX The (unsigned char *) case is needed by THINK C 3.0 */
157 if (sscanf(/*(unsigned char *)*/buf, " %s ", name) != 1) {
Guido van Rossum3f5da241990-12-20 15:06:42 +0000158 printf("No file\n");
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000159 goaway(1);
Guido van Rossum3f5da241990-12-20 15:06:42 +0000160 }
161 return name;
162}
163#endif
164
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165void
166fatal(msg)
167 char *msg;
168{
169 fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
Guido van Rossumf1dc5661993-07-05 10:31:29 +0000170 goaway(1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000171}
172
Guido van Rossum7ebb23c1992-03-27 17:31:35 +0000173#ifdef macintosh
174/* ARGSUSED */
175int
176guesstabsize(path)
177 char *path;
178{
179 return 4;
180}
181#endif
182
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000183/* No-nonsense my_readline() for tokenizer.c */
184
185char *
186my_readline(prompt)
187 char *prompt;
188{
189 int n = 1000;
190 char *p = malloc(n);
191 char *q;
192 if (p == NULL)
193 return NULL;
194 fprintf(stderr, "%s", prompt);
195 q = fgets(p, n, stdin);
196 if (q == NULL) {
197 *p = '\0';
198 return p;
199 }
200 n = strlen(p);
201 if (n > 0 && p[n-1] != '\n')
202 p[n-1] = '\n';
203 return realloc(p, n+1);
204}