blob: 069cc6b711b932a84eeefc63d2b8455fa9ff275d [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 */
Christian Heimes3c608332008-03-26 22:01:37 +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{
Antoine Pitrouc83ea132010-05-09 14:46:46 +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,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000029 perrdetail *err_ret, int flags)
Tim Petersfe2127d2001-07-16 05:37:24 +000030{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000031 return PyParser_ParseStringFlagsFilename(s, NULL,
32 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,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000037 grammar *g, int start,
38 perrdetail *err_ret, int flags)
Thomas Heller6b17abf2002-07-09 09:23:27 +000039{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000040 int iflags = flags;
41 return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
42 err_ret, &iflags);
Christian Heimes3c608332008-03-26 22:01:37 +000043}
44
45node *
46PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000047 grammar *g, int start,
48 perrdetail *err_ret, int *flags)
Christian Heimes3c608332008-03-26 22:01:37 +000049{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000050 struct tok_state *tok;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000051
Antoine Pitrouc83ea132010-05-09 14:46:46 +000052 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000053
Antoine Pitrouc83ea132010-05-09 14:46:46 +000054 if ((tok = PyTokenizer_FromString(s, start == file_input)) == NULL) {
55 err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
56 return NULL;
57 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +000058
Antoine Pitrouc83ea132010-05-09 14:46:46 +000059 tok->filename = filename ? filename : "<string>";
60 if (Py_TabcheckFlag || Py_VerboseFlag) {
61 tok->altwarning = (tok->filename != NULL);
62 if (Py_TabcheckFlag >= 2)
63 tok->alterror++;
64 }
Guido van Rossum89ce4541998-12-21 18:32:40 +000065
Antoine Pitrouc83ea132010-05-09 14:46:46 +000066 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossum3f5da241990-12-20 15:06:42 +000067}
68
Guido van Rossum3f5da241990-12-20 15:06:42 +000069/* Parse input coming from a file. Return error code, print some errors. */
70
Guido van Rossumbd0389d1994-08-29 12:25:45 +000071node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000072PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000073 char *ps1, char *ps2, perrdetail *err_ret)
Guido van Rossum3f5da241990-12-20 15:06:42 +000074{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000075 return PyParser_ParseFileFlags(fp, filename, g, start, ps1, ps2,
76 err_ret, 0);
Tim Petersfe2127d2001-07-16 05:37:24 +000077}
78
79node *
Martin v. Löwis95292d62002-12-11 14:04:59 +000080PyParser_ParseFileFlags(FILE *fp, const char *filename, grammar *g, int start,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000081 char *ps1, char *ps2, perrdetail *err_ret, int flags)
Tim Petersfe2127d2001-07-16 05:37:24 +000082{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000083 int iflags = flags;
84 return PyParser_ParseFileFlagsEx(fp, filename, g, start, ps1, ps2, err_ret, &iflags);
Christian Heimes3c608332008-03-26 22:01:37 +000085}
86
87node *
88PyParser_ParseFileFlagsEx(FILE *fp, const char *filename, grammar *g, int start,
Antoine Pitrouc83ea132010-05-09 14:46:46 +000089 char *ps1, char *ps2, perrdetail *err_ret, int *flags)
Christian Heimes3c608332008-03-26 22:01:37 +000090{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000091 struct tok_state *tok;
Guido van Rossumbd0389d1994-08-29 12:25:45 +000092
Antoine Pitrouc83ea132010-05-09 14:46:46 +000093 initerr(err_ret, filename);
Guido van Rossumbd0389d1994-08-29 12:25:45 +000094
Antoine Pitrouc83ea132010-05-09 14:46:46 +000095 if ((tok = PyTokenizer_FromFile(fp, ps1, ps2)) == NULL) {
96 err_ret->error = E_NOMEM;
97 return NULL;
98 }
99 tok->filename = filename;
100 if (Py_TabcheckFlag || Py_VerboseFlag) {
101 tok->altwarning = (filename != NULL);
102 if (Py_TabcheckFlag >= 2)
103 tok->alterror++;
104 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000105
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000106 return parsetok(tok, g, start, err_ret, flags);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000107}
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000108
Neal Norwitzca460d92006-09-06 06:28:06 +0000109#if 0
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000110static char with_msg[] =
111"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
112
113static char as_msg[] =
114"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
115
116static void
117warn(const char *msg, const char *filename, int lineno)
118{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000119 if (filename == NULL)
120 filename = "<string>";
121 PySys_WriteStderr(msg, filename, lineno);
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000122}
Neal Norwitzca460d92006-09-06 06:28:06 +0000123#endif
124
125/* Parse input coming from the given tokenizer structure.
126 Return error code. */
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000127
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000128static node *
Tim Petersfe2127d2001-07-16 05:37:24 +0000129parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000130 int *flags)
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000131{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000132 parser_state *ps;
133 node *n;
Georg Brandl02144cc2012-08-11 11:16:18 +0200134 int started = 0;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000135
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000136 if ((ps = PyParser_New(g, start)) == NULL) {
137 fprintf(stderr, "no mem for new parser\n");
138 err_ret->error = E_NOMEM;
139 PyTokenizer_Free(tok);
140 return NULL;
141 }
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000142#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000143 if (*flags & PyPARSE_PRINT_IS_FUNCTION) {
144 ps->p_flags |= CO_FUTURE_PRINT_FUNCTION;
145 }
146 if (*flags & PyPARSE_UNICODE_LITERALS) {
147 ps->p_flags |= CO_FUTURE_UNICODE_LITERALS;
148 }
Christian Heimes3c608332008-03-26 22:01:37 +0000149
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000150#endif
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000151
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000152 for (;;) {
153 char *a, *b;
154 int type;
155 size_t len;
156 char *str;
157 int col_offset;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000158
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000159 type = PyTokenizer_Get(tok, &a, &b);
160 if (type == ERRORTOKEN) {
161 err_ret->error = tok->done;
162 break;
163 }
164 if (type == ENDMARKER && started) {
165 type = NEWLINE; /* Add an extra newline */
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000166 started = 0;
167 /* Add the right number of dedent tokens,
168 except if a certain flag is given --
169 codeop.py uses this. */
170 if (tok->indent &&
171 !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
172 {
173 tok->pendin = -tok->indent;
174 tok->indent = 0;
175 }
176 }
177 else
178 started = 1;
179 len = b - a; /* XXX this may compute NULL - NULL */
180 str = (char *) PyObject_MALLOC(len + 1);
181 if (str == NULL) {
182 fprintf(stderr, "no mem for next token\n");
183 err_ret->error = E_NOMEM;
184 break;
185 }
186 if (len > 0)
187 strncpy(str, a, len);
188 str[len] = '\0';
Guido van Rossumda62ecc2001-07-17 16:53:11 +0000189
Thomas Wouters34aa7ba2006-02-28 19:02:24 +0000190#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Neil Schemenauerc24ea082002-03-22 23:53:36 +0000191#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000192 if (a >= tok->line_start)
193 col_offset = a - tok->line_start;
194 else
195 col_offset = -1;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000196
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000197 if ((err_ret->error =
198 PyParser_AddToken(ps, (int)type, str, tok->lineno, col_offset,
199 &(err_ret->expected))) != E_OK) {
200 if (err_ret->error != E_DONE) {
201 PyObject_FREE(str);
202 err_ret->token = type;
203 }
204 break;
205 }
206 }
207
208 if (err_ret->error == E_DONE) {
209 n = ps->p_tree;
210 ps->p_tree = NULL;
211 }
212 else
213 n = NULL;
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000214
Christian Heimes342212c2008-03-26 22:20:26 +0000215#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000216 *flags = ps->p_flags;
Christian Heimes342212c2008-03-26 22:20:26 +0000217#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000218 PyParser_Delete(ps);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000219
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000220 if (n == NULL) {
221 if (tok->lineno <= 1 && tok->done == E_EOF)
222 err_ret->error = E_EOF;
223 err_ret->lineno = tok->lineno;
224 if (tok->buf != NULL) {
225 char *text = NULL;
226 size_t len;
227 assert(tok->cur - tok->buf < INT_MAX);
228 err_ret->offset = (int)(tok->cur - tok->buf);
229 len = tok->inp - tok->buf;
Martin v. Löwisa5136192007-09-04 14:19:28 +0000230#ifdef Py_USING_UNICODE
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000231 text = PyTokenizer_RestoreEncoding(tok, len, &err_ret->offset);
Martin v. Löwisa5136192007-09-04 14:19:28 +0000232
233#endif
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000234 if (text == NULL) {
235 text = (char *) PyObject_MALLOC(len + 1);
236 if (text != NULL) {
237 if (len > 0)
238 strncpy(text, tok->buf, len);
239 text[len] = '\0';
240 }
241 }
242 err_ret->text = text;
243 }
244 } else if (tok->encoding != NULL) {
245 /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
246 * allocated using PyMem_
247 */
248 node* r = PyNode_New(encoding_decl);
249 if (r)
250 r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
251 if (!r || !r->n_str) {
252 err_ret->error = E_NOMEM;
253 if (r)
254 PyObject_FREE(r);
255 n = NULL;
256 goto done;
257 }
258 strcpy(r->n_str, tok->encoding);
259 PyMem_FREE(tok->encoding);
260 tok->encoding = NULL;
261 r->n_nchildren = 1;
262 r->n_child = n;
263 n = r;
264 }
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000265
Neal Norwitz6bf1a8f2006-08-12 01:49:12 +0000266done:
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000267 PyTokenizer_Free(tok);
Guido van Rossumbd0389d1994-08-29 12:25:45 +0000268
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000269 return n;
Guido van Rossum85a5fbb1990-10-14 12:07:46 +0000270}
Guido van Rossum0c156a52001-10-20 14:27:56 +0000271
272static void
Jeremy Hylton3e0055f2005-10-20 19:59:25 +0000273initerr(perrdetail *err_ret, const char *filename)
Guido van Rossum0c156a52001-10-20 14:27:56 +0000274{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000275 err_ret->error = E_OK;
276 err_ret->filename = filename;
277 err_ret->lineno = 0;
278 err_ret->offset = 0;
279 err_ret->text = NULL;
280 err_ret->token = -1;
281 err_ret->expected = -1;
Guido van Rossum0c156a52001-10-20 14:27:56 +0000282}