LCOV - code coverage report
Current view: top level - Parser - parsetok.c (source / functions) Hit Total Coverage
Test: CPython lcov report Lines: 57 125 45.6 %
Date: 2017-04-19 Functions: 4 9 44.4 %

          Line data    Source code
       1             : 
       2             : /* Parser-tokenizer link implementation */
       3             : 
       4             : #include "pgenheaders.h"
       5             : #include "tokenizer.h"
       6             : #include "node.h"
       7             : #include "grammar.h"
       8             : #include "parser.h"
       9             : #include "parsetok.h"
      10             : #include "errcode.h"
      11             : #include "graminit.h"
      12             : 
      13             : int Py_TabcheckFlag;
      14             : 
      15             : 
      16             : /* Forward */
      17             : static node *parsetok(struct tok_state *, grammar *, int, perrdetail *, int *);
      18             : static void initerr(perrdetail *err_ret, const char* filename);
      19             : 
      20             : /* Parse input coming from a string.  Return error code, print some errors. */
      21             : node *
      22           0 : PyParser_ParseString(const char *s, grammar *g, int start, perrdetail *err_ret)
      23             : {
      24           0 :     return PyParser_ParseStringFlagsFilename(s, NULL, g, start, err_ret, 0);
      25             : }
      26             : 
      27             : node *
      28           0 : PyParser_ParseStringFlags(const char *s, grammar *g, int start,
      29             :                           perrdetail *err_ret, int flags)
      30             : {
      31           0 :     return PyParser_ParseStringFlagsFilename(s, NULL,
      32             :                                              g, start, err_ret, flags);
      33             : }
      34             : 
      35             : node *
      36           0 : PyParser_ParseStringFlagsFilename(const char *s, const char *filename,
      37             :                           grammar *g, int start,
      38             :                           perrdetail *err_ret, int flags)
      39             : {
      40           0 :     int iflags = flags;
      41           0 :     return PyParser_ParseStringFlagsFilenameEx(s, filename, g, start,
      42             :                                                err_ret, &iflags);
      43             : }
      44             : 
      45             : node *
      46          27 : PyParser_ParseStringFlagsFilenameEx(const char *s, const char *filename,
      47             :                           grammar *g, int start,
      48             :                           perrdetail *err_ret, int *flags)
      49             : {
      50             :     struct tok_state *tok;
      51             : 
      52          27 :     initerr(err_ret, filename);
      53             : 
      54          27 :     if ((tok = PyTokenizer_FromString(s, start == file_input)) == NULL) {
      55           0 :         err_ret->error = PyErr_Occurred() ? E_DECODE : E_NOMEM;
      56           0 :         return NULL;
      57             :     }
      58             : 
      59          27 :     tok->filename = filename ? filename : "<string>";
      60          27 :     if (Py_TabcheckFlag || Py_VerboseFlag) {
      61           0 :         tok->altwarning = (tok->filename != NULL);
      62           0 :         if (Py_TabcheckFlag >= 2)
      63           0 :             tok->alterror++;
      64             :     }
      65             : 
      66          27 :     return parsetok(tok, g, start, err_ret, flags);
      67             : }
      68             : 
      69             : /* Parse input coming from a file.  Return error code, print some errors. */
      70             : 
      71             : node *
      72           0 : PyParser_ParseFile(FILE *fp, const char *filename, grammar *g, int start,
      73             :                    char *ps1, char *ps2, perrdetail *err_ret)
      74             : {
      75           0 :     return PyParser_ParseFileFlags(fp, filename, g, start, ps1, ps2,
      76             :                                    err_ret, 0);
      77             : }
      78             : 
      79             : node *
      80           0 : PyParser_ParseFileFlags(FILE *fp, const char *filename, grammar *g, int start,
      81             :                         char *ps1, char *ps2, perrdetail *err_ret, int flags)
      82             : {
      83           0 :     int iflags = flags;
      84           0 :     return PyParser_ParseFileFlagsEx(fp, filename, g, start, ps1, ps2, err_ret, &iflags);
      85             : }
      86             : 
      87             : node *
      88          36 : PyParser_ParseFileFlagsEx(FILE *fp, const char *filename, grammar *g, int start,
      89             :                           char *ps1, char *ps2, perrdetail *err_ret, int *flags)
      90             : {
      91             :     struct tok_state *tok;
      92             : 
      93          36 :     initerr(err_ret, filename);
      94             : 
      95          36 :     if ((tok = PyTokenizer_FromFile(fp, ps1, ps2)) == NULL) {
      96           0 :         err_ret->error = E_NOMEM;
      97           0 :         return NULL;
      98             :     }
      99          36 :     tok->filename = filename;
     100          36 :     if (Py_TabcheckFlag || Py_VerboseFlag) {
     101           0 :         tok->altwarning = (filename != NULL);
     102           0 :         if (Py_TabcheckFlag >= 2)
     103           0 :             tok->alterror++;
     104             :     }
     105             : 
     106          36 :     return parsetok(tok, g, start, err_ret, flags);
     107             : }
     108             : 
     109             : #if 0
     110             : static char with_msg[] =
     111             : "%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n";
     112             : 
     113             : static char as_msg[] =
     114             : "%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n";
     115             : 
     116             : static void
     117             : warn(const char *msg, const char *filename, int lineno)
     118             : {
     119             :     if (filename == NULL)
     120             :         filename = "<string>";
     121             :     PySys_WriteStderr(msg, filename, lineno);
     122             : }
     123             : #endif
     124             : 
     125             : /* Parse input coming from the given tokenizer structure.
     126             :    Return error code. */
     127             : 
     128             : static node *
     129          63 : parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret,
     130             :          int *flags)
     131             : {
     132             :     parser_state *ps;
     133             :     node *n;
     134          63 :     int started = 0;
     135             : 
     136          63 :     if ((ps = PyParser_New(g, start)) == NULL) {
     137           0 :         fprintf(stderr, "no mem for new parser\n");
     138           0 :         err_ret->error = E_NOMEM;
     139           0 :         PyTokenizer_Free(tok);
     140           0 :         return NULL;
     141             :     }
     142             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     143          63 :     if (*flags & PyPARSE_PRINT_IS_FUNCTION) {
     144           0 :         ps->p_flags |= CO_FUTURE_PRINT_FUNCTION;
     145             :     }
     146          63 :     if (*flags & PyPARSE_UNICODE_LITERALS) {
     147           0 :         ps->p_flags |= CO_FUTURE_UNICODE_LITERALS;
     148             :     }
     149             : 
     150             : #endif
     151             : 
     152             :     for (;;) {
     153             :         char *a, *b;
     154             :         int type;
     155             :         size_t len;
     156             :         char *str;
     157             :         int col_offset;
     158             : 
     159       74459 :         type = PyTokenizer_Get(tok, &a, &b);
     160       74459 :         if (type == ERRORTOKEN) {
     161           0 :             err_ret->error = tok->done;
     162          63 :             break;
     163             :         }
     164       74459 :         if (type == ENDMARKER && started) {
     165          60 :             type = NEWLINE; /* Add an extra newline */
     166          60 :             started = 0;
     167             :             /* Add the right number of dedent tokens,
     168             :                except if a certain flag is given --
     169             :                codeop.py uses this. */
     170         120 :             if (tok->indent &&
     171           0 :                 !(*flags & PyPARSE_DONT_IMPLY_DEDENT))
     172             :             {
     173           0 :                 tok->pendin = -tok->indent;
     174           0 :                 tok->indent = 0;
     175             :             }
     176             :         }
     177             :         else
     178       74399 :             started = 1;
     179       74459 :         len = b - a; /* XXX this may compute NULL - NULL */
     180       74459 :         str = (char *) PyObject_MALLOC(len + 1);
     181       74459 :         if (str == NULL) {
     182           0 :             fprintf(stderr, "no mem for next token\n");
     183           0 :             err_ret->error = E_NOMEM;
     184           0 :             break;
     185             :         }
     186       74459 :         if (len > 0)
     187       60713 :             strncpy(str, a, len);
     188       74459 :         str[len] = '\0';
     189             : 
     190             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     191             : #endif
     192       74459 :         if (a >= tok->line_start)
     193       68553 :             col_offset = a - tok->line_start;
     194             :         else
     195        5906 :             col_offset = -1;
     196             : 
     197       74459 :         if ((err_ret->error =
     198       74459 :              PyParser_AddToken(ps, (int)type, str, tok->lineno, col_offset,
     199             :                                &(err_ret->expected))) != E_OK) {
     200          63 :             if (err_ret->error != E_DONE) {
     201           0 :                 PyObject_FREE(str);
     202           0 :                 err_ret->token = type;
     203             :             }
     204          63 :             break;
     205             :         }
     206       74396 :     }
     207             : 
     208          63 :     if (err_ret->error == E_DONE) {
     209          63 :         n = ps->p_tree;
     210          63 :         ps->p_tree = NULL;
     211             :     }
     212             :     else
     213           0 :         n = NULL;
     214             : 
     215             : #ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD
     216          63 :     *flags = ps->p_flags;
     217             : #endif
     218          63 :     PyParser_Delete(ps);
     219             : 
     220          63 :     if (n == NULL) {
     221           0 :         if (tok->lineno <= 1 && tok->done == E_EOF)
     222           0 :             err_ret->error = E_EOF;
     223           0 :         err_ret->lineno = tok->lineno;
     224           0 :         if (tok->buf != NULL) {
     225           0 :             char *text = NULL;
     226             :             size_t len;
     227             :             assert(tok->cur - tok->buf < INT_MAX);
     228           0 :             err_ret->offset = (int)(tok->cur - tok->buf);
     229           0 :             len = tok->inp - tok->buf;
     230             : #ifdef Py_USING_UNICODE
     231           0 :             text = PyTokenizer_RestoreEncoding(tok, len, &err_ret->offset);
     232             : 
     233             : #endif
     234           0 :             if (text == NULL) {
     235           0 :                 text = (char *) PyObject_MALLOC(len + 1);
     236           0 :                 if (text != NULL) {
     237           0 :                     if (len > 0)
     238           0 :                         strncpy(text, tok->buf, len);
     239           0 :                     text[len] = '\0';
     240             :                 }
     241             :             }
     242           0 :             err_ret->text = text;
     243             :         }
     244          63 :     } else if (tok->encoding != NULL) {
     245             :         /* 'nodes->n_str' uses PyObject_*, while 'tok->encoding' was
     246             :          * allocated using PyMem_
     247             :          */
     248           0 :         node* r = PyNode_New(encoding_decl);
     249           0 :         if (r)
     250           0 :             r->n_str = PyObject_MALLOC(strlen(tok->encoding)+1);
     251           0 :         if (!r || !r->n_str) {
     252           0 :             err_ret->error = E_NOMEM;
     253           0 :             if (r)
     254           0 :                 PyObject_FREE(r);
     255           0 :             n = NULL;
     256           0 :             goto done;
     257             :         }
     258           0 :         strcpy(r->n_str, tok->encoding);
     259           0 :         PyMem_FREE(tok->encoding);
     260           0 :         tok->encoding = NULL;
     261           0 :         r->n_nchildren = 1;
     262           0 :         r->n_child = n;
     263           0 :         n = r;
     264             :     }
     265             : 
     266             : done:
     267          63 :     PyTokenizer_Free(tok);
     268             : 
     269          63 :     return n;
     270             : }
     271             : 
     272             : static void
     273          63 : initerr(perrdetail *err_ret, const char *filename)
     274             : {
     275          63 :     err_ret->error = E_OK;
     276          63 :     err_ret->filename = filename;
     277          63 :     err_ret->lineno = 0;
     278          63 :     err_ret->offset = 0;
     279          63 :     err_ret->text = NULL;
     280          63 :     err_ret->token = -1;
     281          63 :     err_ret->expected = -1;
     282          63 : }

Generated by: LCOV version 1.10