blob: 4c3b5065e33f7a9fb38c2733cc75107139272885 [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 Rossum3f5da241990-12-20 15:06:42 +000013
14/* Forward */
Christian Heimes4d6ec852008-03-26 22:34:47 +000015static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
Martin v. Löwis95292d62002-12-11 14:04:59 +000016static void initerr(perrdetail *err_ret, const char* filename);
Guido van Rossum3f5da241990-12-20 15:06:42 +000017
18/* Parse input coming from a string. Return error code, print some errors. */
Guido van Rossumbd0389d1994-08-29 12:25:45 +000019node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000020PyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000021{
Jeremy Hylton3e0055f2005-10-20 19:59:25 +000022 return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +000023}
24
25node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000026PyParser_ParseStringFlags(const char *s, grammar *g, int start,
Tim Petersfe2127d2001-07-16 05:37:24 +000027 perrdetail *err_ret, int flags)
28{
Thomas Heller6b17abf2002-07-09 09:23:27 +000029 return PyParser_ParseStringFlagsFilename(s, NULL,
Neal Norwitz4ded4b52004-07-08 01:54:07 +000030 g, start, err_ret, flags);
Thomas Heller6b17abf2002-07-09 09:23:27 +000031}
32
33node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000034PyParser_ParseStringFlagsFilename(const char *s, const char *filename,
Thomas Heller6b17abf2002-07-09 09:23:27 +000035 grammar *g, int start,
36 perrdetail *err_ret, int flags)
37{
Christian Heimes4d6ec852008-03-26 22:34:47 +000038 int iflags = flags;
39 return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
40 err_ret, &iflags);
41}
42
43node *
44PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
45 grammar *g, int start,
46 perrdetail *err_ret, int *flags)
47{
Guido van Rossumbd0389d1994-08-29 12:25:45 +000048 struct tok_state *tok;
49
Thomas Heller6b17abf2002-07-09 09:23:27 +000050 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000051
Benjamin Petersonf5b52242009-03-02 23:31:26 +000052 if (*flags & PyPARSE_IGNORE_COOKIE)
53 tok = PyTokenizer_FromUTF8(s);
54 else
55 tok = PyTokenizer_FromString(s);
56 if (tok == NULL) {
Neal Norwitz40d37812005-10-02 01:48:49 +000057 err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000058 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +000059 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +000060
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +000061 tok->filename = filename ? filename : "<string>";
Tim Petersfe2127d2001-07-16 05:37:24 +000062 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossum3f5da241990-12-20 15:06:42 +000063}
64
Guido van Rossum3f5da241990-12-20 15:06:42 +000065/* Parse input coming from a file. Return error code, print some errors. */
66
Guido van Rossumbd0389d1994-08-29 12:25:45 +000067node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000068PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
Thomas Wouters23c9e002000-07-22 19:20:54 +000069 char *ps1, char *ps2, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000070{
Martin v. Löwis85bcc662007-09-04 09:18:06 +000071 return PyParser_ParseFileFlags(fp, filename, NULL,
72 g, start, ps1, ps2, err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +000073}
74
75node *
Christian Heimes4d6ec852008-03-26 22:34:47 +000076PyParser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
Martin v. Löwis85bcc662007-09-04 09:18:06 +000077 grammar *g, int start,
Tim Petersfe2127d2001-07-16 05:37:24 +000078 char *ps1, char *ps2, perrdetail *err_ret, int flags)
79{
Christian Heimes4d6ec852008-03-26 22:34:47 +000080 int iflags = flags;
81 return PyParser_ParseFileFlagsEx(fp, filename, enc, g, start, ps1,
82 ps2, err_ret, &iflags);
83}
84
85node *
86PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
87 const char *enc, grammar *g, int start,
88 char *ps1, char *ps2, perrdetail *err_ret, int *flags)
89{
Guido van Rossumbd0389d1994-08-29 12:25:45 +000090 struct tok_state *tok;
91
Martin v. Löwis16eff6f2002-01-05 21:40:08 +000092 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000093
Brett Cannonfdc1a562007-09-05 20:35:46 +000094 if ((tok = PyTokenizer_FromFile(fp, (char *)enc, ps1, ps2)) == NULL) {
Guido van Rossumbd0389d1994-08-29 12:25:45 +000095 err_ret->error = E_NOMEM;
96 return NULL;
Guido van Rossum3f5da241990-12-20 15:06:42 +000097 }
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +000098 tok->filename = filename;
Tim Petersfe2127d2001-07-16 05:37:24 +000099 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000100}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000101
Neal Norwitze4993c72006-03-16 06:01:25 +0000102#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000103static char with_msg[] =
104"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
105
106static char as_msg[] =
107"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
108
109static void
110warn(const char *msg, const char *filename, int lineno)
111{
112 if (filename == NULL)
113 filename = "<string>";
114 PySys_WriteStderr(msg, filename, lineno);
115}
Neal Norwitzfc85c922006-03-17 05:44:46 +0000116#endif
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000117
Thomas Wouters89f507f2006-12-13 04:49:30 +0000118/* Parse input coming from the given tokenizer structure.
119 Return error code. */
120
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000121static node *
Tim Petersfe2127d2001-07-16 05:37:24 +0000122parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
Christian Heimes4d6ec852008-03-26 22:34:47 +0000123 int *flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000124{
125 parser_state *ps;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000126 node *n;
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000127 int started = 0, handling_import = 0, handling_with = 0;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000128
Guido van Rossum86bea461997-04-29 21:03:06 +0000129 if ((ps = PyParser_New(g, start)) == NULL) {
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000130 fprintf(stderr, "no mem for new parser\n");
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000131 err_ret->error = E_NOMEM;
Neal Norwitz56c65612005-11-15 04:54:23 +0000132 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000133 return NULL;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000134 }
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000135#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Christian Heimes4d6ec852008-03-26 22:34:47 +0000136 if (*flags & PyPARSE_WITH_IS_KEYWORD)
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000137 ps->p_flags |= CO_FUTURE_WITH_STATEMENT;
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000138#endif
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000139
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000140 for (;;) {
141 char *a, *b;
142 int type;
Guido van Rossum6da34342000-06-28 22:00:02 +0000143 size_t len;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000144 char *str;
Martin v. Löwis49c5da12006-03-01 22:49:05 +0000145 int col_offset;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000146
Guido van Rossum86bea461997-04-29 21:03:06 +0000147 type = PyTokenizer_Get(tok, &a, &b);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000148 if (type == ERRORTOKEN) {
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000149 err_ret->error = tok->done;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000150 break;
151 }
Guido van Rossumd8b1d371992-03-04 16:40:44 +0000152 if (type == ENDMARKER && started) {
153 type = NEWLINE; /* Add an extra newline */
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000154 handling_with = handling_import = 0;
Guido van Rossumd8b1d371992-03-04 16:40:44 +0000155 started = 0;
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000156 /* Add the right number of dedent tokens,
157 except if a certain flag is given --
158 codeop.py uses this. */
159 if (tok->indent &&
Christian Heimes4d6ec852008-03-26 22:34:47 +0000160 !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
Guido van Rossum4b499dd32003-02-13 22:07:59 +0000161 {
162 tok->pendin = -tok->indent;
163 tok->indent = 0;
164 }
Guido van Rossumd8b1d371992-03-04 16:40:44 +0000165 }
166 else
167 started = 1;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000168 len = b - a; /* XXX this may compute NULL - NULL */
Andrew MacIntyre80d4e2a2002-08-04 06:28:21 +0000169 str = (char *) PyObject_MALLOC(len + 1);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000170 if (str == NULL) {
171 fprintf(stderr, "no mem for next token\n");
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000172 err_ret->error = E_NOMEM;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000173 break;
174 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000175 if (len > 0)
176 strncpy(str, a, len);
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000177 str[len] = '\0';
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000178
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000179#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
180 /* This is only necessary to support the "as" warning, but
181 we don't want to warn about "as" in import statements. */
182 if (type == NAME &&
183 len == 6 && str[0] == 'i' && strcmp(str, "import") == 0)
184 handling_import = 1;
185
186 /* Warn about with as NAME */
187 if (type == NAME &&
188 !(ps->p_flags & CO_FUTURE_WITH_STATEMENT)) {
189 if (len == 4 && str[0] == 'w' && strcmp(str, "with") == 0)
190 warn(with_msg, err_ret->filename, tok->lineno);
191 else if (!(handling_import || handling_with) &&
Thomas Wouters8ae12952006-02-28 22:42:15 +0000192 len == 2 && str[0] == 'a' &&
193 strcmp(str, "as") == 0)
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000194 warn(as_msg, err_ret->filename, tok->lineno);
195 }
196 else if (type == NAME &&
197 (ps->p_flags & CO_FUTURE_WITH_STATEMENT) &&
198 len == 4 && str[0] == 'w' && strcmp(str, "with") == 0)
199 handling_with = 1;
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000200#endif
Martin v. Löwis49c5da12006-03-01 22:49:05 +0000201 if (a >= tok->line_start)
202 col_offset = a - tok->line_start;
203 else
204 col_offset = -1;
205
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000206 if ((err_ret->error =
Guido van Rossum45aecf42006-03-15 04:58:47 +0000207 PyParser_AddToken(ps, (int)type, str,
208 tok->lineno, col_offset,
Fred Drake85f36392000-07-11 17:53:00 +0000209 &(err_ret->expected))) != E_OK) {
Thomas Wouters477c8d52006-05-27 19:21:47 +0000210 if (err_ret->error != E_DONE) {
Andrew MacIntyre80d4e2a2002-08-04 06:28:21 +0000211 PyObject_FREE(str);
Thomas Wouters477c8d52006-05-27 19:21:47 +0000212 err_ret->token = type;
213 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000214 break;
Guido van Rossumff0ec521997-07-27 01:52:50 +0000215 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000216 }
217
218 if (err_ret->error == E_DONE) {
219 n = ps->p_tree;
220 ps->p_tree = NULL;
221 }
222 else
223 n = NULL;
Christian Heimesb1b3efc2008-03-26 23:24:27 +0000224
Christian Heimes4d6ec852008-03-26 22:34:47 +0000225#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
226 *flags = ps->p_flags;
227#endif
Guido van Rossum86bea461997-04-29 21:03:06 +0000228 PyParser_Delete(ps);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000229
230 if (n == NULL) {
231 if (tok->lineno <= 1 && tok->done == E_EOF)
232 err_ret->error = E_EOF;
233 err_ret->lineno = tok->lineno;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000234 if (tok->buf != NULL) {
Martin v. Löwisa87c4452006-02-15 19:56:18 +0000235 size_t len;
Martin v. Löwis18e16552006-02-15 17:27:45 +0000236 assert(tok->cur - tok->buf < INT_MAX);
237 err_ret->offset = (int)(tok->cur - tok->buf);
Martin v. Löwisa87c4452006-02-15 19:56:18 +0000238 len = tok->inp - tok->buf;
Martin v. Löwis25931462008-03-17 20:43:42 +0000239 err_ret->text = (char *) PyObject_MALLOC(len + 1);
240 if (err_ret->text != NULL) {
241 if (len > 0)
242 strncpy(err_ret->text, tok->buf, len);
243 err_ret->text[len] = '\0';
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000244 }
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000245 }
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +0000246 } else if (tok->encoding != NULL) {
247 node* r = PyNode_New(encoding_decl);
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000248 if (!r) {
249 err_ret->error = E_NOMEM;
250 n = NULL;
251 goto done;
252 }
Martin v. Löwis00f1e3f2002-08-04 17:29:52 +0000253 r->n_str = tok->encoding;
254 r->n_nchildren = 1;
255 r->n_child = n;
256 tok->encoding = NULL;
257 n = r;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000258 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000259
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000260done:
Guido van Rossum86bea461997-04-29 21:03:06 +0000261 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000262
263 return n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000264}
Guido van Rossum0c156a52001-10-20 14:27:56 +0000265
266static void
Jeremy Hylton3e0055f2005-10-20 19:59:25 +0000267initerr(perrdetail *err_ret, const char *filename)
Guido van Rossum0c156a52001-10-20 14:27:56 +0000268{
269 err_ret->error = E_OK;
Martin v. Löwis16eff6f2002-01-05 21:40:08 +0000270 err_ret->filename = filename;
Guido van Rossum0c156a52001-10-20 14:27:56 +0000271 err_ret->lineno = 0;
272 err_ret->offset = 0;
273 err_ret->text = NULL;
274 err_ret->token = -1;
275 err_ret->expected = -1;
276}