blob: 73e7e3c95a6af5d1bc015093f8068e57ea6dc701 [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{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +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,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000027 perrdetail *err_ret, int flags)
Tim Petersfe2127d2001-07-16 05:37:24 +000028{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000029 return PyParser_ParseStringFlagsFilename(s, NULL,
30 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,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000035 grammar *g, int start,
36 perrdetail *err_ret, int flags)
Thomas Heller6b17abf2002-07-09 09:23:27 +000037{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000038 int iflags = flags;
39 return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
40 err_ret, &iflags);
Christian Heimes4d6ec852008-03-26 22:34:47 +000041}
42
43node *
44PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000045 grammar *g, int start,
46 perrdetail *err_ret, int *flags)
Christian Heimes4d6ec852008-03-26 22:34:47 +000047{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000048 struct tok_state *tok;
49 int exec_input = start == file_input;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000050
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000051 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000052
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000053 if (*flags & PyPARSE_IGNORE_COOKIE)
54 tok = PyTokenizer_FromUTF8(s, exec_input);
55 else
56 tok = PyTokenizer_FromString(s, exec_input);
57 if (tok == NULL) {
58 err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
59 return NULL;
60 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +000061
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000062 tok->filename = filename ? filename : "<string>";
63 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossum3f5da241990-12-20 15:06:42 +000064}
65
Guido van Rossum3f5da241990-12-20 15:06:42 +000066/* Parse input coming from a file. Return error code, print some errors. */
67
Guido van Rossumbd0389d1994-08-29 12:25:45 +000068node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000069PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000070 char *ps1, char *ps2, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000071{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000072 return PyParser_ParseFileFlags(fp, filename, NULL,
73 g, start, ps1, ps2, err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +000074}
75
76node *
Christian Heimes4d6ec852008-03-26 22:34:47 +000077PyParser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000078 grammar *g, int start,
79 char *ps1, char *ps2, perrdetail *err_ret, int flags)
Tim Petersfe2127d2001-07-16 05:37:24 +000080{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000081 int iflags = flags;
82 return PyParser_ParseFileFlagsEx(fp, filename, enc, g, start, ps1,
83 ps2, err_ret, &iflags);
Christian Heimes4d6ec852008-03-26 22:34:47 +000084}
85
86node *
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087PyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
88 const char *enc, grammar *g, int start,
89 char *ps1, char *ps2, perrdetail *err_ret, int *flags)
Christian Heimes4d6ec852008-03-26 22:34:47 +000090{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000091 struct tok_state *tok;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000094
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000095 if ((tok = PyTokenizer_FromFile(fp, (char *)enc, ps1, ps2)) == NULL) {
96 err_ret->error = E_NOMEM;
97 return NULL;
98 }
99 tok->filename = filename;
100 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000101}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000102
Neal Norwitze4993c72006-03-16 06:01:25 +0000103#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Brett Cannone3944a52009-04-01 05:08:41 +0000104#if 0
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000105static char with_msg[] =
106"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
107
108static char as_msg[] =
109"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
110
111static void
112warn(const char *msg, const char *filename, int lineno)
113{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000114 if (filename == NULL)
115 filename = "<string>";
116 PySys_WriteStderr(msg, filename, lineno);
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000117}
Neal Norwitzfc85c922006-03-17 05:44:46 +0000118#endif
Brett Cannone3944a52009-04-01 05:08:41 +0000119#endif
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000120
Thomas Wouters89f507f2006-12-13 04:49:30 +0000121/* Parse input coming from the given tokenizer structure.
122 Return error code. */
123
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000124static node *
Tim Petersfe2127d2001-07-16 05:37:24 +0000125parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 int *flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000127{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000128 parser_state *ps;
129 node *n;
130 int started = 0, handling_import = 0, handling_with = 0;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000131
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000132 if ((ps = PyParser_New(g, start)) == NULL) {
133 fprintf(stderr, "no mem for new parser\n");
134 err_ret->error = E_NOMEM;
135 PyTokenizer_Free(tok);
136 return NULL;
137 }
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000138#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000139 if (*flags & PyPARSE_BARRY_AS_BDFL)
140 ps->p_flags |= CO_FUTURE_BARRY_AS_BDFL;
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000141#endif
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000142
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000143 for (;;) {
144 char *a, *b;
145 int type;
146 size_t len;
147 char *str;
148 int col_offset;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000149
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 type = PyTokenizer_Get(tok, &a, &b);
151 if (type == ERRORTOKEN) {
152 err_ret->error = tok->done;
153 break;
154 }
155 if (type == ENDMARKER && started) {
156 type = NEWLINE; /* Add an extra newline */
157 handling_with = handling_import = 0;
158 started = 0;
159 /* Add the right number of dedent tokens,
160 except if a certain flag is given --
161 codeop.py uses this. */
162 if (tok->indent &&
163 !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
164 {
165 tok->pendin = -tok->indent;
166 tok->indent = 0;
167 }
168 }
169 else
170 started = 1;
171 len = b - a; /* XXX this may compute NULL - NULL */
172 str = (char *) PyObject_MALLOC(len + 1);
173 if (str == NULL) {
174 fprintf(stderr, "no mem for next token\n");
175 err_ret->error = E_NOMEM;
176 break;
177 }
178 if (len > 0)
179 strncpy(str, a, len);
180 str[len] = '\0';
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000181
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000182#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000183 if (type == NOTEQUAL) {
184 if (!(ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
185 strcmp(str, "!=")) {
Antoine Pitrou9ec25932011-11-13 01:01:23 +0100186 PyObject_FREE(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000187 err_ret->error = E_SYNTAX;
188 break;
189 }
190 else if ((ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
191 strcmp(str, "<>")) {
Antoine Pitrou9ec25932011-11-13 01:01:23 +0100192 PyObject_FREE(str);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000193 err_ret->text = "with Barry as BDFL, use '<>' "
194 "instead of '!='";
195 err_ret->error = E_SYNTAX;
196 break;
197 }
198 }
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000199#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000200 if (a >= tok->line_start)
201 col_offset = a - tok->line_start;
202 else
203 col_offset = -1;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000204
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000205 if ((err_ret->error =
206 PyParser_AddToken(ps, (int)type, str,
207 tok->lineno, col_offset,
208 &(err_ret->expected))) != E_OK) {
209 if (err_ret->error != E_DONE) {
210 PyObject_FREE(str);
211 err_ret->token = type;
212 }
213 break;
214 }
215 }
216
217 if (err_ret->error == E_DONE) {
218 n = ps->p_tree;
219 ps->p_tree = NULL;
220 }
221 else
222 n = NULL;
Christian Heimesb1b3efc2008-03-26 23:24:27 +0000223
Christian Heimes4d6ec852008-03-26 22:34:47 +0000224#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 *flags = ps->p_flags;
Christian Heimes4d6ec852008-03-26 22:34:47 +0000226#endif
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000227 PyParser_Delete(ps);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000228
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000229 if (n == NULL) {
230 if (tok->lineno <= 1 && tok->done == E_EOF)
231 err_ret->error = E_EOF;
232 err_ret->lineno = tok->lineno;
233 if (tok->buf != NULL) {
234 size_t len;
235 assert(tok->cur - tok->buf < INT_MAX);
236 err_ret->offset = (int)(tok->cur - tok->buf);
237 len = tok->inp - tok->buf;
238 err_ret->text = (char *) PyObject_MALLOC(len + 1);
239 if (err_ret->text != NULL) {
240 if (len > 0)
241 strncpy(err_ret->text, tok->buf, len);
242 err_ret->text[len] = '\0';
243 }
244 }
245 } else if (tok->encoding != NULL) {
246 /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
247 * allocated using PyMem_
248 */
249 node* r = PyNode_New(encoding_decl);
250 if (r)
251 r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
252 if (!r || !r->n_str) {
253 err_ret->error = E_NOMEM;
254 if (r)
255 PyObject_FREE(r);
256 n = NULL;
257 goto done;
258 }
259 strcpy(r->n_str, tok->encoding);
260 PyMem_FREE(tok->encoding);
261 tok->encoding = NULL;
262 r->n_nchildren = 1;
263 r->n_child = n;
264 n = r;
265 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000266
Thomas Wouters00ee7ba2006-08-21 19:07:27 +0000267done:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000268 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000269
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000270 return n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000271}
Guido van Rossum0c156a52001-10-20 14:27:56 +0000272
273static void
Jeremy Hylton3e0055f2005-10-20 19:59:25 +0000274initerr(perrdetail *err_ret, const char *filename)
Guido van Rossum0c156a52001-10-20 14:27:56 +0000275{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000276 err_ret->error = E_OK;
277 err_ret->filename = filename;
278 err_ret->lineno = 0;
279 err_ret->offset = 0;
280 err_ret->text = NULL;
281 err_ret->token = -1;
282 err_ret->expected = -1;
Guido van Rossum0c156a52001-10-20 14:27:56 +0000283}