blob: 70be26b548523ef506603fc4c7e76993619c7f1a [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;
Guido van Rossumb09f7ed2001-07-15 21:08:29 +000034 } else if (strcmp(feature, FUTURE_GENERATORS) == 0) {
35 /* OK; this is processed by the parser */
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000036 } else if (strcmp(feature, "braces") == 0) {
37 PyErr_SetString(PyExc_SyntaxError,
38 "not a chance");
39 PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
40 return -1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000041 } else {
42 PyErr_Format(PyExc_SyntaxError,
43 UNDEFINED_FUTURE_FEATURE, feature);
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000044 PyErr_SyntaxLocation(filename, CHILD(ch, 0)->n_lineno);
Jeremy Hylton4db62b12001-02-27 19:07:02 +000045 return -1;
46 }
47 }
48 return 0;
49}
50
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000051static void
52future_error(node *n, char *filename)
53{
54 PyErr_SetString(PyExc_SyntaxError,
55 "from __future__ imports must occur at the "
56 "beginning of the file");
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000057 PyErr_SyntaxLocation(filename, n->n_lineno);
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000058 /* XXX set filename and lineno */
59}
60
Jeremy Hylton4db62b12001-02-27 19:07:02 +000061/* Relevant portions of the grammar:
62
63single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
64file_input: (NEWLINE | stmt)* ENDMARKER
65stmt: simple_stmt | compound_stmt
66simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +000067small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt
68 | import_stmt | global_stmt | exec_stmt | assert_stmt
69import_stmt: 'import' dotted_as_name (',' dotted_as_name)*
70 | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000071import_as_name: NAME [NAME NAME]
72dotted_as_name: dotted_name [NAME NAME]
73dotted_name: NAME ('.' NAME)*
74*/
75
76/* future_parse() return values:
77 -1 indicates an error occurred, e.g. unknown feature name
78 0 indicates no feature was found
79 1 indicates a feature was found
80*/
81
82static int
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000083future_parse(PyFutureFeatures *ff, node *n, char *filename)
Jeremy Hylton4db62b12001-02-27 19:07:02 +000084{
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +000085 int i, r;
Jeremy Hylton4db62b12001-02-27 19:07:02 +000086 loop:
87
Jeremy Hylton4db62b12001-02-27 19:07:02 +000088 switch (TYPE(n)) {
89
Jeremy Hylton280c81a2001-02-28 02:26:14 +000090 case single_input:
91 if (TYPE(CHILD(n, 0)) == simple_stmt) {
92 n = CHILD(n, 0);
93 goto loop;
94 }
95 return 0;
96
Jeremy Hylton4db62b12001-02-27 19:07:02 +000097 case file_input:
98 for (i = 0; i < NCH(n); i++) {
99 node *ch = CHILD(n, i);
100 if (TYPE(ch) == stmt) {
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000101 r = future_parse(ff, ch, filename);
102 if (!FUTURE_POSSIBLE(ff))
103 return r;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000104 }
105 }
106 return 0;
107
108 case simple_stmt:
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000109 if (NCH(n) == 2) {
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000110 REQ(CHILD(n, 0), small_stmt);
111 n = CHILD(n, 0);
112 goto loop;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000113 } else {
114 /* Deal with the special case of a series of
115 small statements on a single line. If a
116 future statement follows some other
117 statement, the SyntaxError is raised here.
118 In all other cases, the symtable pass
119 raises the exception.
120 */
121 int found = 0, end_of_future = 0;
122
123 for (i = 0; i < NCH(n); i += 2) {
124 if (TYPE(CHILD(n, i)) == small_stmt) {
125 r = future_parse(ff, CHILD(n, i),
126 filename);
127 if (r < 1)
128 end_of_future = 1;
129 else {
130 found = 1;
131 if (end_of_future) {
132 future_error(n,
133 filename);
134 return -1;
135 }
136 }
137 }
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000138 }
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000139
140 /* If we found one and only one, then the
141 current lineno is legal.
142 */
143 if (found)
144 ff->ff_last_lineno = n->n_lineno + 1;
145 else
146 ff->ff_last_lineno = n->n_lineno;
147
148 if (end_of_future && found)
149 return 1;
150 else
151 return 0;
152 }
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000153
154 case stmt:
155 if (TYPE(CHILD(n, 0)) == simple_stmt) {
156 n = CHILD(n, 0);
157 goto loop;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000158 } else if (TYPE(CHILD(n, 0)) == expr_stmt) {
159 n = CHILD(n, 0);
160 goto loop;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000161 } else {
162 REQ(CHILD(n, 0), compound_stmt);
163 ff->ff_last_lineno = n->n_lineno;
164 return 0;
165 }
166
167 case small_stmt:
168 n = CHILD(n, 0);
169 goto loop;
170
171 case import_stmt: {
172 node *name;
173
174 if (STR(CHILD(n, 0))[0] != 'f') { /* from */
175 ff->ff_last_lineno = n->n_lineno;
176 return 0;
177 }
178 name = CHILD(n, 1);
179 if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
180 return 0;
Jeremy Hyltonad3d3f22001-02-28 17:47:12 +0000181 if (future_check_features(ff, n, filename) < 0)
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000182 return -1;
Jeremy Hylton280c81a2001-02-28 02:26:14 +0000183 ff->ff_last_lineno = n->n_lineno + 1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000184 return 1;
185 }
186
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000187 /* The cases below -- all of them! -- are necessary to find
188 and skip doc strings. */
189 case expr_stmt:
190 case testlist:
191 case test:
192 case and_test:
193 case not_test:
194 case comparison:
195 case expr:
196 case xor_expr:
197 case and_expr:
198 case shift_expr:
199 case arith_expr:
200 case term:
201 case factor:
202 case power:
203 if (NCH(n) == 1) {
204 n = CHILD(n, 0);
205 goto loop;
206 }
207 break;
208
209 case atom:
210 if (TYPE(CHILD(n, 0)) == STRING
211 && ff->ff_found_docstring == 0) {
212 ff->ff_found_docstring = 1;
213 return 0;
214 }
215 ff->ff_last_lineno = n->n_lineno;
216 return 0;
217
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000218 default:
219 ff->ff_last_lineno = n->n_lineno;
220 return 0;
221 }
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000222 return 0;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000223}
224
225PyFutureFeatures *
226PyNode_Future(node *n, char *filename)
227{
228 PyFutureFeatures *ff;
229
230 ff = (PyFutureFeatures *)PyMem_Malloc(sizeof(PyFutureFeatures));
231 if (ff == NULL)
232 return NULL;
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000233 ff->ff_found_docstring = 0;
234 ff->ff_last_lineno = -1;
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000235 ff->ff_nested_scopes = 0;
236
Jeremy Hylton39e2f3f2001-02-28 01:58:08 +0000237 if (future_parse(ff, n, filename) < 0) {
Jeremy Hylton4db62b12001-02-27 19:07:02 +0000238 PyMem_Free((void *)ff);
239 return NULL;
240 }
241 return ff;
242}
243