pgenmain.c 3.38 KB
Newer Older
1

Guido van Rossum's avatar
Guido van Rossum committed
2 3
/* Parser generator main program */

Guido van Rossum's avatar
Guido van Rossum committed
4 5 6 7 8 9 10
/* This expects a filename containing the grammar as argv[1] (UNIX)
   or asks the console for such a file name (THINK C).
   It writes its output on two files in the current directory:
   - "graminit.c" gets the grammar as a bunch of initialized data
   - "graminit.h" gets the grammar's non-terminals as #defines.
   Error messages and status info during the generation process are
   written to stdout, or sometimes to stderr. */
Guido van Rossum's avatar
Guido van Rossum committed
11

12 13 14 15
/* XXX TO DO:
   - check for duplicate definitions of names (instead of fatal err)
*/

Guido van Rossum's avatar
Guido van Rossum committed
16
#include "pgenheaders.h"
Guido van Rossum's avatar
Guido van Rossum committed
17 18 19 20 21
#include "grammar.h"
#include "node.h"
#include "parsetok.h"
#include "pgen.h"

22
int Py_DebugFlag;
23
int Py_VerboseFlag;
Guido van Rossum's avatar
Guido van Rossum committed
24

Guido van Rossum's avatar
Guido van Rossum committed
25
/* Forward */
26
grammar *getgrammar(char *filename);
27
#ifdef THINK_C
28 29
int main(int, char **);
char *askfile(void);
Guido van Rossum's avatar
Guido van Rossum committed
30 31
#endif

32
void
Thomas Wouters's avatar
Thomas Wouters committed
33
Py_Exit(int sts)
34 35 36 37
{
	exit(sts);
}

Guido van Rossum's avatar
Guido van Rossum committed
38
int
Thomas Wouters's avatar
Thomas Wouters committed
39
main(int argc, char **argv)
Guido van Rossum's avatar
Guido van Rossum committed
40
{
Guido van Rossum's avatar
Guido van Rossum committed
41 42 43 44
	grammar *g;
	FILE *fp;
	char *filename;
	
45
#ifdef THINK_C
Guido van Rossum's avatar
Guido van Rossum committed
46 47 48 49
	filename = askfile();
#else
	if (argc != 2) {
		fprintf(stderr, "usage: %s grammar\n", argv[0]);
50
		Py_Exit(2);
Guido van Rossum's avatar
Guido van Rossum committed
51 52 53 54 55 56 57
	}
	filename = argv[1];
#endif
	g = getgrammar(filename);
	fp = fopen("graminit.c", "w");
	if (fp == NULL) {
		perror("graminit.c");
58
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
59
	}
Guido van Rossum's avatar
Guido van Rossum committed
60 61 62 63 64 65
	printf("Writing graminit.c ...\n");
	printgrammar(g, fp);
	fclose(fp);
	fp = fopen("graminit.h", "w");
	if (fp == NULL) {
		perror("graminit.h");
66
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
67
	}
Guido van Rossum's avatar
Guido van Rossum committed
68 69 70
	printf("Writing graminit.h ...\n");
	printnonterminals(g, fp);
	fclose(fp);
71
	Py_Exit(0);
Guido van Rossum's avatar
Guido van Rossum committed
72
	return 0; /* Make gcc -Wall happy */
Guido van Rossum's avatar
Guido van Rossum committed
73 74 75
}

grammar *
Thomas Wouters's avatar
Thomas Wouters committed
76
getgrammar(char *filename)
Guido van Rossum's avatar
Guido van Rossum committed
77 78 79 80
{
	FILE *fp;
	node *n;
	grammar *g0, *g;
81
	perrdetail err;
Guido van Rossum's avatar
Guido van Rossum committed
82 83 84 85
	
	fp = fopen(filename, "r");
	if (fp == NULL) {
		perror(filename);
86
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
87 88
	}
	g0 = meta_grammar();
89
	n = PyParser_ParseFile(fp, filename, g0, g0->g_start,
90
		      (char *)NULL, (char *)NULL, &err);
Guido van Rossum's avatar
Guido van Rossum committed
91 92
	fclose(fp);
	if (n == NULL) {
93 94 95
		fprintf(stderr, "Parsing error %d, line %d.\n",
			err.error, err.lineno);
		if (err.text != NULL) {
96
			size_t i;
97 98 99 100 101 102 103 104 105 106 107
			fprintf(stderr, "%s", err.text);
			i = strlen(err.text);
			if (i == 0 || err.text[i-1] != '\n')
				fprintf(stderr, "\n");
			for (i = 0; i < err.offset; i++) {
				if (err.text[i] == '\t')
					putc('\t', stderr);
				else
					putc(' ', stderr);
			}
			fprintf(stderr, "^\n");
108
			PyMem_DEL(err.text);
109
		}
110
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
111 112 113 114
	}
	g = pgen(n);
	if (g == NULL) {
		printf("Bad grammar.\n");
115
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
116 117 118 119
	}
	return g;
}

120
#ifdef THINK_C
Guido van Rossum's avatar
Guido van Rossum committed
121
char *
Thomas Wouters's avatar
Thomas Wouters committed
122
askfile(void)
Guido van Rossum's avatar
Guido van Rossum committed
123 124 125 126 127 128
{
	char buf[256];
	static char name[256];
	printf("Input file name: ");
	if (fgets(buf, sizeof buf, stdin) == NULL) {
		printf("EOF\n");
129
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
130
	}
131 132
	/* XXX The (unsigned char *) case is needed by THINK C 3.0 */
	if (sscanf(/*(unsigned char *)*/buf, " %s ", name) != 1) {
Guido van Rossum's avatar
Guido van Rossum committed
133
		printf("No file\n");
134
		Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
135
	}
Guido van Rossum's avatar
Guido van Rossum committed
136
	return name;
Guido van Rossum's avatar
Guido van Rossum committed
137
}
Guido van Rossum's avatar
Guido van Rossum committed
138
#endif
Guido van Rossum's avatar
Guido van Rossum committed
139 140

void
Thomas Wouters's avatar
Thomas Wouters committed
141
Py_FatalError(char *msg)
Guido van Rossum's avatar
Guido van Rossum committed
142 143
{
	fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
144
	Py_Exit(1);
Guido van Rossum's avatar
Guido van Rossum committed
145 146
}

147 148 149
#ifdef macintosh
/* ARGSUSED */
int
Thomas Wouters's avatar
Thomas Wouters committed
150
guesstabsize(char *path)
151 152 153 154 155
{
	return 4;
}
#endif

156 157 158
/* No-nonsense my_readline() for tokenizer.c */

char *
Thomas Wouters's avatar
Thomas Wouters committed
159
PyOS_Readline(char *prompt)
160
{
161
	size_t n = 1000;
162
	char *p = PyMem_MALLOC(n);
163 164 165 166 167 168 169 170 171 172 173 174
	char *q;
	if (p == NULL)
		return NULL;
	fprintf(stderr, "%s", prompt);
	q = fgets(p, n, stdin);
	if (q == NULL) {
		*p = '\0';
		return p;
	}
	n = strlen(p);
	if (n > 0 && p[n-1] != '\n')
		p[n-1] = '\n';
175
	return PyMem_REALLOC(p, n+1);
176
}
177 178 179 180 181 182 183 184 185 186 187 188

#include <stdarg.h>

void
PySys_WriteStderr(const char *format, ...)
{
	va_list va;

	va_start(va, format);
	vfprintf(stderr, format, va);
	va_end(va);
}