blob: f67abc978f8777b2a2f53af743fe35e3924ea2c7 [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"
9
10static int
11future_check_features(PyFutureFeatures *ff, node *n)
12{
13 int i;
14 char *feature;
15
16 REQ(n, import_stmt); /* must by from __future__ import ... */
17
18 for (i = 3; i < NCH(n); ++i) {
19 feature = STR(CHILD(CHILD(n, i), 0));
20 if (strcmp(feature, FUTURE_NESTED_SCOPES) == 0) {
21 ff->ff_nested_scopes = 1;
22 } else {
23 PyErr_Format(PyExc_SyntaxError,
24 UNDEFINED_FUTURE_FEATURE, feature);
25 return -1;
26 }
27 }
28 return 0;
29}
30
31/* Relevant portions of the grammar:
32
33single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE
34file_input: (NEWLINE | stmt)* ENDMARKER
35stmt: simple_stmt | compound_stmt
36simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
37small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt | assert_stmt
38import_stmt: 'import' dotted_as_name (',' dotted_as_name)* | 'from' dotted_name 'import' ('*' | import_as_name (',' import_as_name)*)
39import_as_name: NAME [NAME NAME]
40dotted_as_name: dotted_name [NAME NAME]
41dotted_name: NAME ('.' NAME)*
42*/
43
44/* future_parse() return values:
45 -1 indicates an error occurred, e.g. unknown feature name
46 0 indicates no feature was found
47 1 indicates a feature was found
48*/
49
50static int
51future_parse(PyFutureFeatures *ff, node *n)
52{
53 int i, r, found;
54 loop:
55
56/* fprintf(stderr, "future_parse(%d, %d, %s)\n",
57 TYPE(n), NCH(n), (n == NULL) ? "NULL" : STR(n));
58*/
59 switch (TYPE(n)) {
60
61 case file_input:
62 for (i = 0; i < NCH(n); i++) {
63 node *ch = CHILD(n, i);
64 if (TYPE(ch) == stmt) {
65 n = ch;
66 goto loop;
67 }
68 }
69 return 0;
70
71 case simple_stmt:
72 if (NCH(n) == 1) {
73 REQ(CHILD(n, 0), small_stmt);
74 n = CHILD(n, 0);
75 goto loop;
76 }
77 found = 0;
78 for (i = 0; i < NCH(n); ++i)
79 if (TYPE(CHILD(n, i)) == small_stmt) {
80 r = future_parse(ff, CHILD(n, i));
81 if (r < 1) {
82 ff->ff_last_lineno = n->n_lineno;
83 ff->ff_n_simple_stmt = i;
84 return r;
85 } else
86 found++;
87 }
88 if (found)
89 return 1;
90 else
91 return 0;
92
93 case stmt:
94 if (TYPE(CHILD(n, 0)) == simple_stmt) {
95 n = CHILD(n, 0);
96 goto loop;
97 } else {
98 REQ(CHILD(n, 0), compound_stmt);
99 ff->ff_last_lineno = n->n_lineno;
100 return 0;
101 }
102
103 case small_stmt:
104 n = CHILD(n, 0);
105 goto loop;
106
107 case import_stmt: {
108 node *name;
109
110 if (STR(CHILD(n, 0))[0] != 'f') { /* from */
111 ff->ff_last_lineno = n->n_lineno;
112 return 0;
113 }
114 name = CHILD(n, 1);
115 if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
116 return 0;
117 if (future_check_features(ff, n) < 0)
118 return -1;
119 return 1;
120 }
121
122 default:
123 ff->ff_last_lineno = n->n_lineno;
124 return 0;
125 }
126}
127
128PyFutureFeatures *
129PyNode_Future(node *n, char *filename)
130{
131 PyFutureFeatures *ff;
132
133 ff = (PyFutureFeatures *)PyMem_Malloc(sizeof(PyFutureFeatures));
134 if (ff == NULL)
135 return NULL;
136 ff->ff_last_lineno = 0;
137 ff->ff_n_simple_stmt = -1;
138 ff->ff_nested_scopes = 0;
139
140 if (future_parse(ff, n) < 0) {
141 PyMem_Free((void *)ff);
142 return NULL;
143 }
144 return ff;
145}
146