|
1 |
|
2 /* Parser generator main program */ |
|
3 |
|
4 /* This expects a filename containing the grammar as argv[1] (UNIX) |
|
5 or asks the console for such a file name (THINK C). |
|
6 It writes its output on two files in the current directory: |
|
7 - "graminit.c" gets the grammar as a bunch of initialized data |
|
8 - "graminit.h" gets the grammar's non-terminals as #defines. |
|
9 Error messages and status info during the generation process are |
|
10 written to stdout, or sometimes to stderr. */ |
|
11 |
|
12 /* XXX TO DO: |
|
13 - check for duplicate definitions of names (instead of fatal err) |
|
14 */ |
|
15 |
|
16 #include "Python.h" |
|
17 #include "pgenheaders.h" |
|
18 #include "grammar.h" |
|
19 #include "node.h" |
|
20 #include "parsetok.h" |
|
21 #include "pgen.h" |
|
22 |
|
23 int Py_DebugFlag; |
|
24 int Py_VerboseFlag; |
|
25 int Py_IgnoreEnvironmentFlag; |
|
26 |
|
27 /* Forward */ |
|
28 grammar *getgrammar(char *filename); |
|
29 |
|
30 void |
|
31 Py_Exit(int sts) |
|
32 { |
|
33 exit(sts); |
|
34 } |
|
35 |
|
36 int |
|
37 main(int argc, char **argv) |
|
38 { |
|
39 grammar *g; |
|
40 FILE *fp; |
|
41 char *filename, *graminit_h, *graminit_c; |
|
42 |
|
43 if (argc != 4) { |
|
44 fprintf(stderr, |
|
45 "usage: %s grammar graminit.h graminit.c\n", argv[0]); |
|
46 Py_Exit(2); |
|
47 } |
|
48 filename = argv[1]; |
|
49 graminit_h = argv[2]; |
|
50 graminit_c = argv[3]; |
|
51 g = getgrammar(filename); |
|
52 fp = fopen(graminit_c, "w"); |
|
53 if (fp == NULL) { |
|
54 perror(graminit_c); |
|
55 Py_Exit(1); |
|
56 } |
|
57 if (Py_DebugFlag) |
|
58 printf("Writing %s ...\n", graminit_c); |
|
59 printgrammar(g, fp); |
|
60 fclose(fp); |
|
61 fp = fopen(graminit_h, "w"); |
|
62 if (fp == NULL) { |
|
63 perror(graminit_h); |
|
64 Py_Exit(1); |
|
65 } |
|
66 if (Py_DebugFlag) |
|
67 printf("Writing %s ...\n", graminit_h); |
|
68 printnonterminals(g, fp); |
|
69 fclose(fp); |
|
70 Py_Exit(0); |
|
71 return 0; /* Make gcc -Wall happy */ |
|
72 } |
|
73 |
|
74 grammar * |
|
75 getgrammar(char *filename) |
|
76 { |
|
77 FILE *fp; |
|
78 node *n; |
|
79 grammar *g0, *g; |
|
80 perrdetail err; |
|
81 |
|
82 fp = fopen(filename, "r"); |
|
83 if (fp == NULL) { |
|
84 perror(filename); |
|
85 Py_Exit(1); |
|
86 } |
|
87 g0 = meta_grammar(); |
|
88 n = PyParser_ParseFile(fp, filename, g0, g0->g_start, |
|
89 (char *)NULL, (char *)NULL, &err); |
|
90 fclose(fp); |
|
91 if (n == NULL) { |
|
92 fprintf(stderr, "Parsing error %d, line %d.\n", |
|
93 err.error, err.lineno); |
|
94 if (err.text != NULL) { |
|
95 size_t i; |
|
96 fprintf(stderr, "%s", err.text); |
|
97 i = strlen(err.text); |
|
98 if (i == 0 || err.text[i-1] != '\n') |
|
99 fprintf(stderr, "\n"); |
|
100 for (i = 0; i < err.offset; i++) { |
|
101 if (err.text[i] == '\t') |
|
102 putc('\t', stderr); |
|
103 else |
|
104 putc(' ', stderr); |
|
105 } |
|
106 fprintf(stderr, "^\n"); |
|
107 PyObject_FREE(err.text); |
|
108 } |
|
109 Py_Exit(1); |
|
110 } |
|
111 g = pgen(n); |
|
112 if (g == NULL) { |
|
113 printf("Bad grammar.\n"); |
|
114 Py_Exit(1); |
|
115 } |
|
116 return g; |
|
117 } |
|
118 |
|
119 /* Can't happen in pgen */ |
|
120 PyObject* |
|
121 PyErr_Occurred() |
|
122 { |
|
123 return 0; |
|
124 } |
|
125 |
|
126 void |
|
127 Py_FatalError(const char *msg) |
|
128 { |
|
129 fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg); |
|
130 Py_Exit(1); |
|
131 } |
|
132 |
|
133 /* No-nonsense my_readline() for tokenizer.c */ |
|
134 |
|
135 char * |
|
136 PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) |
|
137 { |
|
138 size_t n = 1000; |
|
139 char *p = (char *)PyMem_MALLOC(n); |
|
140 char *q; |
|
141 if (p == NULL) |
|
142 return NULL; |
|
143 fprintf(stderr, "%s", prompt); |
|
144 q = fgets(p, n, sys_stdin); |
|
145 if (q == NULL) { |
|
146 *p = '\0'; |
|
147 return p; |
|
148 } |
|
149 n = strlen(p); |
|
150 if (n > 0 && p[n-1] != '\n') |
|
151 p[n-1] = '\n'; |
|
152 return (char *)PyMem_REALLOC(p, n+1); |
|
153 } |
|
154 |
|
155 /* No-nonsense fgets */ |
|
156 char * |
|
157 Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj) |
|
158 { |
|
159 return fgets(buf, n, stream); |
|
160 } |
|
161 |
|
162 |
|
163 #include <stdarg.h> |
|
164 |
|
165 void |
|
166 PySys_WriteStderr(const char *format, ...) |
|
167 { |
|
168 va_list va; |
|
169 |
|
170 va_start(va, format); |
|
171 vfprintf(stderr, format, va); |
|
172 va_end(va); |
|
173 } |