blob: 6494a9381cf88a4e5896c2817f24bcc5e1e4038f [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00002/* Parser-tokenizer link implementation */
3
Guido van Rossum3f5da241990-12-20 15:06:42 +00004#include "pgenheaders.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +00005#include "tokenizer.h"
6#include "node.h"
7#include "grammar.h"
8#include "parser.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +00009#include "parsetok.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000010#include "errcode.h"
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +000011#include "graminit.h"
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000012
Guido van Rossum6135df61998-04-10 19:35:06 +000013int Py_TabcheckFlag;
14
Guido van Rossum3f5da241990-12-20 15:06:42 +000015
16/* Forward */
Tim Petersfe2127d2001-07-16 05:37:24 +000017static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int);
Martin v. Löwis95292d62002-12-11 14:04:59 +000018static void initerr(perrdetail *err_ret, const char* filename);
Guido van Rossum3f5da241990-12-20 15:06:42 +000019
20/* Parse input coming from a string. Return error code, print some errors. */
Guido van Rossumbd0389d1994-08-29 12:25:45 +000021node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000022PyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000023{
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000024 return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +000025}
26
27node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000028PyParser_ParseStringFlags(const char *s, grammar *g, int start,
Tim Petersfe2127d2001-07-16 05:37:24 +000029 perrdetail *err_ret, int flags)
30{
Thomas Heller6b17abf2002-07-09 09:23:27 +000031 return PyParser_ParseStringFlagsFilename(s, NULL,
Neal Norwitz4ded4b52004-07-08 01:54:07 +000032 g, start, err_ret, flags);
Thomas Heller6b17abf2002-07-09 09:23:27 +000033}
34
35node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000036PyParser_ParseStringFlagsFilename(const char *s, const char *filename,
Thomas Heller6b17abf2002-07-09 09:23:27 +000037 grammar *g, int start,
38 perrdetail *err_ret, int flags)
39{
Guido van Rossumbd0389d1994-08-29 12:25:45 +000040 struct tok_state *tok;
41
Thomas Heller6b17abf2002-07-09 09:23:27 +000042 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000043
Guido van Rossum86bea461997-04-29 21:03:06 +000044 if ((tok = PyTokenizer_FromString(s)) == NULL) {
Neal Norwitz40d37812005-10-02 01:48:49 +000045 err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000046 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +000047 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +000048
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +000049 tok->filename = filename ? filename : "<string>";
Guido van Rossum89ce4541998-12-21 18:32:40 +000050 if (Py_TabcheckFlag || Py_VerboseFlag) {
Guido van Rossum89ce4541998-12-21 18:32:40 +000051 tok->altwarning = (tok->filename != NULL);
52 if (Py_TabcheckFlag >= 2)
53 tok->alterror++;
54 }
55
Tim Petersfe2127d2001-07-16 05:37:24 +000056 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossum3f5da241990-12-20 15:06:42 +000057}
58
Guido van Rossum3f5da241990-12-20 15:06:42 +000059/* Parse input coming from a file. Return error code, print some errors. */
60
Guido van Rossumbd0389d1994-08-29 12:25:45 +000061node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000062PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
Thomas Wouters23c9e002000-07-22 19:20:54 +000063 char *ps1, char *ps2, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000064{
Tim Petersfe2127d2001-07-16 05:37:24 +000065 return PyParser_ParseFileFlags(fp, filename, g, start, ps1, ps2,
66 err_ret, 0);
67}
68
69node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000070PyParser_ParseFileFlags(FILE *fp, const char *filename, grammar *g, int start,
Tim Petersfe2127d2001-07-16 05:37:24 +000071 char *ps1, char *ps2, perrdetail *err_ret, int flags)
72{
Guido van Rossumbd0389d1994-08-29 12:25:45 +000073 struct tok_state *tok;
74
Martin v. Löwis16eff6f2002-01-05 21:40:08 +000075 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000076
Guido van Rossum86bea461997-04-29 21:03:06 +000077 if ((tok = PyTokenizer_FromFile(fp, ps1, ps2)) == NULL) {
Guido van Rossumbd0389d1994-08-29 12:25:45 +000078 err_ret->error = E_NOMEM;
79 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +000080 }
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +000081 tok->filename = filename;
Guido van Rossum6135df61998-04-10 19:35:06 +000082 if (Py_TabcheckFlag || Py_VerboseFlag) {
Guido van Rossum6135df61998-04-10 19:35:06 +000083 tok->altwarning = (filename != NULL);
84 if (Py_TabcheckFlag >= 2)
85 tok->alterror++;
86 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +000087
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000088
Tim Petersfe2127d2001-07-16 05:37:24 +000089 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000090}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +000091
92/* Parse input coming from the given tokenizer structure.
93 Return error code. */
94
Thomas Wouters34aa7ba2006-02-28 19:02:24 +000095static char with_msg[] =
96"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
97
98static char as_msg[] =
99"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
100
101static void
102warn(const char *msg, const char *filename, int lineno)
103{
104 if (filename == NULL)
105 filename = "<string>";
106 PySys_WriteStderr(msg, filename, lineno);
107}
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000108
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000109static node *
Tim Petersfe2127d2001-07-16 05:37:24 +0000110parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
111 int flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000112{
113 parser_state *ps;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000114 node *n;
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000115 int started = 0, handling_import = 0, handling_with = 0;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000116
Guido van Rossum86bea461997-04-29 21:03:06 +0000117 if ((ps = PyParser_New(g, start)) == NULL) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000118 fprintf(stderr, "no mem for new parser\n");
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000119 err_ret->error = E_NOMEM;
Neal Norwitz56c65612005-11-15 04:54:23 +0000120 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000121 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000122 }
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000123#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
124 if (flags & PyPARSE_WITH_IS_KEYWORD)
125 ps->p_flags |= CO_FUTURE_WITH_STATEMENT;
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000126#endif
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000127
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000128 for (;;) {
129 char *a, *b;
130 int type;
Guido van Rossum6da34342000-06-28 22:00:02 +0000131 size_t len;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000132 char *str;
Martin v. Löwis49c5da12006-03-01 22:49:05 +0000133 int col_offset;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000134
Guido van Rossum86bea461997-04-29 21:03:06 +0000135 type = PyTokenizer_Get(tok, &a, &b);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000136 if (type == ERRORTOKEN) {
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000137 err_ret->error = tok->done;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000138 break;
139 }
Guido van Rossumd8b1d371992-03-04 16:40:44 +0000140 if (type == ENDMARKER && started) {
141 type = NEWLINE; /* Add an extra newline */
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000142 handling_with = handling_import = 0;
Guido van Rossumd8b1d371992-03-04 16:40:44 +0000143 started = 0;
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000144 /* Add the right number of dedent tokens,
145 except if a certain flag is given --
146 codeop.py uses this. */
147 if (tok->indent &&
148 !(flags & PyPARSE_DONT_IMPLY_DEDENT))
149 {
150 tok->pendin = -tok->indent;
151 tok->indent = 0;
152 }
Guido van Rossumd8b1d371992-03-04 16:40:44 +0000153 }
154 else
155 started = 1;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000156 len = b - a; /* XXX this may compute NULL - NULL */
Andrew MacIntyre80d4e2a2002-08-04 06:28:21 +0000157 str = (char *) PyObject_MALLOC(len + 1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000158 if (str == NULL) {
159 fprintf(stderr, "no mem for next token\n");
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000160 err_ret->error = E_NOMEM;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000161 break;
162 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000163 if (len > 0)
164 strncpy(str, a, len);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000165 str[len] = '\0';
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000166
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000167#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
168 /* This is only necessary to support the "as" warning, but
169 we don't want to warn about "as" in import statements. */
170 if (type == NAME &&
171 len == 6 && str[0] == 'i' && strcmp(str, "import") == 0)
172 handling_import = 1;
173
174 /* Warn about with as NAME */
175 if (type == NAME &&
176 !(ps->p_flags & CO_FUTURE_WITH_STATEMENT)) {
177 if (len == 4 && str[0] == 'w' && strcmp(str, "with") == 0)
178 warn(with_msg, err_ret->filename, tok->lineno);
179 else if (!(handling_import || handling_with) &&
Thomas Wouters8ae12952006-02-28 22:42:15 +0000180 len == 2 && str[0] == 'a' &&
181 strcmp(str, "as") == 0)
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000182 warn(as_msg, err_ret->filename, tok->lineno);
183 }
184 else if (type == NAME &&
185 (ps->p_flags & CO_FUTURE_WITH_STATEMENT) &&
186 len == 4 && str[0] == 'w' && strcmp(str, "with") == 0)
187 handling_with = 1;
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000188#endif
Martin v. Löwis49c5da12006-03-01 22:49:05 +0000189 if (a >= tok->line_start)
190 col_offset = a - tok->line_start;
191 else
192 col_offset = -1;
193
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000194 if ((err_ret->error =
Martin v. Löwis49c5da12006-03-01 22:49:05 +0000195 PyParser_AddToken(ps, (int)type, str, tok->lineno, col_offset,
Fred Drake85f36392000-07-11 17:53:00 +0000196 &(err_ret->expected))) != E_OK) {
Martin v. Löwis77736712006-05-04 05:51:03 +0000197 if (err_ret->error != E_DONE) {
Andrew MacIntyre80d4e2a2002-08-04 06:28:21 +0000198 PyObject_FREE(str);
Martin v. Löwis77736712006-05-04 05:51:03 +0000199 err_ret->token = type;
200 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000201 break;
Guido van Rossumff0ec521997-07-27 01:52:50 +0000202 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000203 }
204
205 if (err_ret->error == E_DONE) {
206 n = ps->p_tree;
207 ps->p_tree = NULL;
208 }
209 else
210 n = NULL;
211
Guido van Rossum86bea461997-04-29 21:03:06 +0000212 PyParser_Delete(ps);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000213
214 if (n == NULL) {
215 if (tok->lineno <= 1 && tok->done == E_EOF)
216 err_ret->error = E_EOF;
217 err_ret->lineno = tok->lineno;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000218 if (tok->buf != NULL) {
Martin v. Löwisfc787d52007-09-04 14:20:25 +0000219 char *text = NULL;
Martin v. Löwisa87c4452006-02-15 19:56:18 +0000220 size_t len;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000221 assert(tok->cur - tok->buf < INT_MAX);
222 err_ret->offset = (int)(tok->cur - tok->buf);
Martin v. Löwisa87c4452006-02-15 19:56:18 +0000223 len = tok->inp - tok->buf;
Martin v. Löwisfc787d52007-09-04 14:20:25 +0000224#ifdef Py_USING_UNICODE
225 text = PyTokenizer_RestoreEncoding(tok, len, &err_ret->offset);
226
227#endif
228 if (text == NULL) {
229 text = (char *) PyObject_MALLOC(len + 1);
230 if (text != NULL) {
231 if (len > 0)
232 strncpy(text, tok->buf, len);
233 text[len] = '\0';
234 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000235 }
Martin v. Löwisfc787d52007-09-04 14:20:25 +0000236 err_ret->text = text;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000237 }
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +0000238 } else if (tok->encoding != NULL) {
239 node* r = PyNode_New(encoding_decl);
Neal Norwitz6bf1a8f2006-08-12 01:49:12 +0000240 if (!r) {
241 err_ret->error = E_NOMEM;
242 n = NULL;
243 goto done;
244 }
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +0000245 r->n_str = tok->encoding;
246 r->n_nchildren = 1;
247 r->n_child = n;
248 tok->encoding = NULL;
249 n = r;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000250 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000251
Neal Norwitz6bf1a8f2006-08-12 01:49:12 +0000252done:
Guido van Rossum86bea461997-04-29 21:03:06 +0000253 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000254
255 return n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000256}
Guido van Rossum0c156a52001-10-20 14:27:56 +0000257
258static void
Jeremy Hylton3e0055f2005-10-20 19:59:25 +0000259initerr(perrdetail *err_ret, const char *filename)
Guido van Rossum0c156a52001-10-20 14:27:56 +0000260{
261 err_ret->error = E_OK;
Martin v. Löwis16eff6f2002-01-05 21:40:08 +0000262 err_ret->filename = filename;
Guido van Rossum0c156a52001-10-20 14:27:56 +0000263 err_ret->lineno = 0;
264 err_ret->offset = 0;
265 err_ret->text = NULL;
266 err_ret->token = -1;
267 err_ret->expected = -1;
268}