forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merged revisions 61596-61597 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r61596 | martin.v.loewis | 2008-03-18 23:43:46 -0500 (Di, 18 Mär 2008) | 2 lines Import lib2to3. ........ r61597 | martin.v.loewis | 2008-03-18 23:58:04 -0500 (Di, 18 Mär 2008) | 3 lines Initialized merge tracking via "svnmerge" with revisions "1-61595" from svn+ssh://pythondev@svn.python.org/sandbox/trunk/2to3/lib2to3 ........
- Loading branch information
Showing
67 changed files
with
11,990 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
# Grammar for Python | ||
|
||
# Note: Changing the grammar specified in this file will most likely | ||
# require corresponding changes in the parser module | ||
# (../Modules/parsermodule.c). If you can't make the changes to | ||
# that module yourself, please co-ordinate the required changes | ||
# with someone who can; ask around on python-dev for help. Fred | ||
# Drake <fdrake@acm.org> will probably be listening there. | ||
|
||
# NOTE WELL: You should also follow all the steps listed in PEP 306, | ||
# "How to Change Python's Grammar" | ||
|
||
# Commands for Kees Blom's railroad program | ||
#diagram:token NAME | ||
#diagram:token NUMBER | ||
#diagram:token STRING | ||
#diagram:token NEWLINE | ||
#diagram:token ENDMARKER | ||
#diagram:token INDENT | ||
#diagram:output\input python.bla | ||
#diagram:token DEDENT | ||
#diagram:output\textwidth 20.04cm\oddsidemargin 0.0cm\evensidemargin 0.0cm | ||
#diagram:rules | ||
|
||
# Start symbols for the grammar: | ||
# file_input is a module or sequence of commands read from an input file; | ||
# single_input is a single interactive statement; | ||
# eval_input is the input for the eval() and input() functions. | ||
# NB: compound_stmt in single_input is followed by extra NEWLINE! | ||
file_input: (NEWLINE | stmt)* ENDMARKER | ||
single_input: NEWLINE | simple_stmt | compound_stmt NEWLINE | ||
eval_input: testlist NEWLINE* ENDMARKER | ||
|
||
decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE | ||
decorators: decorator+ | ||
decorated: decorators (classdef | funcdef) | ||
funcdef: 'def' NAME parameters ['->' test] ':' suite | ||
parameters: '(' [typedargslist] ')' | ||
typedargslist: ((tfpdef ['=' test] ',')* | ||
('*' [tname] (',' tname ['=' test])* [',' '**' tname] | '**' tname) | ||
| tfpdef ['=' test] (',' tfpdef ['=' test])* [',']) | ||
tname: NAME [':' test] | ||
tfpdef: tname | '(' tfplist ')' | ||
tfplist: tfpdef (',' tfpdef)* [','] | ||
varargslist: ((vfpdef ['=' test] ',')* | ||
('*' [vname] (',' vname ['=' test])* [',' '**' vname] | '**' vname) | ||
| vfpdef ['=' test] (',' vfpdef ['=' test])* [',']) | ||
vname: NAME | ||
vfpdef: vname | '(' vfplist ')' | ||
vfplist: vfpdef (',' vfpdef)* [','] | ||
|
||
stmt: simple_stmt | compound_stmt | ||
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE | ||
small_stmt: (expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | | ||
import_stmt | global_stmt | exec_stmt | assert_stmt) | ||
expr_stmt: testlist (augassign (yield_expr|testlist) | | ||
('=' (yield_expr|testlist))*) | ||
augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | | ||
'<<=' | '>>=' | '**=' | '//=') | ||
# For normal assignments, additional restrictions enforced by the interpreter | ||
print_stmt: 'print' ( [ test (',' test)* [','] ] | | ||
'>>' test [ (',' test)+ [','] ] ) | ||
del_stmt: 'del' exprlist | ||
pass_stmt: 'pass' | ||
flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt | ||
break_stmt: 'break' | ||
continue_stmt: 'continue' | ||
return_stmt: 'return' [testlist] | ||
yield_stmt: yield_expr | ||
raise_stmt: 'raise' [test ['from' test | ',' test [',' test]]] | ||
import_stmt: import_name | import_from | ||
import_name: 'import' dotted_as_names | ||
import_from: ('from' ('.'* dotted_name | '.'+) | ||
'import' ('*' | '(' import_as_names ')' | import_as_names)) | ||
import_as_name: NAME ['as' NAME] | ||
dotted_as_name: dotted_name ['as' NAME] | ||
import_as_names: import_as_name (',' import_as_name)* [','] | ||
dotted_as_names: dotted_as_name (',' dotted_as_name)* | ||
dotted_name: NAME ('.' NAME)* | ||
global_stmt: ('global' | 'nonlocal') NAME (',' NAME)* | ||
exec_stmt: 'exec' expr ['in' test [',' test]] | ||
assert_stmt: 'assert' test [',' test] | ||
|
||
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | ||
if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite] | ||
while_stmt: 'while' test ':' suite ['else' ':' suite] | ||
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] | ||
try_stmt: ('try' ':' suite | ||
((except_clause ':' suite)+ | ||
['else' ':' suite] | ||
['finally' ':' suite] | | ||
'finally' ':' suite)) | ||
with_stmt: 'with' test [ with_var ] ':' suite | ||
with_var: 'as' expr | ||
# NB compile.c makes sure that the default except clause is last | ||
except_clause: 'except' [test [(',' | 'as') test]] | ||
suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT | ||
|
||
# Backward compatibility cruft to support: | ||
# [ x for x in lambda: True, lambda: False if x() ] | ||
# even while also allowing: | ||
# lambda x: 5 if x else 2 | ||
# (But not a mix of the two) | ||
testlist_safe: old_test [(',' old_test)+ [',']] | ||
old_test: or_test | old_lambdef | ||
old_lambdef: 'lambda' [varargslist] ':' old_test | ||
|
||
test: or_test ['if' or_test 'else' test] | lambdef | ||
or_test: and_test ('or' and_test)* | ||
and_test: not_test ('and' not_test)* | ||
not_test: 'not' not_test | comparison | ||
comparison: expr (comp_op expr)* | ||
comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' | ||
expr: xor_expr ('|' xor_expr)* | ||
xor_expr: and_expr ('^' and_expr)* | ||
and_expr: shift_expr ('&' shift_expr)* | ||
shift_expr: arith_expr (('<<'|'>>') arith_expr)* | ||
arith_expr: term (('+'|'-') term)* | ||
term: factor (('*'|'/'|'%'|'//') factor)* | ||
factor: ('+'|'-'|'~') factor | power | ||
power: atom trailer* ['**' factor] | ||
atom: ('(' [yield_expr|testlist_gexp] ')' | | ||
'[' [listmaker] ']' | | ||
'{' [dictsetmaker] '}' | | ||
'`' testlist1 '`' | | ||
NAME | NUMBER | STRING+ | '.' '.' '.') | ||
listmaker: test ( comp_for | (',' test)* [','] ) | ||
testlist_gexp: test ( comp_for | (',' test)* [','] ) | ||
lambdef: 'lambda' [varargslist] ':' test | ||
trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME | ||
subscriptlist: subscript (',' subscript)* [','] | ||
subscript: test | [test] ':' [test] [sliceop] | ||
sliceop: ':' [test] | ||
exprlist: expr (',' expr)* [','] | ||
testlist: test (',' test)* [','] | ||
dictsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) | | ||
(test (comp_for | (',' test)* [','])) ) | ||
|
||
classdef: 'class' NAME ['(' [arglist] ')'] ':' suite | ||
|
||
arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) | ||
argument: test [comp_for] | test '=' test # Really [keyword '='] test | ||
|
||
comp_iter: comp_for | comp_if | ||
comp_for: 'for' exprlist 'in' testlist_safe [comp_iter] | ||
comp_if: 'if' old_test [comp_iter] | ||
|
||
testlist1: test (',' test)* | ||
|
||
# not used in grammar, but may appear in "node" passed from Parser to Compiler | ||
encoding_decl: NAME | ||
|
||
yield_expr: 'yield' [testlist] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright 2006 Google, Inc. All Rights Reserved. | ||
# Licensed to PSF under a Contributor Agreement. | ||
|
||
# A grammar to describe tree matching patterns. | ||
# Not shown here: | ||
# - 'TOKEN' stands for any token (leaf node) | ||
# - 'any' stands for any node (leaf or interior) | ||
# With 'any' we can still specify the sub-structure. | ||
|
||
# The start symbol is 'Matcher'. | ||
|
||
Matcher: Alternatives ENDMARKER | ||
|
||
Alternatives: Alternative ('|' Alternative)* | ||
|
||
Alternative: (Unit | NegatedUnit)+ | ||
|
||
Unit: [NAME '='] ( STRING [Repeater] | ||
| NAME [Details] [Repeater] | ||
| '(' Alternatives ')' [Repeater] | ||
| '[' Alternatives ']' | ||
) | ||
|
||
NegatedUnit: 'not' (STRING | NAME [Details] | '(' Alternatives ')') | ||
|
||
Repeater: '*' | '+' | '{' NUMBER [',' NUMBER] '}' | ||
|
||
Details: '<' Alternatives '>' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
#empty |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Dummy file to make this directory a package. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
# Copyright 2006 Google, Inc. All Rights Reserved. | ||
# Licensed to PSF under a Contributor Agreement. | ||
|
||
"""Base class for fixers (optional, but recommended).""" | ||
|
||
# Python imports | ||
import logging | ||
import itertools | ||
|
||
# Get a usable 'set' constructor | ||
try: | ||
set | ||
except NameError: | ||
from sets import Set as set | ||
|
||
# Local imports | ||
from ..patcomp import PatternCompiler | ||
from .. import pygram | ||
|
||
class BaseFix(object): | ||
|
||
"""Optional base class for fixers. | ||
The subclass name must be FixFooBar where FooBar is the result of | ||
removing underscores and capitalizing the words of the fix name. | ||
For example, the class name for a fixer named 'has_key' should be | ||
FixHasKey. | ||
""" | ||
|
||
PATTERN = None # Most subclasses should override with a string literal | ||
pattern = None # Compiled pattern, set by compile_pattern() | ||
options = None # Options object passed to initializer | ||
filename = None # The filename (set by set_filename) | ||
logger = None # A logger (set by set_filename) | ||
numbers = itertools.count(1) # For new_name() | ||
used_names = set() # A set of all used NAMEs | ||
order = "post" # Does the fixer prefer pre- or post-order traversal | ||
explicit = False # Is this ignored by refactor.py -f all? | ||
|
||
# Shortcut for access to Python grammar symbols | ||
syms = pygram.python_symbols | ||
|
||
def __init__(self, options, log): | ||
"""Initializer. Subclass may override. | ||
Args: | ||
options: an optparse.Values instance which can be used | ||
to inspect the command line options. | ||
log: a list to append warnings and other messages to. | ||
""" | ||
self.options = options | ||
self.log = log | ||
self.compile_pattern() | ||
|
||
def compile_pattern(self): | ||
"""Compiles self.PATTERN into self.pattern. | ||
Subclass may override if it doesn't want to use | ||
self.{pattern,PATTERN} in .match(). | ||
""" | ||
if self.PATTERN is not None: | ||
self.pattern = PatternCompiler().compile_pattern(self.PATTERN) | ||
|
||
def set_filename(self, filename): | ||
"""Set the filename, and a logger derived from it. | ||
The main refactoring tool should call this. | ||
""" | ||
self.filename = filename | ||
self.logger = logging.getLogger(filename) | ||
|
||
def match(self, node): | ||
"""Returns match for a given parse tree node. | ||
Should return a true or false object (not necessarily a bool). | ||
It may return a non-empty dict of matching sub-nodes as | ||
returned by a matching pattern. | ||
Subclass may override. | ||
""" | ||
results = {"node": node} | ||
return self.pattern.match(node, results) and results | ||
|
||
def transform(self, node, results): | ||
"""Returns the transformation for a given parse tree node. | ||
Args: | ||
node: the root of the parse tree that matched the fixer. | ||
results: a dict mapping symbolic names to part of the match. | ||
Returns: | ||
None, or a node that is a modified copy of the | ||
argument node. The node argument may also be modified in-place to | ||
effect the same change. | ||
Subclass *must* override. | ||
""" | ||
raise NotImplementedError() | ||
|
||
def parenthesize(self, node): | ||
"""Wrapper around pygram.parenthesize().""" | ||
return pygram.parenthesize(node) | ||
|
||
def new_name(self, template="xxx_todo_changeme"): | ||
"""Return a string suitable for use as an identifier | ||
The new name is guaranteed not to conflict with other identifiers. | ||
""" | ||
name = template | ||
while name in self.used_names: | ||
name = template + str(self.numbers.next()) | ||
self.used_names.add(name) | ||
return name | ||
|
||
def log_message(self, message): | ||
if self.first_log: | ||
self.first_log = False | ||
self.log.append("### In file %s ###" % self.filename) | ||
self.log.append(message) | ||
|
||
def cannot_convert(self, node, reason=None): | ||
"""Warn the user that a given chunk of code is not valid Python 3, | ||
but that it cannot be converted automatically. | ||
First argument is the top-level node for the code in question. | ||
Optional second argument is why it can't be converted. | ||
""" | ||
lineno = node.get_lineno() | ||
for_output = node.clone() | ||
for_output.set_prefix("") | ||
msg = "Line %d: could not convert: %s" | ||
self.log_message(msg % (lineno, for_output)) | ||
if reason: | ||
self.log_message(reason) | ||
|
||
def warning(self, node, reason): | ||
"""Used for warning the user about possible uncertainty in the | ||
translation. | ||
First argument is the top-level node for the code in question. | ||
Optional second argument is why it can't be converted. | ||
""" | ||
lineno = node.get_lineno() | ||
self.log_message("Line %d: %s" % (lineno, reason)) | ||
|
||
def start_tree(self, tree, filename): | ||
"""Some fixers need to maintain tree-wide state. | ||
This method is called once, at the start of tree fix-up. | ||
tree - the root node of the tree to be processed. | ||
filename - the name of the file the tree came from. | ||
""" | ||
self.used_names = tree.used_names | ||
self.set_filename(filename) | ||
self.numbers = itertools.count(1) | ||
self.first_log = True | ||
|
||
def finish_tree(self, tree, filename): | ||
"""Some fixers need to maintain tree-wide state. | ||
This method is called once, at the conclusion of tree fix-up. | ||
tree - the root node of the tree to be processed. | ||
filename - the name of the file the tree came from. | ||
""" | ||
pass |
Oops, something went wrong.