2 /* Parser-tokenizer link implementation */
4 #include "pgenheaders.h"
17 static node
*parsetok(struct tok_state
*, grammar
*, int, perrdetail
*, int);
18 static void initerr(perrdetail
*err_ret
, const char* filename
);
20 /* Parse input coming from a string. Return error code, print some errors. */
22 PyParser_ParseString(const char *s
, grammar
*g
, int start
, perrdetail
*err_ret
)
24 return PyParser_ParseStringFlagsFilename(s
, NULL
, g
, start
, err_ret
, 0);
28 PyParser_ParseStringFlags(const char *s
, grammar
*g
, int start
,
29 perrdetail
*err_ret
, int flags
)
31 return PyParser_ParseStringFlagsFilename(s
, NULL
,
32 g
, start
, err_ret
, flags
);
36 PyParser_ParseStringFlagsFilename(const char *s
, const char *filename
,
37 grammar
*g
, int start
,
38 perrdetail
*err_ret
, int flags
)
40 struct tok_state
*tok
;
42 initerr(err_ret
, filename
);
44 if ((tok
= PyTokenizer_FromString(s
)) == NULL
) {
45 err_ret
->error
= PyErr_Occurred() ? E_DECODE
: E_NOMEM
;
49 tok
->filename
= filename
? filename
: "<string>";
50 if (Py_TabcheckFlag
|| Py_VerboseFlag
) {
51 tok
->altwarning
= (tok
->filename
!= NULL
);
52 if (Py_TabcheckFlag
>= 2)
56 return parsetok(tok
, g
, start
, err_ret
, flags
);
59 /* Parse input coming from a file. Return error code, print some errors. */
62 PyParser_ParseFile(FILE *fp
, const char *filename
, grammar
*g
, int start
,
63 char *ps1
, char *ps2
, perrdetail
*err_ret
)
65 return PyParser_ParseFileFlags(fp
, filename
, g
, start
, ps1
, ps2
,
70 PyParser_ParseFileFlags(FILE *fp
, const char *filename
, grammar
*g
, int start
,
71 char *ps1
, char *ps2
, perrdetail
*err_ret
, int flags
)
73 struct tok_state
*tok
;
75 initerr(err_ret
, filename
);
77 if ((tok
= PyTokenizer_FromFile(fp
, ps1
, ps2
)) == NULL
) {
78 err_ret
->error
= E_NOMEM
;
81 tok
->filename
= filename
;
82 if (Py_TabcheckFlag
|| Py_VerboseFlag
) {
83 tok
->altwarning
= (filename
!= NULL
);
84 if (Py_TabcheckFlag
>= 2)
89 return parsetok(tok
, g
, start
, err_ret
, flags
);
93 static char with_msg
[] =
94 "%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
96 static char as_msg
[] =
97 "%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
100 warn(const char *msg
, const char *filename
, int lineno
)
102 if (filename
== NULL
)
103 filename
= "<string>";
104 PySys_WriteStderr(msg
, filename
, lineno
);
108 /* Parse input coming from the given tokenizer structure.
109 Return error code. */
112 parsetok(struct tok_state
*tok
, grammar
*g
, int start
, perrdetail
*err_ret
,
117 int started
= 0, handling_import
= 0, handling_with
= 0;
119 if ((ps
= PyParser_New(g
, start
)) == NULL
) {
120 fprintf(stderr
, "no mem for new parser\n");
121 err_ret
->error
= E_NOMEM
;
122 PyTokenizer_Free(tok
);
125 #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
126 if (flags
& PyPARSE_WITH_IS_KEYWORD
)
127 ps
->p_flags
|= CO_FUTURE_WITH_STATEMENT
;
137 type
= PyTokenizer_Get(tok
, &a
, &b
);
138 if (type
== ERRORTOKEN
) {
139 err_ret
->error
= tok
->done
;
142 if (type
== ENDMARKER
&& started
) {
143 type
= NEWLINE
; /* Add an extra newline */
144 handling_with
= handling_import
= 0;
146 /* Add the right number of dedent tokens,
147 except if a certain flag is given --
148 codeop.py uses this. */
150 !(flags
& PyPARSE_DONT_IMPLY_DEDENT
))
152 tok
->pendin
= -tok
->indent
;
158 len
= b
- a
; /* XXX this may compute NULL - NULL */
159 str
= (char *) PyObject_MALLOC(len
+ 1);
161 fprintf(stderr
, "no mem for next token\n");
162 err_ret
->error
= E_NOMEM
;
166 strncpy(str
, a
, len
);
169 #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
170 /* This is only necessary to support the "as" warning, but
171 we don't want to warn about "as" in import statements. */
173 len
== 6 && str
[0] == 'i' && strcmp(str
, "import") == 0)
176 /* Warn about with as NAME */
178 !(ps
->p_flags
& CO_FUTURE_WITH_STATEMENT
)) {
179 if (len
== 4 && str
[0] == 'w' && strcmp(str
, "with") == 0)
180 warn(with_msg
, err_ret
->filename
, tok
->lineno
);
181 else if (!(handling_import
|| handling_with
) &&
182 len
== 2 && str
[0] == 'a' &&
183 strcmp(str
, "as") == 0)
184 warn(as_msg
, err_ret
->filename
, tok
->lineno
);
186 else if (type
== NAME
&&
187 (ps
->p_flags
& CO_FUTURE_WITH_STATEMENT
) &&
188 len
== 4 && str
[0] == 'w' && strcmp(str
, "with") == 0)
191 if (a
>= tok
->line_start
)
192 col_offset
= a
- tok
->line_start
;
196 if ((err_ret
->error
=
197 PyParser_AddToken(ps
, (int)type
, str
, tok
->lineno
, col_offset
,
198 &(err_ret
->expected
))) != E_OK
) {
199 if (err_ret
->error
!= E_DONE
) {
201 err_ret
->token
= type
;
207 if (err_ret
->error
== E_DONE
) {
217 if (tok
->lineno
<= 1 && tok
->done
== E_EOF
)
218 err_ret
->error
= E_EOF
;
219 err_ret
->lineno
= tok
->lineno
;
220 if (tok
->buf
!= NULL
) {
223 assert(tok
->cur
- tok
->buf
< INT_MAX
);
224 err_ret
->offset
= (int)(tok
->cur
- tok
->buf
);
225 len
= tok
->inp
- tok
->buf
;
226 #ifdef Py_USING_UNICODE
227 text
= PyTokenizer_RestoreEncoding(tok
, len
, &err_ret
->offset
);
231 text
= (char *) PyObject_MALLOC(len
+ 1);
234 strncpy(text
, tok
->buf
, len
);
238 err_ret
->text
= text
;
240 } else if (tok
->encoding
!= NULL
) {
241 node
* r
= PyNode_New(encoding_decl
);
243 err_ret
->error
= E_NOMEM
;
247 r
->n_str
= tok
->encoding
;
250 tok
->encoding
= NULL
;
255 PyTokenizer_Free(tok
);
261 initerr(perrdetail
*err_ret
, const char *filename
)
263 err_ret
->error
= E_OK
;
264 err_ret
->filename
= filename
;
267 err_ret
->text
= NULL
;
269 err_ret
->expected
= -1;