blob: cf2dca5ea5acd8555e875a9f1d0a2492653e6bd5 [file] [log] [blame]
Jeremy Hylton4db62b12001-02-27 19:07:02 +00001#include "Python.h"
2#include "node.h"
3#include "token.h"
4#include "graminit.h"
5#include "compile.h"
6#include "symtable.h"
7
8#define UNDEFINED_FUTURE_FEATURE "future feature %.100s is not defined"
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +00009#define FUTURE_IMPORT_STAR "future statement does not support import *"
Jeremy Hylton4db62b12001-02-27 19:07:02 +000010
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000011#define FUTURE_POSSIBLE(FF) ((FF)->ff_last_lineno == -1)
12
Jeremy Hylton4db62b12001-02-27 19:07:02 +000013static int
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000014future_check_features(PyFutureFeatures *ff, node *n, char *filename)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000015{
16 int i;
17 char *feature;
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000018 node *ch;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000019
20 REQ(n, import_stmt); /* must by from __future__ import ... */
21
Fred Drake198457a2001-03-10 02:15:37 +000022 for (i = 3; i < NCH(n); i += 2) {
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000023 ch = CHILD(n, i);
24 if (TYPE(ch) == STAR) {
25 PyErr_SetString(PyExc_SyntaxError,
26 FUTURE_IMPORT_STAR);
27 PyErr_SyntaxLocation(filename, ch->n_lineno);
28 return -1;
29 }
30 REQ(ch, import_as_name);
31 feature = STR(CHILD(ch, 0));
Jeremy Hylton4db62b12001-02-27 19:07:02 +000032 if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
33 ff->ff_nested_scopes = 1;
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000034 } else if (strcmp(feature, "braces") == 0) {
35 PyErr_SetString(PyExc_SyntaxError,
36 "not a chance");
37 PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
38 return -1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000039 } else {
40 PyErr_Format(PyExc_SyntaxError,
41 UNDEFINED_FUTURE_FEATURE, feature);
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000042 PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
Jeremy Hylton4db62b12001-02-27 19:07:02 +000043 return -1;
44 }
45 }
46 return 0;
47}
48
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000049static void
50future_error(node *n, char *filename)
51{
52 PyErr_SetString(PyExc_SyntaxError,
53 "from __future__ imports must occur at the "
54 "beginning of the file");
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000055 PyErr_SyntaxLocation(filename, n->n_lineno);
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000056 /* XXX set filename and lineno */
57}
58
Jeremy Hylton4db62b12001-02-27 19:07:02 +000059/* Relevant portions of the grammar:
60
61single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
62file_input: (NEWLINE | stmt)* ENDMARKER
63stmt: simple_stmt | compound_stmt
64simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000065small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt
66 | import_stmt | global_stmt | exec_stmt | assert_stmt
67import_stmt: 'import' dotted_as_name (',' dotted_as_name)*
68 | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000069import_as_name: NAME [NAME NAME]
70dotted_as_name: dotted_name [NAME NAME]
71dotted_name: NAME ('.' NAME)*
72*/
73
74/* future_parse() return values:
75 -1 indicates an error occurred, e.g. unknown feature name
76 0 indicates no feature was found
77 1 indicates a feature was found
78*/
79
80static int
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000081future_parse(PyFutureFeatures *ff, node *n, char *filename)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000082{
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000083 int i, r;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000084 loop:
85
Jeremy Hylton4db62b12001-02-27 19:07:02 +000086 switch (TYPE(n)) {
87
Jeremy Hylton280c81a2001-02-28 02:26:14 +000088 case single_input:
89 if (TYPE(CHILD(n, 0)) == simple_stmt) {
90 n = CHILD(n, 0);
91 goto loop;
92 }
93 return 0;
94
Jeremy Hylton4db62b12001-02-27 19:07:02 +000095 case file_input:
96 for (i = 0; i < NCH(n); i++) {
97 node *ch = CHILD(n, i);
98 if (TYPE(ch) == stmt) {
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000099 r = future_parse(ff, ch, filename);
100 if (!FUTURE_POSSIBLE(ff))
101 return r;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000102 }
103 }
104 return 0;
105
106 case simple_stmt:
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000107 if (NCH(n) == 2) {
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000108 REQ(CHILD(n, 0), small_stmt);
109 n = CHILD(n, 0);
110 goto loop;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000111 } else {
112 /* Deal with the special case of a series of
113 small statements on a single line. If a
114 future statement follows some other
115 statement, the SyntaxError is raised here.
116 In all other cases, the symtable pass
117 raises the exception.
118 */
119 int found = 0, end_of_future = 0;
120
121 for (i = 0; i < NCH(n); i += 2) {
122 if (TYPE(CHILD(n, i)) == small_stmt) {
123 r = future_parse(ff, CHILD(n, i),
124 filename);
125 if (r < 1)
126 end_of_future = 1;
127 else {
128 found = 1;
129 if (end_of_future) {
130 future_error(n,
131 filename);
132 return -1;
133 }
134 }
135 }
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000136 }
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000137
138 /* If we found one and only one, then the
139 current lineno is legal.
140 */
141 if (found)
142 ff->ff_last_lineno = n->n_lineno + 1;
143 else
144 ff->ff_last_lineno = n->n_lineno;
145
146 if (end_of_future && found)
147 return 1;
148 else
149 return 0;
150 }
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000151
152 case stmt:
153 if (TYPE(CHILD(n, 0)) == simple_stmt) {
154 n = CHILD(n, 0);
155 goto loop;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000156 } else if (TYPE(CHILD(n, 0)) == expr_stmt) {
157 n = CHILD(n, 0);
158 goto loop;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000159 } else {
160 REQ(CHILD(n, 0), compound_stmt);
161 ff->ff_last_lineno = n->n_lineno;
162 return 0;
163 }
164
165 case small_stmt:
166 n = CHILD(n, 0);
167 goto loop;
168
169 case import_stmt: {
170 node *name;
171
172 if (STR(CHILD(n, 0))[0] != 'f') { /* from */
173 ff->ff_last_lineno = n->n_lineno;
174 return 0;
175 }
176 name = CHILD(n, 1);
177 if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
178 return 0;
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000179 if (future_check_features(ff, n, filename) < 0)
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000180 return -1;
Jeremy Hylton280c81a2001-02-28 02:26:14 +0000181 ff->ff_last_lineno = n->n_lineno + 1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000182 return 1;
183 }
184
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000185 /* The cases below -- all of them! -- are necessary to find
186 and skip doc strings. */
187 case expr_stmt:
188 case testlist:
189 case test:
190 case and_test:
191 case not_test:
192 case comparison:
193 case expr:
194 case xor_expr:
195 case and_expr:
196 case shift_expr:
197 case arith_expr:
198 case term:
199 case factor:
200 case power:
201 if (NCH(n) == 1) {
202 n = CHILD(n, 0);
203 goto loop;
204 }
205 break;
206
207 case atom:
208 if (TYPE(CHILD(n, 0)) == STRING
209 && ff->ff_found_docstring == 0) {
210 ff->ff_found_docstring = 1;
211 return 0;
212 }
213 ff->ff_last_lineno = n->n_lineno;
214 return 0;
215
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000216 default:
217 ff->ff_last_lineno = n->n_lineno;
218 return 0;
219 }
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000220 return 0;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000221}
222
223PyFutureFeatures *
224PyNode_Future(node *n, char *filename)
225{
226 PyFutureFeatures *ff;
227
228 ff = (PyFutureFeatures *)PyMem_Malloc(sizeof(PyFutureFeatures));
229 if (ff == NULL)
230 return NULL;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000231 ff->ff_found_docstring = 0;
232 ff->ff_last_lineno = -1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000233 ff->ff_nested_scopes = 0;
234
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000235 if (future_parse(ff, n, filename) < 0) {
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000236 PyMem_Free((void *)ff);
237 return NULL;
238 }
239 return ff;
240}
241