diff options
author | Thomas Wouters <thomas@python.org> | 2006-02-28 19:02:24 (GMT) |
---|---|---|
committer | Thomas Wouters <thomas@python.org> | 2006-02-28 19:02:24 (GMT) |
commit | 34aa7ba11431a46e72ec30ee7528f2e52adbed7f (patch) | |
tree | ac399604026430f720f60a7b42264103a747a18c /Parser | |
parent | edc8f1366af2d32882649647a7a79873a6cb9503 (diff) | |
download | cpython-34aa7ba11431a46e72ec30ee7528f2e52adbed7f.zip cpython-34aa7ba11431a46e72ec30ee7528f2e52adbed7f.tar.gz cpython-34aa7ba11431a46e72ec30ee7528f2e52adbed7f.tar.bz2 |
from __future__ import with_statement addon for 'with', mostly written by
Neal.
Diffstat (limited to 'Parser')
-rw-r--r-- | Parser/parser.c | 37 | ||||
-rw-r--r-- | Parser/parser.h | 4 | ||||
-rw-r--r-- | Parser/parsetok.c | 55 |
3 files changed, 65 insertions, 31 deletions
diff --git a/Parser/parser.c b/Parser/parser.c index 686161b..cad5ce2 100644 --- a/Parser/parser.c +++ b/Parser/parser.c @@ -79,8 +79,8 @@ PyParser_New(grammar *g, int start) if (ps == NULL) return NULL; ps->p_grammar = g; -#if 0 /* future keyword */ - ps->p_generators = 0; +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD + ps->p_flags = 0; #endif ps->p_tree = PyNode_New(start); if (ps->p_tree == NULL) { @@ -147,10 +147,10 @@ classify(parser_state *ps, int type, char *str) if (l->lb_type == NAME && l->lb_str != NULL && l->lb_str[0] == s[0] && strcmp(l->lb_str, s) == 0) { -#if 0 /* future keyword */ - if (!ps->p_generators && - s[0] == 'y' && - strcmp(s, "yield") == 0) +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD + if (!(ps->p_flags & CO_FUTURE_WITH_STATEMENT) && + s[0] == 'w' && + strcmp(s, "with") == 0) break; /* not a keyword */ #endif D(printf("It's a keyword\n")); @@ -174,7 +174,7 @@ classify(parser_state *ps, int type, char *str) return -1; } -#if 0 /* future keyword */ +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD static void future_hack(parser_state *ps) { @@ -182,16 +182,27 @@ future_hack(parser_state *ps) node *ch; int i; - if (strcmp(STR(CHILD(n, 0)), "from") != 0) + /* from __future__ import ..., must have at least 4 children */ + n = CHILD(n, 0); + if (NCH(n) < 4) + return; + ch = CHILD(n, 0); + if (STR(ch) == NULL || strcmp(STR(ch), "from") != 0) return; ch = CHILD(n, 1); - if (strcmp(STR(CHILD(ch, 0)), "__future__") != 0) + if (NCH(ch) == 1 && STR(CHILD(ch, 0)) && + strcmp(STR(CHILD(ch, 0)), "__future__") != 0) return; for (i = 3; i < NCH(n); i += 2) { + /* XXX: assume we don't have parentheses in import: + from __future__ import (x, y, z) + */ ch = CHILD(n, i); + if (NCH(ch) == 1) + ch = CHILD(ch, 0); if (NCH(ch) >= 1 && TYPE(CHILD(ch, 0)) == NAME && - strcmp(STR(CHILD(ch, 0)), "generators") == 0) { - ps->p_generators = 1; + strcmp(STR(CHILD(ch, 0)), "with_statement") == 0) { + ps->p_flags |= CO_FUTURE_WITH_STATEMENT; break; } } @@ -255,7 +266,7 @@ PyParser_AddToken(register parser_state *ps, register int type, char *str, "Direct pop.\n", d->d_name, ps->p_stack.s_top->s_state)); -#if 0 /* future keyword */ +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD if (d->d_name[0] == 'i' && strcmp(d->d_name, "import_stmt") == 0) @@ -273,7 +284,7 @@ PyParser_AddToken(register parser_state *ps, register int type, char *str, } if (s->s_accept) { -#if 0 /* future keyword */ +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD if (d->d_name[0] == 'i' && strcmp(d->d_name, "import_stmt") == 0) future_hack(ps); diff --git a/Parser/parser.h b/Parser/parser.h index 95ec247..f5d2d0d 100644 --- a/Parser/parser.h +++ b/Parser/parser.h @@ -25,8 +25,8 @@ typedef struct { stack p_stack; /* Stack of parser states */ grammar *p_grammar; /* Grammar to use */ node *p_tree; /* Top of parse tree */ -#if 0 /* future keyword */ - int p_generators; /* 1 if yield is a keyword */ +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD + unsigned long p_flags; /* see co_flags in Include/code.h */ #endif } parser_state; diff --git a/Parser/parsetok.c b/Parser/parsetok.c index 4c533f1..cf445e1 100644 --- a/Parser/parsetok.c +++ b/Parser/parsetok.c @@ -92,10 +92,19 @@ PyParser_ParseFileFlags(FILE *fp, const char *filename, grammar *g, int start, /* Parse input coming from the given tokenizer structure. Return error code. */ -#if 0 /* future keyword */ -static char yield_msg[] = -"%s:%d: Warning: 'yield' will become a reserved keyword in the future\n"; -#endif +static char with_msg[] = +"%s:%d: Warning: 'with' will become a reserved keyword in Python 2.6\n"; + +static char as_msg[] = +"%s:%d: Warning: 'as' will become a reserved keyword in Python 2.6\n"; + +static void +warn(const char *msg, const char *filename, int lineno) +{ + if (filename == NULL) + filename = "<string>"; + PySys_WriteStderr(msg, filename, lineno); +} static node * parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret, @@ -103,7 +112,7 @@ parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret, { parser_state *ps; node *n; - int started = 0; + int started = 0, handling_import = 0, handling_with = 0; if ((ps = PyParser_New(g, start)) == NULL) { fprintf(stderr, "no mem for new parser\n"); @@ -111,9 +120,9 @@ parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret, PyTokenizer_Free(tok); return NULL; } -#if 0 /* future keyword */ - if (flags & PyPARSE_YIELD_IS_KEYWORD) - ps->p_generators = 1; +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD + if (flags & PyPARSE_WITH_IS_KEYWORD) + ps->p_flags |= CO_FUTURE_WITH_STATEMENT; #endif for (;;) { @@ -129,6 +138,7 @@ parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret, } if (type == ENDMARKER && started) { type = NEWLINE; /* Add an extra newline */ + handling_with = handling_import = 0; started = 0; /* Add the right number of dedent tokens, except if a certain flag is given -- @@ -153,14 +163,27 @@ parsetok(struct tok_state *tok, grammar *g, int start, perrdetail *err_ret, strncpy(str, a, len); str[len] = '\0'; -#if 0 /* future keyword */ - /* Warn about yield as NAME */ - if (type == NAME && !ps->p_generators && - len == 5 && str[0] == 'y' && strcmp(str, "yield") == 0) - PySys_WriteStderr(yield_msg, - err_ret->filename==NULL ? - "<string>" : err_ret->filename, - tok->lineno); +#ifdef PY_PARSER_REQUIRES_FUTURE_KEYWORD + /* This is only necessary to support the "as" warning, but + we don't want to warn about "as" in import statements. */ + if (type == NAME && + len == 6 && str[0] == 'i' && strcmp(str, "import") == 0) + handling_import = 1; + + /* Warn about with as NAME */ + if (type == NAME && + !(ps->p_flags & CO_FUTURE_WITH_STATEMENT)) { + if (len == 4 && str[0] == 'w' && strcmp(str, "with") == 0) + warn(with_msg, err_ret->filename, tok->lineno); + else if (!(handling_import || handling_with) && + len == 2 && + str[0] == 'a' && strcmp(str, "as") == 0) + warn(as_msg, err_ret->filename, tok->lineno); + } + else if (type == NAME && + (ps->p_flags & CO_FUTURE_WITH_STATEMENT) && + len == 4 && str[0] == 'w' && strcmp(str, "with") == 0) + handling_with = 1; #endif if ((err_ret->error = |