From 28f739aad47f1022fda19e4f3d8ad1b8228d221b Mon Sep 17 00:00:00 2001 From: Fred Drake Date: Fri, 25 Aug 2000 22:42:40 +0000 Subject: [PATCH] Update the parser module to support augmented assignment. Add some test cases. --- Lib/test/output/test_parser | 59 +++++++++++++------- Lib/test/test_parser.py | 106 ++++++++++++++++++++++++++++-------- Modules/parsermodule.c | 36 ++++++++++-- 3 files changed, 152 insertions(+), 49 deletions(-) diff --git a/Lib/test/output/test_parser b/Lib/test/output/test_parser index c5b6777babe..86ec22d08e6 100644 --- a/Lib/test/output/test_parser +++ b/Lib/test/output/test_parser @@ -1,28 +1,42 @@ test_parser Expressions: -foo(1) -[1, 2, 3] -[x**3 for x in range(20)] -[x**3 for x in range(20) if x % 3] -foo(*args) -foo(*args, **kw) -foo(**kw) -foo(key=value) -foo(key=value, *args) -foo(key=value, *args, **kw) -foo(key=value, **kw) -foo(a, b, c, *args) -foo(a, b, c, *args, **kw) -foo(a, b, c, **kw) -foo + bar +expr: foo(1) +expr: [1, 2, 3] +expr: [x**3 for x in range(20)] +expr: [x**3 for x in range(20) if x % 3] +expr: foo(*args) +expr: foo(*args, **kw) +expr: foo(**kw) +expr: foo(key=value) +expr: foo(key=value, *args) +expr: foo(key=value, *args, **kw) +expr: foo(key=value, **kw) +expr: foo(a, b, c, *args) +expr: foo(a, b, c, *args, **kw) +expr: foo(a, b, c, **kw) +expr: foo + bar Statements: -print -print 1 -print 1, -print >>fp -print >>fp, 1 -print >>fp, 1, +suite: print +suite: print 1 +suite: print 1, +suite: print >>fp +suite: print >>fp, 1 +suite: print >>fp, 1, +suite: a +suite: a = b +suite: a = b = c = d = e +suite: a += b +suite: a -= b +suite: a *= b +suite: a /= b +suite: a %= b +suite: a &= b +suite: a |= b +suite: a ^= b +suite: a <<= b +suite: a >>= b +suite: a **= b Invalid parse trees: @@ -34,3 +48,6 @@ caught expected exception for invalid tree a,,c caught expected exception for invalid tree + +a $= b +caught expected exception for invalid tree diff --git a/Lib/test/test_parser.py b/Lib/test/test_parser.py index 559a0f4b9ba..bc41de42676 100644 --- a/Lib/test/test_parser.py +++ b/Lib/test/test_parser.py @@ -1,3 +1,4 @@ +import os.path import parser import pprint import sys @@ -12,38 +13,68 @@ from test_support import verbose # def roundtrip(f, s): - print s st1 = f(s) t = st1.totuple() st2 = parser.sequence2ast(t) +def roundtrip_fromfile(filename): + roundtrip(suite, open(filename).read()) + +def test_expr(s): + print "expr:", s + roundtrip(expr, s) + +def test_suite(s): + print "suite:", s + roundtrip(suite, s) + print "Expressions:" -roundtrip(expr, "foo(1)") -roundtrip(expr, "[1, 2, 3]") -roundtrip(expr, "[x**3 for x in range(20)]") -roundtrip(expr, "[x**3 for x in range(20) if x % 3]") -roundtrip(expr, "foo(*args)") -roundtrip(expr, "foo(*args, **kw)") -roundtrip(expr, "foo(**kw)") -roundtrip(expr, "foo(key=value)") -roundtrip(expr, "foo(key=value, *args)") -roundtrip(expr, "foo(key=value, *args, **kw)") -roundtrip(expr, "foo(key=value, **kw)") -roundtrip(expr, "foo(a, b, c, *args)") -roundtrip(expr, "foo(a, b, c, *args, **kw)") -roundtrip(expr, "foo(a, b, c, **kw)") -roundtrip(expr, "foo + bar") +test_expr("foo(1)") +test_expr("[1, 2, 3]") +test_expr("[x**3 for x in range(20)]") +test_expr("[x**3 for x in range(20) if x % 3]") +test_expr("foo(*args)") +test_expr("foo(*args, **kw)") +test_expr("foo(**kw)") +test_expr("foo(key=value)") +test_expr("foo(key=value, *args)") +test_expr("foo(key=value, *args, **kw)") +test_expr("foo(key=value, **kw)") +test_expr("foo(a, b, c, *args)") +test_expr("foo(a, b, c, *args, **kw)") +test_expr("foo(a, b, c, **kw)") +test_expr("foo + bar") print print "Statements:" -roundtrip(suite, "print") -roundtrip(suite, "print 1") -roundtrip(suite, "print 1,") -roundtrip(suite, "print >>fp") -roundtrip(suite, "print >>fp, 1") -roundtrip(suite, "print >>fp, 1,") +test_suite("print") +test_suite("print 1") +test_suite("print 1,") +test_suite("print >>fp") +test_suite("print >>fp, 1") +test_suite("print >>fp, 1,") + +# expr_stmt +test_suite("a") +test_suite("a = b") +test_suite("a = b = c = d = e") +test_suite("a += b") +test_suite("a -= b") +test_suite("a *= b") +test_suite("a /= b") +test_suite("a %= b") +test_suite("a &= b") +test_suite("a |= b") +test_suite("a ^= b") +test_suite("a <<= b") +test_suite("a >>= b") +test_suite("a **= b") + +#d = os.path.dirname(os.__file__) +#roundtrip_fromfile(os.path.join(d, "os.py")) +#roundtrip_fromfile(os.path.join(d, "test", "test_parser.py")) # # Second, we take *invalid* trees and make sure we get ParserError @@ -114,3 +145,34 @@ tree = \ (0, '')) check_bad_tree(tree, "a,,c") + +# a $= b +tree = \ +(257, + (264, + (265, + (266, + (267, + (312, + (291, + (292, + (293, + (294, + (296, + (297, + (298, + (299, (300, (301, (302, (303, (304, (1, 'a'))))))))))))))), + (268, (37, '$=')), + (312, + (291, + (292, + (293, + (294, + (296, + (297, + (298, + (299, (300, (301, (302, (303, (304, (1, 'b'))))))))))))))))), + (4, ''))), + (0, '')) + +check_bad_tree(tree, "a $= b") diff --git a/Modules/parsermodule.c b/Modules/parsermodule.c index ef8ec9bcf60..50161cffedf 100644 --- a/Modules/parsermodule.c +++ b/Modules/parsermodule.c @@ -1467,10 +1467,34 @@ validate_expr_stmt(node *tree) && is_odd(nch) && validate_testlist(CHILD(tree, 0))); - for (j = 1; res && (j < nch); j += 2) - res = (validate_equal(CHILD(tree, j)) - && validate_testlist(CHILD(tree, j + 1))); + if (res && nch == 3 + && TYPE(CHILD(tree, 1)) == augassign) { + res = (validate_numnodes(CHILD(tree, 1), 1, "augassign") + && validate_testlist(CHILD(tree, 2))); + if (res) { + char *s = STR(CHILD(CHILD(tree, 1), 0)); + + res = (strcmp(s, "+=") == 0 + || strcmp(s, "-=") == 0 + || strcmp(s, "*=") == 0 + || strcmp(s, "/=") == 0 + || strcmp(s, "%=") == 0 + || strcmp(s, "&=") == 0 + || strcmp(s, "|=") == 0 + || strcmp(s, "^=") == 0 + || strcmp(s, "<<=") == 0 + || strcmp(s, ">>=") == 0 + || strcmp(s, "**=") == 0); + if (!res) + err_string("illegal augmmented assignment operator"); + } + } + else { + for (j = 1; res && (j < nch); j += 2) + res = (validate_equal(CHILD(tree, j)) + && validate_testlist(CHILD(tree, j + 1))); + } return (res); } @@ -2822,9 +2846,11 @@ static PyMethodDef parser_functions[] = { }; +DL_IMPORT(void) initparser(void); + DL_EXPORT(void) initparser(void) - { +{ PyObject* module; PyObject* dict; @@ -2834,8 +2860,6 @@ initparser(void) if (parser_error == 0) parser_error = PyErr_NewException("parser.ParserError", NULL, NULL); - else - puts("parser module initialized more than once!"); if ((parser_error == 0) || (PyDict_SetItemString(dict, "ParserError", parser_error) != 0)) {