From: <fwi...@us...> - 2008-08-06 17:54:11
|
Revision: 5094 http://jython.svn.sourceforge.net/jython/?rev=5094&view=rev Author: fwierzbicki Date: 2008-08-06 17:54:07 +0000 (Wed, 06 Aug 2008) Log Message: ----------- Changed grammars to allow most keywords to be used as attributes for Java compatibility. Also added some tests. Removed a couple of tests that use keywords as function names as this is no longer permitted. Allowing keywords to be used as arbitrary NAMEs causes very weird grammar issues. For example for x, in ((1,),(2,)): matched "x, in" as a tuple. Now the permitted use is limited to things like foo.in() Modified Paths: -------------- branches/asm/Lib/test/test_grammar_jy.py branches/asm/Lib/test/test_java_integration.py branches/asm/grammar/Python.g branches/asm/grammar/PythonWalker.g Modified: branches/asm/Lib/test/test_grammar_jy.py =================================================================== --- branches/asm/Lib/test/test_grammar_jy.py 2008-08-06 13:05:15 UTC (rev 5093) +++ branches/asm/Lib/test/test_grammar_jy.py 2008-08-06 17:54:07 UTC (rev 5094) @@ -1,27 +1,10 @@ -"""Tests whether Python keywords that are *not* Java keywords can be used - as method names (needed for Java integration -- for example, if a Java - method is named "print" and we want to use it from Jython). - -Made for Jython. +""" Extra grammar tests for Jython. """ import test_support import unittest -class Keywords(object): - def exec(self): - exec "2+2" - return "success" - - def as(self): - import unittest as eggs - return "success" - class GrammarTest(unittest.TestCase): - def testKeywords(self): - kws = Keywords() - self.assertEquals("success", kws.exec()) - self.assertEquals("success", kws.as()) def testStringPrefixes(self): self.assertEquals(u"spam",U"spam") Modified: branches/asm/Lib/test/test_java_integration.py =================================================================== --- branches/asm/Lib/test/test_java_integration.py 2008-08-06 13:05:15 UTC (rev 5093) +++ branches/asm/Lib/test/test_java_integration.py 2008-08-06 17:54:07 UTC (rev 5094) @@ -172,14 +172,51 @@ class ReservedNamesTest(unittest.TestCase): "Access to java names which are al reserved words" - def test_system_in(self): + def test_in(self): s = System.in self.assert_("java.io.BufferedInputStream" in str(s)) - def test_runtime_exec(self): + def test_exec(self): e = Runtime.getRuntime().exec self.assert_(re.search("method .*exec", str(e)) is not None) + def test_class(self): + b = Byte(10) + self.assert_("java.lang.Byte" in str(b.class)) + + def test_print(self): + #XXX should find a better print test. + System.out.print("") + + #TODO: + #and + #as + #assert + #break + #continue + #def + #del + #elif + #else + #except + #finally + #from + #for + #global + #if + #import + #is + #lambda + #pass + #print + #raise + #return + #try + #while + #with + #yield + + class ImportTest(unittest.TestCase): def test_bad_input_exception(self): Modified: branches/asm/grammar/Python.g =================================================================== --- branches/asm/grammar/Python.g 2008-08-06 13:05:15 UTC (rev 5093) +++ branches/asm/grammar/Python.g 2008-08-06 17:54:07 UTC (rev 5094) @@ -82,9 +82,6 @@ Interactive; Expression; NameTok; - ExecTok; - InTok; - ClassTok; Test; Msg; Level; @@ -506,10 +503,44 @@ : NAME (DOT^ attr)* ; +//attr is here for Java compatibility. A Java foo.getIf() can be called from Jython as foo.if +// so we need to support any keyword as an attribute. + attr : NAME + | AND + | AS + | ASSERT + | BREAK + | CLASS + | CONTINUE + | DEF + | DELETE + | ELIF + | EXCEPT + | EXEC + | FINALLY + | FROM + | FOR + | GLOBAL + | IF + | IMPORT | IN + | IS + | LAMBDA + | NOT + | OR + | ORELSE + | PASS + | PRINT + | RAISE + | RETURN + | TRY + | WHILE + | WITH + | YIELD ; + //decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE decorator: AT dotted_attr ( (LPAREN arglist? RPAREN) -> ^(AT dotted_attr ^(Call ^(Args arglist)?)) @@ -758,16 +789,13 @@ ; //import_as_name: NAME [('as' | NAME) NAME] -import_as_name : name=NAME (keyAS asname=NAME)? +import_as_name : name=NAME (AS asname=NAME)? -> ^(Alias $name ^(Asname $asname)?) ; -//XXX: when does CPython Grammar match "dotted_name NAME NAME"? This may be a big -// problem because of the keyAS rule, which matches NAME (needed to allow -// 'as' to be a method name for Java integration). - +//XXX: when does CPython Grammar match "dotted_name NAME NAME"? //dotted_as_name: dotted_name [('as' | NAME) NAME] -dotted_as_name : dotted_name (keyAS asname=NAME)? +dotted_as_name : dotted_name (AS asname=NAME)? -> ^(Alias dotted_name ^(Asname NAME)?) ; @@ -784,8 +812,8 @@ ; //exec_stmt: 'exec' expr ['in' test [',' test]] -exec_stmt : keyEXEC expr[expr_contextType.Load] (IN t1=test[expr_contextType.Load] (COMMA t2=test[expr_contextType.Load])?)? - -> ^(ExecTok[$keyEXEC.start] expr ^(Globals $t1)? ^(Locals $t2)?) +exec_stmt : EXEC expr[expr_contextType.Load] (IN t1=test[expr_contextType.Load] (COMMA t2=test[expr_contextType.Load])?)? + -> ^(EXEC expr ^(Globals $t1)? ^(Locals $t2)?) ; //assert_stmt: 'assert' test [',' test] @@ -842,14 +870,14 @@ ; //with_var: ('as' | NAME) expr -with_var: (keyAS | NAME) expr[expr_contextType.Load] +with_var: (AS | NAME) expr[expr_contextType.Load] ; //except_clause: 'except' [test [',' test]] -except_clause : 'except' (t1=test[expr_contextType.Load] (COMMA t2=test[expr_contextType.Load])?)? COLON suite +except_clause : EXCEPT (t1=test[expr_contextType.Load] (COMMA t2=test[expr_contextType.Load])?)? COLON suite //Note: passing the 'except' keyword on so we can pass the same offset // as CPython. - -> ^(ExceptHandler 'except' ^(Type $t1)? ^(Value $t2)? ^(Body suite)) + -> ^(EXCEPT ^(Type $t1)? ^(Value $t2)? ^(Body suite)) ; //suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT @@ -895,8 +923,8 @@ | NOTEQUAL | IN | NOT IN -> NotIn - | 'is' - | 'is' NOT -> IsNot + | IS + | IS NOT -> IsNot ; //expr: xor_expr ('|' xor_expr)* @@ -1040,8 +1068,8 @@ ; //classdef: 'class' NAME ['(' [testlist] ')'] ':' suite -classdef: keyCLASS NAME (LPAREN testlist[expr_contextType.Load]? RPAREN)? COLON suite - -> ^(ClassTok[$keyCLASS.start] NAME ^(Bases testlist)? ^(Body suite)) +classdef: CLASS NAME (LPAREN testlist[expr_contextType.Load]? RPAREN)? COLON suite + -> ^(CLASS NAME ^(Bases testlist)? ^(Body suite)) ; //arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) @@ -1119,56 +1147,34 @@ //XXX: //testlist1: test (',' test)* -//These are all Python keywords that are not Java keywords -//This means that Jython needs to support these as NAMEs -//unlike CPython. For now I have only done this for 'as' -//and 'exec'. A chat with Leo Soto on #jython has made me -//realize I may need to do this for *all* keywords, since -//a Java foo.getIf() can be called from Jython as foo.if - -//keyAND : {input.LT(1).getText().equals("and")}? NAME ; -keyAS : {input.LT(1).getText().equals("as")}? NAME ; -//keyDEF : {input.LT(1).getText().equals("def")}? NAME ; -//keyDEL : {input.LT(1).getText().equals("del")}? NAME ; -//keyELIF : {input.LT(1).getText().equals("elif")}? NAME ; -//keyEXCEPT : {input.LT(1).getText().equals("except")}? NAME ; -keyEXEC : {input.LT(1).getText().equals("exec")}? NAME ; -//keyFROM : {input.LT(1).getText().equals("from")}? NAME ; -//keyGLOBAL : {input.LT(1).getText().equals("global")}? NAME ; -keyCLASS : {input.LT(1).getText().equals("class")}? NAME ; -//keyIS : {input.LT(1).getText().equals("is")}? NAME ; -//keyLAMBDA : {input.LT(1).getText().equals("lambda")}? NAME ; -//keyNOT : {input.LT(1).getText().equals("not")}? NAME ; -//keyOR : {input.LT(1).getText().equals("or")}? NAME ; -//keyPASS : {input.LT(1).getText().equals("pass")}? NAME ; -//keyPRINT : {input.LT(1).getText().equals("print")}? NAME ; -//keyRAISE : {input.LT(1).getText().equals("raise")}? NAME ; -//keyWITH : {input.LT(1).getText().equals("with")}? NAME ; -//keyYIELD : {input.LT(1).getText().equals("yield")}? NAME ; - -DEF : 'def' ; -PRINT : 'print' ; +AS : 'as' ; +ASSERT : 'assert' ; BREAK : 'break' ; +CLASS : 'class' ; CONTINUE : 'continue' ; -RETURN : 'return' ; -RAISE : 'raise' ; -PASS : 'pass' ; -IMPORT : 'import' ; +DEF : 'def' ; +DELETE : 'del' ; +ELIF : 'elif' ; +EXCEPT : 'except' ; +EXEC : 'exec' ; +FINALLY : 'finally' ; FROM : 'from' ; FOR : 'for' ; +GLOBAL : 'global' ; +IF : 'if' ; +IMPORT : 'import' ; +IN : 'in' ; +IS : 'is' ; +LAMBDA : 'lambda' ; ORELSE : 'else' ; -ELIF : 'elif' ; -IF : 'if' ; +PASS : 'pass' ; +PRINT : 'print' ; +RAISE : 'raise' ; +RETURN : 'return' ; +TRY : 'try' ; WHILE : 'while' ; WITH : 'with' ; -LAMBDA : 'lambda' ; -GLOBAL : 'global' ; YIELD : 'yield' ; -ASSERT : 'assert' ; -FINALLY : 'finally' ; -DELETE : 'del' ; -TRY : 'try' ; -IN : 'in' ; LPAREN : '(' {implicitLineJoiningLevel++;} ; Modified: branches/asm/grammar/PythonWalker.g =================================================================== --- branches/asm/grammar/PythonWalker.g 2008-08-06 13:05:15 UTC (rev 5093) +++ branches/asm/grammar/PythonWalker.g 2008-08-06 17:54:07 UTC (rev 5094) @@ -420,10 +420,43 @@ } ; +//attr is here for Java compatibility. A Java foo.getIf() can be called from Jython as foo.if +// so we need to support any keyword as an attribute. attr : NAME + | AND + | AS + | ASSERT + | BREAK + | CLASS + | CONTINUE + | DEF + | DELETE + | ELIF + | EXCEPT + | EXEC + | FINALLY + | FROM + | FOR + | GLOBAL + | IF + | IMPORT | IN + | IS + | LAMBDA + | NOT + | OR + | ORELSE + | PASS + | PRINT + | RAISE + | RETURN + | TRY + | WHILE + | WITH + | YIELD ; + stmts returns [List stypes] scope { List statements; @@ -752,7 +785,7 @@ //Using NAME instead of 'exec' for Java integration exec_stmt - : ^(ExecTok exec=test[expr_contextType.Load] (^(Globals globals=test[expr_contextType.Load]))? (^(Locals locals=test[expr_contextType.Load]))?) { + : ^(EXEC exec=test[expr_contextType.Load] (^(Globals globals=test[expr_contextType.Load]))? (^(Locals locals=test[expr_contextType.Load]))?) { exprType g = null; if ($Globals != null) { g = $globals.etype; @@ -761,7 +794,7 @@ if ($Locals != null) { loc = $locals.etype; } - $stmts::statements.add(new Exec($ExecTok, $exec.etype, g, loc)); + $stmts::statements.add(new Exec($EXEC, $exec.etype, g, loc)); } ; @@ -854,7 +887,7 @@ ; except_clause[List handlers] - : ^(ExceptHandler 'except' (^(Type type=test[expr_contextType.Load]))? (^(Value name=test[expr_contextType.Store]))? ^(Body stmts)) { + : ^(EXCEPT (^(Type type=test[expr_contextType.Load]))? (^(Value name=test[expr_contextType.Store]))? ^(Body stmts)) { stmtType[] b; if ($stmts.start != null) { b = (stmtType[])$stmts.stypes.toArray(new stmtType[$stmts.stypes.size()]); @@ -867,7 +900,7 @@ if ($Value != null) { n = $name.etype; } - handlers.add(new excepthandlerType($ExceptHandler, t, n, b, $ExceptHandler.getLine(), $ExceptHandler.getCharPositionInLine())); + handlers.add(new excepthandlerType($EXCEPT, t, n, b, $EXCEPT.getLine(), $EXCEPT.getCharPositionInLine())); } ; @@ -880,7 +913,7 @@ //using NAME because of Java integration for 'as' with_var returns [exprType etype] - : NAME test[expr_contextType.Store] { + : (AS | NAME) test[expr_contextType.Store] { $etype = $test.etype; } ; @@ -1046,7 +1079,7 @@ | NOTEQUAL {$op = cmpopType.NotEq;} | IN {$op = cmpopType.In;} | NotIn {$op = cmpopType.NotIn;} - | 'is' {$op = cmpopType.Is;} + | IS {$op = cmpopType.Is;} | IsNot {$op = cmpopType.IsNot;} ; @@ -1269,14 +1302,14 @@ ; classdef - : ^(ClassTok classname=NAME (^(Bases bases))? ^(Body stmts)) { + : ^(CLASS classname=NAME (^(Bases bases))? ^(Body stmts)) { List b; if ($Bases != null) { b = $bases.names; } else { b = new ArrayList(); } - $stmts::statements.add(makeClassDef($ClassTok, $classname, b, $stmts.stypes)); + $stmts::statements.add(makeClassDef($CLASS, $classname, b, $stmts.stypes)); } ; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |