ยปCore Development>Code coverage>Parser/parsetok.c

Python code coverage for Parser/parsetok.c

#countcontent
1n/a
2n/a/* Parser-tokenizer link implementation */
3n/a
4n/a#include "pgenheaders.h"
5n/a#include "tokenizer.h"
6n/a#include "node.h"
7n/a#include "grammar.h"
8n/a#include "parser.h"
9n/a#include "parsetok.h"
10n/a#include "errcode.h"
11n/a#include "graminit.h"
12n/a
13n/a
14n/a/* Forward */
15n/astatic node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
16n/astatic int initerr(perrdetail *err_ret, PyObject * filename);
17n/a
18n/a/* Parse input coming from a string. Return error code, print some errors. */
19n/anode *
20n/aPyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
21n/a{
22n/a return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
23n/a}
24n/a
25n/anode *
26n/aPyParser_ParseStringFlags(const char *s, grammar *g, int start,
27n/a perrdetail *err_ret, int flags)
28n/a{
29n/a return PyParser_ParseStringFlagsFilename(s, NULL,
30n/a g, start, err_ret, flags);
31n/a}
32n/a
33n/anode *
34n/aPyParser_ParseStringFlagsFilename(const char *s, const char *filename,
35n/a grammar *g, int start,
36n/a perrdetail *err_ret, int flags)
37n/a{
38n/a int iflags = flags;
39n/a return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
40n/a err_ret, &iflags);
41n/a}
42n/a
43n/anode *
44n/aPyParser_ParseStringObject(const char *s, PyObject *filename,
45n/a grammar *g, int start,
46n/a perrdetail *err_ret, int *flags)
47n/a{
48n/a struct tok_state *tok;
49n/a int exec_input = start == file_input;
50n/a
51n/a if (initerr(err_ret, filename) < 0)
52n/a return NULL;
53n/a
54n/a if (*flags & PyPARSE_IGNORE_COOKIE)
55n/a tok = PyTokenizer_FromUTF8(s, exec_input);
56n/a else
57n/a tok = PyTokenizer_FromString(s, exec_input);
58n/a if (tok == NULL) {
59n/a err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
60n/a return NULL;
61n/a }
62n/a
63n/a#ifndef PGEN
64n/a Py_INCREF(err_ret->filename);
65n/a tok->filename = err_ret->filename;
66n/a#endif
67n/a return parsetok(tok, g, start, err_ret, flags);
68n/a}
69n/a
70n/anode *
71n/aPyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename_str,
72n/a grammar *g, int start,
73n/a perrdetail *err_ret, int *flags)
74n/a{
75n/a node *n;
76n/a PyObject *filename = NULL;
77n/a#ifndef PGEN
78n/a if (filename_str != NULL) {
79n/a filename = PyUnicode_DecodeFSDefault(filename_str);
80n/a if (filename == NULL) {
81n/a err_ret->error = E_ERROR;
82n/a return NULL;
83n/a }
84n/a }
85n/a#endif
86n/a n = PyParser_ParseStringObject(s, filename, g, start, err_ret, flags);
87n/a#ifndef PGEN
88n/a Py_XDECREF(filename);
89n/a#endif
90n/a return n;
91n/a}
92n/a
93n/a/* Parse input coming from a file. Return error code, print some errors. */
94n/a
95n/anode *
96n/aPyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
97n/a const char *ps1, const char *ps2,
98n/a perrdetail *err_ret)
99n/a{
100n/a return PyParser_ParseFileFlags(fp, filename, NULL,
101n/a g, start, ps1, ps2, err_ret, 0);
102n/a}
103n/a
104n/anode *
105n/aPyParser_ParseFileFlags(FILE *fp, const char *filename, const char *enc,
106n/a grammar *g, int start,
107n/a const char *ps1, const char *ps2,
108n/a perrdetail *err_ret, int flags)
109n/a{
110n/a int iflags = flags;
111n/a return PyParser_ParseFileFlagsEx(fp, filename, enc, g, start, ps1,
112n/a ps2, err_ret, &iflags);
113n/a}
114n/a
115n/anode *
116n/aPyParser_ParseFileObject(FILE *fp, PyObject *filename,
117n/a const char *enc, grammar *g, int start,
118n/a const char *ps1, const char *ps2,
119n/a perrdetail *err_ret, int *flags)
120n/a{
121n/a struct tok_state *tok;
122n/a
123n/a if (initerr(err_ret, filename) < 0)
124n/a return NULL;
125n/a
126n/a if ((tok = PyTokenizer_FromFile(fp, enc, ps1, ps2)) == NULL) {
127n/a err_ret->error = E_NOMEM;
128n/a return NULL;
129n/a }
130n/a#ifndef PGEN
131n/a Py_INCREF(err_ret->filename);
132n/a tok->filename = err_ret->filename;
133n/a#endif
134n/a return parsetok(tok, g, start, err_ret, flags);
135n/a}
136n/a
137n/anode *
138n/aPyParser_ParseFileFlagsEx(FILE *fp, const char *filename,
139n/a const char *enc, grammar *g, int start,
140n/a const char *ps1, const char *ps2,
141n/a perrdetail *err_ret, int *flags)
142n/a{
143n/a node *n;
144n/a PyObject *fileobj = NULL;
145n/a#ifndef PGEN
146n/a if (filename != NULL) {
147n/a fileobj = PyUnicode_DecodeFSDefault(filename);
148n/a if (fileobj == NULL) {
149n/a err_ret->error = E_ERROR;
150n/a return NULL;
151n/a }
152n/a }
153n/a#endif
154n/a n = PyParser_ParseFileObject(fp, fileobj, enc, g,
155n/a start, ps1, ps2, err_ret, flags);
156n/a#ifndef PGEN
157n/a Py_XDECREF(fileobj);
158n/a#endif
159n/a return n;
160n/a}
161n/a
162n/a#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
163n/a#if 0
164n/astatic const char with_msg[] =
165n/a"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
166n/a
167n/astatic const char as_msg[] =
168n/a"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
169n/a
170n/astatic void
171n/awarn(const char *msg, const char *filename, int lineno)
172n/a{
173n/a if (filename == NULL)
174n/a filename = "<string>";
175n/a PySys_WriteStderr(msg, filename, lineno);
176n/a}
177n/a#endif
178n/a#endif
179n/a
180n/a/* Parse input coming from the given tokenizer structure.
181n/a Return error code. */
182n/a
183n/astatic node *
184n/aparsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
185n/a int *flags)
186n/a{
187n/a parser_state *ps;
188n/a node *n;
189n/a int started = 0;
190n/a
191n/a if ((ps = PyParser_New(g, start)) == NULL) {
192n/a err_ret->error = E_NOMEM;
193n/a PyTokenizer_Free(tok);
194n/a return NULL;
195n/a }
196n/a#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
197n/a if (*flags & PyPARSE_BARRY_AS_BDFL)
198n/a ps->p_flags |= CO_FUTURE_BARRY_AS_BDFL;
199n/a#endif
200n/a
201n/a for (;;) {
202n/a char *a, *b;
203n/a int type;
204n/a size_t len;
205n/a char *str;
206n/a int col_offset;
207n/a
208n/a type = PyTokenizer_Get(tok, &a, &b);
209n/a if (type == ERRORTOKEN) {
210n/a err_ret->error = tok->done;
211n/a break;
212n/a }
213n/a if (type == ENDMARKER && started) {
214n/a type = NEWLINE; /* Add an extra newline */
215n/a started = 0;
216n/a /* Add the right number of dedent tokens,
217n/a except if a certain flag is given --
218n/a codeop.py uses this. */
219n/a if (tok->indent &&
220n/a !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
221n/a {
222n/a tok->pendin = -tok->indent;
223n/a tok->indent = 0;
224n/a }
225n/a }
226n/a else
227n/a started = 1;
228n/a len = b - a; /* XXX this may compute NULL - NULL */
229n/a str = (char *) PyObject_MALLOC(len + 1);
230n/a if (str == NULL) {
231n/a err_ret->error = E_NOMEM;
232n/a break;
233n/a }
234n/a if (len > 0)
235n/a strncpy(str, a, len);
236n/a str[len] = '\0';
237n/a
238n/a#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
239n/a if (type == NOTEQUAL) {
240n/a if (!(ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
241n/a strcmp(str, "!=")) {
242n/a PyObject_FREE(str);
243n/a err_ret->error = E_SYNTAX;
244n/a break;
245n/a }
246n/a else if ((ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
247n/a strcmp(str, "<>")) {
248n/a PyObject_FREE(str);
249n/a err_ret->text = "with Barry as BDFL, use '<>' "
250n/a "instead of '!='";
251n/a err_ret->error = E_SYNTAX;
252n/a break;
253n/a }
254n/a }
255n/a#endif
256n/a if (a >= tok->line_start)
257n/a col_offset = Py_SAFE_DOWNCAST(a - tok->line_start,
258n/a intptr_t, int);
259n/a else
260n/a col_offset = -1;
261n/a
262n/a if ((err_ret->error =
263n/a PyParser_AddToken(ps, (int)type, str,
264n/a tok->lineno, col_offset,
265n/a &(err_ret->expected))) != E_OK) {
266n/a if (err_ret->error != E_DONE) {
267n/a PyObject_FREE(str);
268n/a err_ret->token = type;
269n/a }
270n/a break;
271n/a }
272n/a }
273n/a
274n/a if (err_ret->error == E_DONE) {
275n/a n = ps->p_tree;
276n/a ps->p_tree = NULL;
277n/a
278n/a#ifndef PGEN
279n/a /* Check that the source for a single input statement really
280n/a is a single statement by looking at what is left in the
281n/a buffer after parsing. Trailing whitespace and comments
282n/a are OK. */
283n/a if (start == single_input) {
284n/a char *cur = tok->cur;
285n/a char c = *tok->cur;
286n/a
287n/a for (;;) {
288n/a while (c == ' ' || c == '\t' || c == '\n' || c == '\014')
289n/a c = *++cur;
290n/a
291n/a if (!c)
292n/a break;
293n/a
294n/a if (c != '#') {
295n/a err_ret->error = E_BADSINGLE;
296n/a PyNode_Free(n);
297n/a n = NULL;
298n/a break;
299n/a }
300n/a
301n/a /* Suck up comment. */
302n/a while (c && c != '\n')
303n/a c = *++cur;
304n/a }
305n/a }
306n/a#endif
307n/a }
308n/a else
309n/a n = NULL;
310n/a
311n/a#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
312n/a *flags = ps->p_flags;
313n/a#endif
314n/a PyParser_Delete(ps);
315n/a
316n/a if (n == NULL) {
317n/a if (tok->done == E_EOF)
318n/a err_ret->error = E_EOF;
319n/a err_ret->lineno = tok->lineno;
320n/a if (tok->buf != NULL) {
321n/a size_t len;
322n/a assert(tok->cur - tok->buf < INT_MAX);
323n/a err_ret->offset = (int)(tok->cur - tok->buf);
324n/a len = tok->inp - tok->buf;
325n/a err_ret->text = (char *) PyObject_MALLOC(len + 1);
326n/a if (err_ret->text != NULL) {
327n/a if (len > 0)
328n/a strncpy(err_ret->text, tok->buf, len);
329n/a err_ret->text[len] = '\0';
330n/a }
331n/a }
332n/a } else if (tok->encoding != NULL) {
333n/a /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
334n/a * allocated using PyMem_
335n/a */
336n/a node* r = PyNode_New(encoding_decl);
337n/a if (r)
338n/a r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
339n/a if (!r || !r->n_str) {
340n/a err_ret->error = E_NOMEM;
341n/a if (r)
342n/a PyObject_FREE(r);
343n/a n = NULL;
344n/a goto done;
345n/a }
346n/a strcpy(r->n_str, tok->encoding);
347n/a PyMem_FREE(tok->encoding);
348n/a tok->encoding = NULL;
349n/a r->n_nchildren = 1;
350n/a r->n_child = n;
351n/a n = r;
352n/a }
353n/a
354n/adone:
355n/a PyTokenizer_Free(tok);
356n/a
357n/a return n;
358n/a}
359n/a
360n/astatic int
361n/ainiterr(perrdetail *err_ret, PyObject *filename)
362n/a{
363n/a err_ret->error = E_OK;
364n/a err_ret->lineno = 0;
365n/a err_ret->offset = 0;
366n/a err_ret->text = NULL;
367n/a err_ret->token = -1;
368n/a err_ret->expected = -1;
369n/a#ifndef PGEN
370n/a if (filename) {
371n/a Py_INCREF(filename);
372n/a err_ret->filename = filename;
373n/a }
374n/a else {
375n/a err_ret->filename = PyUnicode_FromString("<string>");
376n/a if (err_ret->filename == NULL) {
377n/a err_ret->error = E_ERROR;
378n/a return -1;
379n/a }
380n/a }
381n/a#endif
382n/a return 0;
383n/a}