示例#1
0
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, const char *filename)
{
    int i, found_docstring = 0, done = 0, prev_line = 0;

    if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
        return 1;

    /* A subsequent pass will detect future imports that don't
       appear at the beginning of the file.  There's one case,
       however, that is easier to handle here: A series of imports
       joined by semi-colons, where the first import is a future
       statement but some subsequent import has the future form
       but is preceded by a regular import.
    */


    for (i = 0; i < asdl_seq_LEN(mod->v.Module.body); i++) {
        stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);

        if (done && s->lineno > prev_line)
            return 1;
        prev_line = s->lineno;

        /* The tests below will return from this function unless it is
           still possible to find a future statement.  The only things
           that can precede a future statement are another future
           statement and a doc string.
        */

        if (s->kind == ImportFrom_kind) {
            identifier modname = s->v.ImportFrom.module;
            if (modname && PyString_GET_SIZE(modname) == 10 &&
                !strcmp(PyString_AS_STRING(modname), "__future__")) {
                if (done) {
                    PyErr_SetString(PyExc_SyntaxError,
                                    ERR_LATE_FUTURE);
                    PyErr_SyntaxLocation(filename,
                                         s->lineno);
                    return 0;
                }
                if (!future_check_features(ff, s, filename))
                    return 0;
                ff->ff_lineno = s->lineno;
            }
            else
                done = 1;
        }
        else if (s->kind == Expr_kind && !found_docstring) {
            expr_ty e = s->v.Expr.value;
            if (e->kind != Str_kind)
                done = 1;
            else
                found_docstring = 1;
        }
        else
            done = 1;
    }
    return 1;
}
示例#2
0
static int
future_parse(PyFutureFeatures *ff, mod_ty mod, PyObject *filename)
{
    int i, done = 0, prev_line = 0;

    if (!(mod->kind == Module_kind || mod->kind == Interactive_kind))
        return 1;

    if (asdl_seq_LEN(mod->v.Module.body) == 0)
        return 1;

    /* A subsequent pass will detect future imports that don't
       appear at the beginning of the file.  There's one case,
       however, that is easier to handle here: A series of imports
       joined by semi-colons, where the first import is a future
       statement but some subsequent import has the future form
       but is preceded by a regular import.
    */

    i = 0;
    if (_PyAST_GetDocString(mod->v.Module.body) != NULL)
        i++;

    for (; i < asdl_seq_LEN(mod->v.Module.body); i++) {
        stmt_ty s = (stmt_ty)asdl_seq_GET(mod->v.Module.body, i);

        if (done && s->lineno > prev_line)
            return 1;
        prev_line = s->lineno;

        /* The tests below will return from this function unless it is
           still possible to find a future statement.  The only things
           that can precede a future statement are another future
           statement and a doc string.
        */

        if (s->kind == ImportFrom_kind) {
            identifier modname = s->v.ImportFrom.module;
            if (modname &&
                _PyUnicode_EqualToASCIIString(modname, "__future__")) {
                if (done) {
                    PyErr_SetString(PyExc_SyntaxError,
                                    ERR_LATE_FUTURE);
                    PyErr_SyntaxLocationObject(filename, s->lineno, s->col_offset);
                    return 0;
                }
                if (!future_check_features(ff, s, filename))
                    return 0;
                ff->ff_lineno = s->lineno;
            }
            else {
                done = 1;
            }
        }
        else {
            done = 1;
        }
    }
    return 1;
}
示例#3
0
static int
future_parse(PyFutureFeatures *ff, node *n, const char *filename)
{
	int i, r;
 loop:

	switch (TYPE(n)) {

	case single_input:
		if (TYPE(CHILD(n, 0)) == simple_stmt) {
			n = CHILD(n, 0);
			goto loop;
		}
		return 0;

	case file_input:
		/* Check each statement in the file, starting with the
		   first, and continuing until the first statement
		   that isn't a future statement.
		*/
		for (i = 0; i < NCH(n); i++) {
			node *ch = CHILD(n, i);
			if (TYPE(ch) == stmt) {
				r = future_parse(ff, ch, filename);
				/* Need to check both conditions below
				   to accomodate doc strings, which
				   causes r < 0.
				*/
				if (r < 1 && !FUTURE_POSSIBLE(ff))
					return r;
			}
		}
		return 0;

	case simple_stmt:
		if (NCH(n) == 2) {
			REQ(CHILD(n, 0), small_stmt);
			n = CHILD(n, 0);
			goto loop;
		} else {
			/* Deal with the special case of a series of
			   small statements on a single line.  If a
			   future statement follows some other
			   statement, the SyntaxError is raised here.
			   In all other cases, the symtable pass
			   raises the exception.
			*/
			int found = 0, end_of_future = 0;

			for (i = 0; i < NCH(n); i += 2) {
				if (TYPE(CHILD(n, i)) == small_stmt) {
					r = future_parse(ff, CHILD(n, i), 
							 filename);
					if (r < 1)
						end_of_future = 1;
					else {
						found = 1;
						if (end_of_future) {
							future_error(n, 
								     filename);
							return -1;
						}
					}
				}
			}

			/* If we found one and only one, then the
			   current lineno is legal. 
			*/
			if (found)
				ff->ff_last_lineno = n->n_lineno + 1;
			else
				ff->ff_last_lineno = n->n_lineno;

			if (end_of_future && found)
				return 1;
			else 
				return 0;
		}
	
	case stmt:
		if (TYPE(CHILD(n, 0)) == simple_stmt) {
			n = CHILD(n, 0);
			goto loop;
		} else if (TYPE(CHILD(n, 0)) == expr_stmt) {
			n = CHILD(n, 0);
			goto loop;
		} else {
			REQ(CHILD(n, 0), compound_stmt);
			ff->ff_last_lineno = n->n_lineno;
			return 0;
		}

	case small_stmt:
		n = CHILD(n, 0);
		goto loop;

	case import_stmt: {
		node *name;

		n = CHILD(n, 0);
		if (TYPE(n) != import_from) {
			ff->ff_last_lineno = n->n_lineno;
			return 0;
		}
		name = CHILD(n, 1);
		if (strcmp(STR(CHILD(name, 0)), "__future__") != 0)
			return 0;
		if (future_check_features(ff, n, filename) < 0)
			return -1;
		ff->ff_last_lineno = n->n_lineno + 1;
		return 1;
	}

	/* The cases below -- all of them! -- are necessary to find
	   and skip doc strings. */
	case expr_stmt:
	case testlist:
	case test:
	case and_test:
	case not_test:
	case comparison:
	case expr:
	case xor_expr:
	case and_expr:
	case shift_expr:
	case arith_expr:
	case term:
	case factor:
	case power:
		if (NCH(n) == 1) {
			n = CHILD(n, 0);
			goto loop;
		}
		break;

	case atom:
		if (TYPE(CHILD(n, 0)) == STRING 
		    && ff->ff_found_docstring == 0) {
			ff->ff_found_docstring = 1;
			return 0;
		}
		ff->ff_last_lineno = n->n_lineno;
		return 0;

	default:
		ff->ff_last_lineno = n->n_lineno;
		return 0;
	}
	return 0;
}