blob: 6b1c0c55b892cba9ddd751ab260786f045caccdd [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) {
Jeremy Hyltonb857ba22001-08-10 21:41:33 +000033 continue;
Guido van Rossumb09f7ed2001-07-15 21:08:29 +000034 } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
Jeremy Hyltonb857ba22001-08-10 21:41:33 +000035 ff->ff_features |= CO_GENERATOR_ALLOWED;
Guido van Rossum4668b002001-08-08 05:00:18 +000036 } else if (strcmp(feature, FUTURE_DIVISION) == 0) {
Jeremy Hyltonb857ba22001-08-10 21:41:33 +000037 ff->ff_features |= CO_FUTURE_DIVISION;
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000038 } else if (strcmp(feature, "braces") == 0) {
39 PyErr_SetString(PyExc_SyntaxError,
40 "not a chance");
41 PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
42 return -1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000043 } else {
44 PyErr_Format(PyExc_SyntaxError,
45 UNDEFINED_FUTURE_FEATURE, feature);
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000046 PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
Jeremy Hylton4db62b12001-02-27 19:07:02 +000047 return -1;
48 }
49 }
50 return 0;
51}
52
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000053static void
54future_error(node *n, char *filename)
55{
56 PyErr_SetString(PyExc_SyntaxError,
57 "from __future__ imports must occur at the "
58 "beginning of the file");
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000059 PyErr_SyntaxLocation(filename, n->n_lineno);
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000060 /* XXX set filename and lineno */
61}
62
Jeremy Hylton4db62b12001-02-27 19:07:02 +000063/* Relevant portions of the grammar:
64
65single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
66file_input: (NEWLINE | stmt)* ENDMARKER
67stmt: simple_stmt | compound_stmt
68simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000069small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt
70 | import_stmt | global_stmt | exec_stmt | assert_stmt
71import_stmt: 'import' dotted_as_name (',' dotted_as_name)*
72 | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000073import_as_name: NAME [NAME NAME]
74dotted_as_name: dotted_name [NAME NAME]
75dotted_name: NAME ('.' NAME)*
76*/
77
78/* future_parse() return values:
79 -1 indicates an error occurred, e.g. unknown feature name
80 0 indicates no feature was found
81 1 indicates a feature was found
82*/
83
84static int
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000085future_parse(PyFutureFeatures *ff, node *n, char *filename)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000086{
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000087 int i, r;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000088 loop:
89
Jeremy Hylton4db62b12001-02-27 19:07:02 +000090 switch (TYPE(n)) {
91
Jeremy Hylton280c81a2001-02-28 02:26:14 +000092 case single_input:
93 if (TYPE(CHILD(n, 0)) == simple_stmt) {
94 n = CHILD(n, 0);
95 goto loop;
96 }
97 return 0;
98
Jeremy Hylton4db62b12001-02-27 19:07:02 +000099 case file_input:
100 for (i = 0; i < NCH(n); i++) {
101 node *ch = CHILD(n, i);
102 if (TYPE(ch) == stmt) {
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000103 r = future_parse(ff, ch, filename);
104 if (!FUTURE_POSSIBLE(ff))
105 return r;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000106 }
107 }
108 return 0;
109
110 case simple_stmt:
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000111 if (NCH(n) == 2) {
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000112 REQ(CHILD(n, 0), small_stmt);
113 n = CHILD(n, 0);
114 goto loop;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000115 } else {
116 /* Deal with the special case of a series of
117 small statements on a single line. If a
118 future statement follows some other
119 statement, the SyntaxError is raised here.
120 In all other cases, the symtable pass
121 raises the exception.
122 */
123 int found = 0, end_of_future = 0;
124
125 for (i = 0; i < NCH(n); i += 2) {
126 if (TYPE(CHILD(n, i)) == small_stmt) {
127 r = future_parse(ff, CHILD(n, i),
128 filename);
129 if (r < 1)
130 end_of_future = 1;
131 else {
132 found = 1;
133 if (end_of_future) {
134 future_error(n,
135 filename);
136 return -1;
137 }
138 }
139 }
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000140 }
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000141
142 /* If we found one and only one, then the
143 current lineno is legal.
144 */
145 if (found)
146 ff->ff_last_lineno = n->n_lineno + 1;
147 else
148 ff->ff_last_lineno = n->n_lineno;
149
150 if (end_of_future && found)
151 return 1;
152 else
153 return 0;
154 }
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000155
156 case stmt:
157 if (TYPE(CHILD(n, 0)) == simple_stmt) {
158 n = CHILD(n, 0);
159 goto loop;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000160 } else if (TYPE(CHILD(n, 0)) == expr_stmt) {
161 n = CHILD(n, 0);
162 goto loop;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000163 } else {
164 REQ(CHILD(n, 0), compound_stmt);
165 ff->ff_last_lineno = n->n_lineno;
166 return 0;
167 }
168
169 case small_stmt:
170 n = CHILD(n, 0);
171 goto loop;
172
173 case import_stmt: {
174 node *name;
175
176 if (STR(CHILD(n, 0))[0] != 'f') { /* from */
177 ff->ff_last_lineno = n->n_lineno;
178 return 0;
179 }
180 name = CHILD(n, 1);
181 if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
182 return 0;
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000183 if (future_check_features(ff, n, filename) < 0)
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000184 return -1;
Jeremy Hylton280c81a2001-02-28 02:26:14 +0000185 ff->ff_last_lineno = n->n_lineno + 1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000186 return 1;
187 }
188
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000189 /* The cases below -- all of them! -- are necessary to find
190 and skip doc strings. */
191 case expr_stmt:
192 case testlist:
193 case test:
194 case and_test:
195 case not_test:
196 case comparison:
197 case expr:
198 case xor_expr:
199 case and_expr:
200 case shift_expr:
201 case arith_expr:
202 case term:
203 case factor:
204 case power:
205 if (NCH(n) == 1) {
206 n = CHILD(n, 0);
207 goto loop;
208 }
209 break;
210
211 case atom:
212 if (TYPE(CHILD(n, 0)) == STRING
213 && ff->ff_found_docstring == 0) {
214 ff->ff_found_docstring = 1;
215 return 0;
216 }
217 ff->ff_last_lineno = n->n_lineno;
218 return 0;
219
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000220 default:
221 ff->ff_last_lineno = n->n_lineno;
222 return 0;
223 }
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000224 return 0;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000225}
226
227PyFutureFeatures *
228PyNode_Future(node *n, char *filename)
229{
230 PyFutureFeatures *ff;
231
232 ff = (PyFutureFeatures *)PyMem_Malloc(sizeof(PyFutureFeatures));
233 if (ff == NULL)
234 return NULL;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000235 ff->ff_found_docstring = 0;
236 ff->ff_last_lineno = -1;
Jeremy Hyltonb857ba22001-08-10 21:41:33 +0000237 ff->ff_features = 0;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000238
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000239 if (future_parse(ff, n, filename) < 0) {
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000240 PyMem_Free((void *)ff);
241 return NULL;
242 }
243 return ff;
244}
245