Line data Source code
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 : #define PGEN
17 :
18 : #include "Python.h"
19 : #include "pgenheaders.h"
20 : #include "grammar.h"
21 : #include "node.h"
22 : #include "parsetok.h"
23 : #include "pgen.h"
24 :
25 : int Py_DebugFlag;
26 : int Py_VerboseFlag;
27 : int Py_IgnoreEnvironmentFlag;
28 :
29 : /* Forward */
30 : grammar *getgrammar(char *filename);
31 :
32 : void Py_Exit(int) _Py_NO_RETURN;
33 :
34 : void
35 0 : Py_Exit(int sts)
36 : {
37 0 : exit(sts);
38 : }
39 :
40 : int
41 0 : main(int argc, char **argv)
42 : {
43 : grammar *g;
44 : FILE *fp;
45 : char *filename, *graminit_h, *graminit_c;
46 :
47 0 : if (argc != 4) {
48 0 : fprintf(stderr,
49 : "usage: %s grammar graminit.h graminit.c\n", argv[0]);
50 0 : Py_Exit(2);
51 : }
52 0 : filename = argv[1];
53 0 : graminit_h = argv[2];
54 0 : graminit_c = argv[3];
55 0 : g = getgrammar(filename);
56 0 : fp = fopen(graminit_c, "w");
57 0 : if (fp == NULL) {
58 0 : perror(graminit_c);
59 0 : Py_Exit(1);
60 : }
61 0 : if (Py_DebugFlag)
62 0 : printf("Writing %s ...\n", graminit_c);
63 0 : printgrammar(g, fp);
64 0 : fclose(fp);
65 0 : fp = fopen(graminit_h, "w");
66 0 : if (fp == NULL) {
67 0 : perror(graminit_h);
68 0 : Py_Exit(1);
69 : }
70 0 : if (Py_DebugFlag)
71 0 : printf("Writing %s ...\n", graminit_h);
72 0 : printnonterminals(g, fp);
73 0 : fclose(fp);
74 0 : Py_Exit(0);
75 0 : return 0; /* Make gcc -Wall happy */
76 : }
77 :
78 : grammar *
79 0 : getgrammar(char *filename)
80 : {
81 : FILE *fp;
82 : node *n;
83 : grammar *g0, *g;
84 : perrdetail err;
85 :
86 0 : fp = fopen(filename, "r");
87 0 : if (fp == NULL) {
88 0 : perror(filename);
89 0 : Py_Exit(1);
90 : }
91 0 : g0 = meta_grammar();
92 0 : n = PyParser_ParseFile(fp, filename, g0, g0->g_start,
93 : (char *)NULL, (char *)NULL, &err);
94 0 : fclose(fp);
95 0 : if (n == NULL) {
96 0 : fprintf(stderr, "Parsing error %d, line %d.\n",
97 : err.error, err.lineno);
98 0 : if (err.text != NULL) {
99 : size_t i;
100 0 : fprintf(stderr, "%s", err.text);
101 0 : i = strlen(err.text);
102 0 : if (i == 0 || err.text[i-1] != '\n')
103 0 : fprintf(stderr, "\n");
104 0 : for (i = 0; i < err.offset; i++) {
105 0 : if (err.text[i] == '\t')
106 0 : putc('\t', stderr);
107 : else
108 0 : putc(' ', stderr);
109 : }
110 0 : fprintf(stderr, "^\n");
111 0 : PyObject_FREE(err.text);
112 : }
113 0 : Py_Exit(1);
114 : }
115 0 : g = pgen(n);
116 0 : if (g == NULL) {
117 0 : printf("Bad grammar.\n");
118 0 : Py_Exit(1);
119 : }
120 0 : return g;
121 : }
122 :
123 : /* Can't happen in pgen */
124 : PyObject*
125 0 : PyErr_Occurred()
126 : {
127 0 : return 0;
128 : }
129 :
130 : void
131 0 : Py_FatalError(const char *msg)
132 : {
133 0 : fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
134 0 : Py_Exit(1);
135 0 : }
136 :
137 : /* No-nonsense my_readline() for tokenizer.c */
138 :
139 : char *
140 0 : PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
141 : {
142 0 : size_t n = 1000;
143 0 : char *p = (char *)PyMem_MALLOC(n);
144 : char *q;
145 0 : if (p == NULL)
146 0 : return NULL;
147 0 : fprintf(stderr, "%s", prompt);
148 0 : q = fgets(p, n, sys_stdin);
149 0 : if (q == NULL) {
150 0 : *p = '\0';
151 0 : return p;
152 : }
153 0 : n = strlen(p);
154 0 : if (n > 0 && p[n-1] != '\n')
155 0 : p[n-1] = '\n';
156 0 : return (char *)PyMem_REALLOC(p, n+1);
157 : }
158 :
159 : /* No-nonsense fgets */
160 : char *
161 0 : Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
162 : {
163 0 : return fgets(buf, n, stream);
164 : }
165 :
166 :
167 : #include <stdarg.h>
168 :
169 : void
170 0 : PySys_WriteStderr(const char *format, ...)
171 : {
172 : va_list va;
173 :
174 0 : va_start(va, format);
175 0 : vfprintf(stderr, format, va);
176 0 : va_end(va);
177 0 : }
|