blob: 63784d71cd3d85e450b0729d9e22b8fe37910102 [file] [log] [blame]
grammar python_v3;
//parser grammar python_v3;
options
{
// output = AST;
// k = 2;
language = Java;
}
tokens {
INDENT;
DEDENT;
}
@lexer::header {
package org.eclipse.dltk.python.internal.core.parsers;
}
@parser::header {
package org.eclipse.dltk.python.internal.core.parsers;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.dltk.ast.DLTKToken;
import org.eclipse.dltk.ast.declarations.Decorator;
import org.eclipse.dltk.ast.declarations.MethodDeclaration;
import org.eclipse.dltk.ast.declarations.ModuleDeclaration;
import org.eclipse.dltk.ast.expressions.Expression;
import org.eclipse.dltk.ast.expressions.ExpressionList;
import org.eclipse.dltk.ast.expressions.NumericLiteral;
import org.eclipse.dltk.ast.expressions.StringLiteral;
import org.eclipse.dltk.ast.references.VariableReference;
import org.eclipse.dltk.ast.statements.Block;
import org.eclipse.dltk.ast.statements.Statement;
import org.eclipse.dltk.compiler.problem.IProblemReporter;
import org.eclipse.dltk.python.parser.ast.PythonArgument;
import org.eclipse.dltk.python.parser.ast.PythonAssertStatement;
import org.eclipse.dltk.python.parser.ast.PythonClassDeclaration;
import org.eclipse.dltk.python.parser.ast.PythonDelStatement;
import org.eclipse.dltk.python.parser.ast.PythonExceptStatement;
import org.eclipse.dltk.python.parser.ast.PythonForStatement;
import org.eclipse.dltk.python.parser.ast.PythonImportFromStatement;
import org.eclipse.dltk.python.parser.ast.PythonImportStatement;
import org.eclipse.dltk.python.parser.ast.PythonRaiseStatement;
import org.eclipse.dltk.python.parser.ast.PythonTryStatement;
import org.eclipse.dltk.python.parser.ast.PythonWhileStatement;
import org.eclipse.dltk.python.parser.ast.PythonYieldStatement;
import org.eclipse.dltk.python.parser.ast.expressions.Assignment;
import org.eclipse.dltk.python.parser.ast.expressions.BinaryExpression;
import org.eclipse.dltk.python.parser.ast.expressions.CallHolder;
import org.eclipse.dltk.python.parser.ast.expressions.ComplexNumericLiteral;
import org.eclipse.dltk.python.parser.ast.expressions.EmptyExpression;
import org.eclipse.dltk.python.parser.ast.expressions.ExtendedVariableReference;
import org.eclipse.dltk.python.parser.ast.expressions.IndexHolder;
import org.eclipse.dltk.python.parser.ast.expressions.NotStrictAssignment;
import org.eclipse.dltk.python.parser.ast.expressions.PrintExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonAllImportExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonDictExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonForListExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonFunctionDecorator;
import org.eclipse.dltk.python.parser.ast.expressions.PythonImportAsExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonImportExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonLambdaExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonListExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonListForExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonSubscriptExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonTestListExpression;
import org.eclipse.dltk.python.parser.ast.expressions.PythonTupleExpression;
import org.eclipse.dltk.python.parser.ast.expressions.UnaryExpression;
import org.eclipse.dltk.python.parser.ast.statements.BreakStatement;
import org.eclipse.dltk.python.parser.ast.statements.ContinueStatement;
import org.eclipse.dltk.python.parser.ast.statements.EmptyStatement;
import org.eclipse.dltk.python.parser.ast.statements.ExecStatement;
import org.eclipse.dltk.python.parser.ast.statements.IfStatement;
import org.eclipse.dltk.python.parser.ast.statements.ReturnStatement;
import org.eclipse.dltk.python.parser.ast.statements.TryFinallyStatement;
import org.eclipse.dltk.python.parser.ast.PythonWithStatement;
}
@lexer::members {
/** Handles context-sensitive lexing of implicit line joining such as
* the case where newline is ignored in cases like this:
* a = [3,
* 4]
*/
public int implicitLineJoiningLevel = 0;
public int startPos=-1;
public void emitErrorMessage(String msg) {
}
}
@parser::members {
public DLTKPythonErrorReporter reporter;
public ModuleDeclaration decl;
public int length;
public DLTKTokenConverter converter;
DLTKToken toDLTK(Token token) {
return converter.convert(token);
}
public void emitErrorMessage(String msg) {
reporter.reportMessage(msg);
}
public void reportError(RecognitionException e) {
if( reporter != null ) {
reporter.reportError(e);
}
}
public void setStartEndForEmbracedExpr(Expression exp, Token lb, Token rb)
{
exp.setStart(toDLTK(lb).getColumn());
exp.setEnd(toDLTK(rb).getColumn()+1);
}
}
@rulecatch {
catch (RecognitionException re) {
if( reporter != null ) {
reporter.reportError(re);
}
recover(input,re);
}
catch (Throwable extre) {
//System.err.println(t);
if( reporter != null ) {
reporter.reportThrowable(extre);
}
}
}
// Parser rules
file_input:
(
NEWLINE
|
s = stmt
{
//statements.addAll( s );
if( s != null ) {
Iterator i = s.iterator();
while( i.hasNext() ) {
Statement sst = (Statement)i.next();
if( sst != null ) {
decl.addStatement( sst );
}
}
}
}
)*
EOF
//{
// decl.setStatements( statements );
//}
;
// Decorator grammar. 2.4.x
// decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
// decorators: decorator+
decorator returns [ Decorator decorator = null ]:
dec = DECORATOR_S
dottedName = dot_name
(
lp0 = LPAREN
arguments = arglist
rp0 = RPAREN
{
decorator = new PythonFunctionDecorator( toDLTK( dottedName), toDLTK(dec), toDLTK(rp0), arguments );
}
)?
{
if( decorator == null ) {
decorator = new PythonFunctionDecorator( toDLTK( dottedName ), toDLTK(dec) );
}
}
NEWLINE
;
decoraror_list returns [List decorators = new ArrayList() ]:
(
dec = decorator
{
if( dec != null ) {
decorators.add( dec );
}
}
)+
;
//
// Function declaration
funcdef returns [ MethodDeclaration methodDeclaration = null; ]:
(
decorators = decoraror_list
)?
w = 'def'
tu = NAME
{
methodDeclaration = new MethodDeclaration( toDLTK( w ), toDLTK( tu ) );
if( decorators != null ) {
methodDeclaration.setDecorators( decorators );
}
//this.fParameters.clear();
List params = new ArrayList();
//Block body;
}
parameters[ params ]
{
methodDeclaration.acceptArguments( params );
}
e = COLON
body = suite
{
methodDeclaration.acceptBody( body );
}
;
// function parameters
parameters[ List params ]:
LPAREN
(varargslist[ params ])?
RPAREN
;
// List of arguments
varargslist[ List params ]:
defparameter[params]
(
options { greedy=true;} :COMMA
defparameter[ params ]
)*
(COMMA
( STAR tu = NAME
{
params.add( new PythonArgument( toDLTK( tu ) ) );
}
(COMMA DOUBLESTAR t1 = NAME
{
params.add( new PythonArgument( toDLTK( t1 ) ) );
}
)?
| DOUBLESTAR t2 = NAME
{
params.add( new PythonArgument( toDLTK( t2 ) ) );
}
)?
)?
| STAR m = NAME
{
params.add( new PythonArgument( toDLTK( m ) ) );
}
(COMMA
DOUBLESTAR m1 = NAME
{
params.add( new PythonArgument( toDLTK( m1 ) ) );
}
)?
| DOUBLESTAR m2 = NAME
{
params.add( new PythonArgument( toDLTK( m2 ) ) );
}
;
// Parameter with possible initialization expression.
defparameter[ List params ]:
lastParam = fpdef[ params ]
(ASSIGN
initExpr=test
{
if( lastParam != null ) {
lastParam.assign( initExpr );
}
}
)?
;
// Parameter declaration
fpdef [ List params ] returns [ PythonArgument argument = null ]:
tu = NAME
{
argument = new PythonArgument( toDLTK( tu ) );
params.add( argument );
}
|LPAREN fplist[params] RPAREN
;
//
fplist [List params ]:
fpdef[ params ]
(options { greedy=true; }:
COMMA fpdef[ params ]
)*
(COMMA)?
;
////////////////////////////////////////////////////////////////////
//// Statements Part////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// Statement rule
simple_stmt [ List stmts ]:
small_stmt[ stmts ]
(options { greedy = true; }:
SEMI small_stmt[ stmts ]
) * (SEMI)?
NEWLINE
; stmt returns [ ArrayList statements = new ArrayList( ) ]:
(
{
List simpleStatements = new ArrayList();
}
simple_stmt[ simpleStatements ] { statements.addAll( simpleStatements ); }
|
compoundStatement = compound_stmt { statements.add( compoundStatement ); }
)
;
// Simple statement rule.
// Small statement declaration
small_stmt [ List stmts ] returns [ Statement rstatement = null ]:
(
statement1 = expr_stmt { rstatement = statement1; }
| statement2 = print_stmt{ rstatement = statement2; }
| statement3 = del_stmt{ rstatement = statement3; }
| statement4 = pass_stmt{ rstatement = statement4; }
| statement5 = flow_stmt{ rstatement = statement5; }
| statement6 = import_stmt{ rstatement = statement6; }
| statement7 = global_stmt{ rstatement = statement7; }
| statement8 = exec_stmt{ rstatement = statement8; }
| statement9 = assert_stmt{ rstatement = statement9; }
)
{
if( rstatement != null )
stmts.add( rstatement );
}
;
// Expression rule
expr_stmt returns [ Expression exp = null ] :
exp0 = testlist { exp = exp0; }
(
type = augassign
right = testlist
{
if( type != 0 ) {
NotStrictAssignment e = new NotStrictAssignment( exp, type, right );
exp = e;
}
else {
exp = new Assignment( exp, right );
}
}
|
(
a = ASSIGN
right = testlist
{
if( type != 0 ) {
NotStrictAssignment e = new NotStrictAssignment( exp, type, right );
exp = e;
}
else {
exp = new Assignment( exp, right );
}
}
)+
)?
{
if( exp == null )
exp = new EmptyExpression();
}
;
augassign returns[ int type = 0 ] :
PLUSEQUAL
{
type = Expression.E_PLUS_ASSIGN;
}
| MINUSEQUAL
{
type = Expression.E_MINUS_ASSIGN;
}
| STAREQUAL
{
type = Expression.E_MULT_ASSIGN;
}
| SLASHEQUAL
{
type = Expression.E_DIV_ASSIGN;
}
| PERCENTEQUAL
{
type = Expression.E_MOD_ASSIGN;
}
| AMPEREQUAL
{
type = Expression.E_BAND_ASSIGN;
}
| VBAREQUAL
{
type = Expression.E_BOR_ASSIGN;
}
| CIRCUMFLEXEQUAL
{
type = Expression.E_BXOR_ASSIGN;
}
| LEFTSHIFTEQUAL
{
type = Expression.E_SL_ASSIGN;
}
| RIGHTSHIFTEQUAL
{
type = Expression.E_SR_ASSIGN;
}
| DOUBLESTAREQUAL
{
type = Expression.E_DOUBLESTAR_ASSIGN;
}
| DOUBLESLASHEQUAL
{
type = Expression.E_DOUBLEDIV_ASSIGN;
}
;
// Print rule statement
print_stmt returns [ Statement statement = null ]:
tu = 'print'
(
ex = testlist
| RIGHTSHIFT
ex = testlist
)?
{
statement = new PrintExpression( toDLTK( tu ), ex );
if( ex != null ) {
statement.setEnd(ex.sourceEnd());
}
}
;
// Delete statement
del_stmt returns [ Statement statement = null ]:
sa = 'del'
tu = exprlist
{
statement = new PythonDelStatement( toDLTK( sa ), tu );
}
;
// Pass statement
pass_stmt returns [ Statement statement = null]:
tu = 'pass'
{
statement = new EmptyStatement( toDLTK( tu ) );
}
;
// Flow statement
flow_stmt returns [ Statement statement = null ]:
statement0 = break_stmt { statement = statement0; }
| statement1 = continue_stmt{ statement = statement1; }
| statement2 = return_stmt{ statement = statement2; }
| statement3 = raise_stmt{ statement = statement3; }
| statement4 = yield_stmt{ statement = statement4; }
;
// Break statement
break_stmt returns [ Statement statement = null ]:
ta = 'break'
{
statement = new BreakStatement( toDLTK( ta ), null, toDLTK(ta) );
}
;
// Continue statement
continue_stmt returns [ Statement statement = null ]:
ta = 'continue'
{
statement = new ContinueStatement( toDLTK( ta ), null, toDLTK(ta) );
}
;
// Return statement
return_stmt returns [ Statement statement = null ]:
ra = 'return'
( tu = testlist )?
{
DLTKToken ret = toDLTK(ra);
int end = ret.getColumn()+ret.getText().length();
if( tu != null ) {
end = tu.sourceEnd();
}
statement = new ReturnStatement( toDLTK( ra ), tu , end );
}
;
// Yield statement
yield_stmt returns [ PythonYieldStatement statement = null ]:
tu = 'yield'
r = testlist
{
statement = new PythonYieldStatement( toDLTK( tu ), r );
}
;
// Exception raise statement
raise_stmt returns [ PythonRaiseStatement statement = null ]:
tu = 'raise'
{
statement = new PythonRaiseStatement( toDLTK( tu ) );
int end = -1;
}
(
e1 = test
{
statement.acceptExpression1( e1 );
if( e1 != null && e1.sourceEnd() > end ) {
end = e1.sourceEnd();
}
}
( COMMA
e2 = test
{
statement.acceptExpression2( e2 );
if( e2 != null && e2.sourceEnd() > end ) {
end = e2.sourceEnd();
}
}
( COMMA
e3 = test
{
statement.acceptExpression3( e3 );
if( e3 != null && e3.sourceEnd() > end ) {
end = e3.sourceEnd();
}
}
)?
)?
)?
;
import_stmt returns [ Statement statement = null ] :
{
Expression impExpr;
String impName;
String impName2;
//Token moduleName;
PythonTestListExpression importNames = new PythonTestListExpression();
}
(
(
tu ='import'
{
statement = new PythonImportStatement( toDLTK( tu ), importNames );
//Expression expr0 = null;
}
expr0 = module_imp
{
importNames.setStart(expr0.sourceStart());
importNames.setEnd(expr0.sourceEnd());
importNames.addExpression( expr0 );
if( expr0.sourceEnd() > statement.sourceEnd() ) {
statement.setEnd( expr0.sourceEnd() );
}
}
( COMMA
expr0 = module_imp
{
importNames.addExpression( expr0 );
importNames.setEnd( expr0.sourceEnd());
if( expr0.sourceEnd() > statement.sourceEnd() ) {
statement.setEnd( expr0.sourceEnd() );
}
}
)*
)
|
r = 'from'
moduleName = dot_name
'import'
(
(
{
//moduleName.setColumn(moduleName.getColumn()-1);
statement = new PythonImportFromStatement( toDLTK( r ), new VariableReference( toDLTK( moduleName ) ), importNames );
//Expression expr0 = null;
}
expr0 = module_imp
{
importNames.setStart(expr0.sourceStart());
importNames.setEnd(expr0.sourceEnd());
importNames.addExpression( expr0 );
if( expr0.sourceEnd() > statement.sourceEnd() ) {
statement.setEnd( expr0.sourceEnd() );
}
}
( COMMA
expr0 = module_imp
{
importNames.addExpression( expr0 );
importNames.setEnd( expr0.sourceEnd());
if( expr0.sourceEnd() > statement.sourceEnd() ) {
statement.setEnd( expr0.sourceEnd() );
}
}
)*
)
|
(
STAR
{
//moduleName.setColumn(moduleName.getColumn()-1);
statement = new PythonImportFromStatement( toDLTK( r ), new VariableReference( toDLTK( moduleName ) ), new PythonAllImportExpression( ) );
}
)
)
)
;
dotted_name returns [ Token token = null ]:
{
String value = "";
}
n =NAME
{
value += n.getText();
}
(
DOT
n2 =NAME
{
value += "." + n2.getText();
}
)+
{
token = new CommonToken( n );
token.setText( value );
//token.setColumn( n.getColumn() );
}
;
dot_name returns [ Token token = null ]:
(
moduleName1 = dotted_name
{
token = moduleName1;
}
)
|
(
moduleName2 =NAME
{
token = moduleName2;
}
)
{
if( token != null ) {
//int column = token.getColumn();
//token.setColumn( column -1 );
}
}
;
module_imp returns [ Expression expr = null ]:
impName = dot_name
{
expr = new PythonImportExpression( toDLTK( impName ) );
}
(
'as'// this is should be as.
as =NAME
{
expr = new PythonImportAsExpression( toDLTK( impName ), toDLTK( as ) );
}
)?
;
// TODO: Not Implemented at all yet.
global_stmt returns [ Statement statement = null ]:
'global' NAME (COMMA NAME)*
;
// TODO: Not Implemented at all yet.
exec_stmt returns [ Statement statement = null]:
e = 'exec' ex = expr { statement = new ExecStatement(this.converter.convert(e), ex); }
('in'
ex = test { ((ExecStatement)statement).acceptIn(ex); }
(COMMA ex = test { ((ExecStatement)statement).acceptIn2(ex); }
)?)?
;
// Assert statement
assert_stmt returns [ PythonAssertStatement statement = null ]:
tu ='assert'
exp1 = test
( COMMA exp2 = test )?
{
statement = new PythonAssertStatement( toDLTK( tu ), exp1, exp2 );
}
;
// Compound statement
compound_stmt returns [ Statement statement = null ]:
statement0 = if_stmt { statement = statement0; }
| statement1 = while_stmt{ statement = statement1; }
| statement2 = for_stmt{ statement = statement2; }
| statement3 = try_stmt{ statement = statement3; }
| statement4 = funcdef{ statement = statement4; }
| statement5 = classdef{ statement = statement5; }
| statement6 = with_stmt {statement = statement6; }
;
// If Statement
if_stmt returns [ IfStatement statement = null ]:
is ='if'
mn = test
COLON
body = suite
{
IfStatement t,base;
List ifs = new ArrayList();
statement = new IfStatement( toDLTK( is ), mn, body );
statement.setEnd(body.sourceEnd());
ifs.add(statement);
base = statement;
t = statement;
}
(
z ='elif'
mn = test
COLON
body=suite
{
IfStatement elseIfStatement = new IfStatement( toDLTK( z ), mn, body );
t.acceptElse( elseIfStatement );
t = elseIfStatement;
ifs.add(t);
for(Iterator i = ifs.iterator(); i.hasNext(); ((IfStatement)i.next()).setEnd(body.sourceEnd()));
base.setEnd(elseIfStatement.sourceEnd());
}
)*
(
'else'
COLON
body = suite
{
t.setElse( body );
for(Iterator i = ifs.iterator(); i.hasNext(); ((IfStatement)i.next()).setEnd(body.sourceEnd()));
}
)?
;
// While statement
while_stmt returns [ PythonWhileStatement whileStatement = null ]:
is ='while'
expression = test
COLON
body = suite
{
whileStatement = new PythonWhileStatement( toDLTK( is ), expression, body );
}
(
'else' COLON
body = suite
{
whileStatement.setElseStatement( body );
}
)?
;
// For statement
for_stmt returns [ PythonForStatement statement = null]:
is ='for'
mains = exprlist
'in'
conds = testlist
COLON
body = suite
{
statement = new PythonForStatement( toDLTK( is ), mains, conds, body );
}
(
'else'
COLON
body = suite
{
statement.acceptElse( body );
}
)?
;
// Try Statement
// not fully implemented yet
try_stmt returns [ PythonTryStatement statement = null ]:
is ='try'
COLON
{
Token lastTok = is;
List catches = new ArrayList();
}
body = suite
(
(
(
ex_='except'
(
t1 = test
(COMMA t2 = test)?
)?
COLON
su = suite
{
lastTok = ex_;
catches.add( new PythonExceptStatement( toDLTK( ex_ ), t1, t2, su ) );
}
)+
(
( elseT = 'else'
COLON
elseBlock = suite
{
lastTok = elseT;
}
)
)?
)
|
(
fin ='finally'
{
lastTok = fin;
}
COLON
su = suite
{
catches.add( new TryFinallyStatement( toDLTK( fin ), su ) );
}
)
)
{
statement = new PythonTryStatement( toDLTK( is ), body, catches );
statement.setElseStatement( elseBlock );
}
;
// Suite rule
suite returns [ Block statement = new Block() ]:
{
ArrayList l = new ArrayList();
int startPos = -1;
int endPos = -1;
}
(
simple_stmt[ l ]
{
Iterator i = l.iterator();
while( i.hasNext()) {
Statement sst = (Statement)i.next();
if( sst != null ) {
if( sst.sourceStart() < startPos || startPos == -1 ) {
startPos = sst.sourceStart();
}
if( sst.sourceEnd() > endPos || endPos == -1 ) {
endPos = sst.sourceEnd();
}
statement.addStatement( sst );
}
}
}
|
NEWLINE
ind = INDENT
{
if( ind != null ) {
int s = converter.convert( ind ).getColumn();
if( s < startPos && s != -1 ) {
startPos = s;
}
}
//ArrayList k;
}
(
k = stmt
{
//l.addAll( k );
if( k != null ) {
Iterator i = k.iterator();
while( i.hasNext() ) {
Statement sst = (Statement)i.next();
if( sst != null ) {
statement.addStatement( sst );
if( sst.sourceStart() < startPos || startPos == -1 ) {
startPos = sst.sourceStart();
}
if( sst.sourceEnd() > endPos || endPos == -1 ) {
endPos = sst.sourceEnd();
}
}
}
}
}
)+
d =DEDENT
{
if( d != null ) {
int e = converter.convert( d ).getColumn() - 1;
if( e > endPos ) {
endPos = e;
}
}
}
)
{
//endPos -= 1;
//statement = new Block( startPos, endPos, l );
statement.setStart( startPos );
//if( endPos == -1 ) {
// endPos = length;
//}
statement.setEnd( endPos );
}
;
///////////////////////////////////////////////
/// Expressions
//////////////////////////////////////////
or_test returns [ Expression exp = null ] :
exp0 = and_test
{
exp = exp0;
}
(
r = 'or'
v = and_test
{
exp = new BinaryExpression( exp0, Expression.E_LOR, v);
}
)*
;
//To be replaced with 'expression' (?) in some rules (as 2.5 grammar)
test returns [ Expression exp = null ]:
exp0 = or_test {exp = exp0;}
|
exp0 = lambdef {exp = exp0;}
;
and_test returns [ Expression exp = null ]:
exp0 = not_test
{
exp = exp0;
}
(
m ='and'
v = not_test
{
exp = new BinaryExpression( exp0, Expression.E_LAND,v);
}
)*
;
not_test returns [ Expression exp = null ]:
(
n ='not'
v = not_test
{
exp = new UnaryExpression( toDLTK( n ), Expression.E_LNOT, v );
}
)
| exp0 = comparison { exp = exp0;}
;
comparison returns [ Expression exp = null ]:
exp0 = expr
{
exp = exp0;
}
(
tu = comp_op
v = expr
{
exp = new BinaryExpression( exp0, tu, v );
}
)*
;
comp_op returns [ int t = Expression.E_EMPTY ] :
t1 =LESS {t = Expression.E_LT;}
|t2 =GREATER {t = Expression.E_GT;}
|t3 =EQUAL {t = Expression.E_EQUAL;}
|t4 =GREATEREQUAL {t = Expression.E_GE;}
|t5 =LESSEQUAL {t = Expression.E_LE;}
|t6 =ALT_NOTEQUAL {t = Expression.E_NOT_EQUAL2;}
|t7 =NOTEQUAL {t = Expression.E_NOT_EQUAL;}
|t8 ='in' {t = Expression.E_IN;}
|t9 ='not' 'in' {t = Expression.E_NOTIN;}///XXX://
|t10 ='is' {t = Expression.E_IS;}
|t11 ='is' 'not' {t = Expression.E_ISNOT;}//XXX://
;
expr returns [ Expression e = null]:
e0 = xor_expr
{
e = e0;
}
(
tu = VBAR
v = xor_expr
{
e = new BinaryExpression( e0, Expression.E_LOR,v);
}
)*
;
xor_expr returns [ Expression e = null ]:
e0 = and_expr
{
e = e0;
}
(
tu =CIRCUMFLEX
v = and_expr
{
e = new BinaryExpression( e0, Expression.E_XOR,v);
}
)*
;
and_expr returns [ Expression e = null ]:
e0 = shift_expr
{
e = e0;
}
(
tu = AMPER
v = shift_expr
{
e = new BinaryExpression( e0, Expression.E_LAND, v );
}
)*
;
shift_expr returns [ Expression e = null ]:
e0 = arith_expr
{
e = e0;
}
{
Token tk = null;
}
(
(
t1 = LEFTSHIFT
{
tk = t1;
}
|
t2 = RIGHTSHIFT
{
tk = t2;
}
)
v = arith_expr
{
if( tk == t1 )
e = new BinaryExpression( e0, Expression.E_LSHIFT, v );
else
e = new BinaryExpression( e0, Expression.E_RSHIFT, v);
}
)*
;
arith_expr returns [ Expression e = null ]:
e0 = term
{
e = e0;
}
{
Token tk = null;
}
(
(
t1 = PLUS
{
tk = t1;
}
|
t2 = MINUS
{
tk = t2;
}
)
v = term
{
if( tk == t1 )
e = new BinaryExpression( e0, Expression.E_PLUS, v );
else
e = new BinaryExpression( e0, Expression.E_MINUS, v );
}
)*
;
term returns [ Expression e = null]:
e0 = factor
{
e = e0;
}
{
int type = Expression.E_EMPTY;
}
(
(
t1 =STAR
{
type = Expression.E_MULT;
}
|
t2 =SLASH
{
type = Expression.E_DIV;
}
|
t3 =PERCENT
{
type = Expression.E_MOD;
}
|
t4 =DOUBLESLASH
{
type = Expression.E_MOD;
}
)
v = factor
{
e = new BinaryExpression( e0,type,v );
}
)*
;
factor returns [ Expression e = new EmptyExpression() ]:
{
Token tk = null;
}
(
t1 = PLUS
{
tk = t1;
}
|
t2 = MINUS
{
tk = t2;
}
|
t3 =TILDE
{
tk = t3;
}
)
e0 = factor
{
if( tk == t1 ) {
e = new UnaryExpression( toDLTK( tk ), Expression.E_PLUS, e0);
}
else if( tk == t2 ) {
e = new UnaryExpression( toDLTK( tk ), Expression.E_MINUS, e0);
}
else if( tk == t3 ) {
e = new UnaryExpression( toDLTK( tk ), Expression.E_MINUS, e0);
}
else {
e = new UnaryExpression( toDLTK( tk ), Expression.E_FACTOR, e0);
}
}
|
e0 = power {
e = e0;
}
;
power returns [ Expression exp = null; ]:
(
exp0 = atom
{
//Expression ex = exp;
exp = exp0;
}
(
ex = trailer[ exp ]
{
exp = ex;
}
)*
(
options {greedy=true;}:DOUBLESTAR
expr0 = factor
{
//TODO: add factor expression.
// PythonTestListExpression testListExpr = new PythonTestListExpression();
// testListExpr.addExpression( exp );
// testListExpr.addExpression( expr );
// exp = testListExpr;
exp = new BinaryExpression( exp, Expression.E_POWER, expr0 );
}
)?
)
;
// expr this is initial expression.
trailer[ Expression expr ] returns [ Expression returnExpression = null ]:
{
//Expression k=null;
// Create extended variable reference.
if( !( expr instanceof ExtendedVariableReference ) )
expr = new ExtendedVariableReference( expr );
ExtendedVariableReference exVariableReference = ( ExtendedVariableReference )expr;
}
(
lp0 = LPAREN
( k = arglist )?
rp0 = RPAREN
{
// This is Call lets' create it
if( k == null )
k = new EmptyExpression();
exVariableReference.addExpression( new CallHolder( toDLTK(lp0), toDLTK(rp0), k ) );
returnExpression = exVariableReference;
}
|
lb1 = LBRACK
k = subscriptlist
rb1 = RBRACK
{
// This is subscript lets return it.
//a = new PythonSubscriptAppender(k);
//returnExpression = ExpressionConverter.getIndexed( expr, k );
exVariableReference.addExpression( new IndexHolder( toDLTK(lb1), toDLTK(rb1), k ) );
returnExpression = exVariableReference;
}
|
DOT
ta =NAME
{
//a=new PythonFieldAppenter(ta);
//returnExpression = ExpressionConverter.getDotted( expr, new VariableReference( toDLTK( ta ) ) );
//ta.setColumn(ta.getColumn()-1);
exVariableReference.addExpression( new VariableReference( toDLTK( ta ) ) );
returnExpression = exVariableReference;
}
)
;
atom returns [ Expression exp = null ]:
lb = LPAREN ( exp0 = tuplelist { exp = exp0;} ) rb = RPAREN { setStartEndForEmbracedExpr(exp,lb,rb); }
| lb = LPAREN { exp = new PythonTupleExpression(); } rb = RPAREN { setStartEndForEmbracedExpr(exp,lb,rb); } // for initializations like a = ()
| lb = LBRACK ( exp0 = listmaker {exp = exp0; } ) rb = RBRACK { setStartEndForEmbracedExpr(exp,lb,rb); }
| lb =LBRACK { exp = new PythonListExpression( ); } rb = RBRACK { setStartEndForEmbracedExpr(exp,lb,rb); } // for initializations like a = []
| a1=LCURLY {lb =a1;} ( exp0 = dictmaker { exp = exp0; } ) rb = RCURLY { setStartEndForEmbracedExpr(exp,lb,rb); }
| lb =LCURLY { exp = new PythonDictExpression(); } rb = RCURLY { setStartEndForEmbracedExpr(exp,lb,rb); } // for initialization like a = {}
| lb = BACKQUOTE exp0 = testlist { exp = exp0; } rb = BACKQUOTE { setStartEndForEmbracedExpr(exp,lb,rb); }
| n =NAME { exp = new VariableReference( toDLTK( n ) ); }
| i = INT { exp = new NumericLiteral( toDLTK( i ) );}
| li = LONGINT { exp=new NumericLiteral( toDLTK( li ) );}
| f = FLOAT { exp=new NumericLiteral( toDLTK( f ) );}
| c = COMPLEX { exp=new ComplexNumericLiteral( toDLTK( c ) ); }
|
(
s = STRING
{
if( exp != null && exp instanceof StringLiteral )
exp = new StringLiteral( exp.sourceStart(), toDLTK(s), ((StringLiteral)exp).getValue() + s.getText() );
else
exp = new StringLiteral( toDLTK( s ) );
}
)+
;
listmaker returns [ PythonListExpression exp = new PythonListExpression() ]:
firstExpr = test
(
(
{
PythonListForExpression listExpr = new PythonListForExpression( firstExpr );
}
list_for[ listExpr ]
{
exp.addExpression( listExpr );
}
)
|
(
{
exp.addExpression( firstExpr );
}
(
options {greedy=true;}:
COMMA
expr0 = test
{
exp.addExpression( expr0 );
}
)*
(COMMA)?
)
)
;
// Available only in python >=2.3.x
list_for [PythonListForExpression list ]:
(
forToken = 'for'
expr1 = exprlist
'in'
expr2 = testlist
{
PythonForListExpression forListExpression = new PythonForListExpression( expr1, expr2 );
forListExpression.setStart(toDLTK(forToken).getColumn());
list.addExpression( forListExpression );
}
{
PythonListExpression ifList = null;
}
(
expr0 = list_if
{
if( ifList == null )
ifList = new PythonListExpression();
ifList.addExpression( expr0 );
ifList.setStart(expr0.sourceStart());
ifList.setEnd(expr0.sourceEnd());
}
)*
{
if( ifList != null )
forListExpression.setIfListExpression( ifList );
}
)+
;
list_if returns[ Expression expr = null ]:
'if'
expr0 = test {
expr = expr0;
}
;
lambdef returns [ Expression e = null ]:
lambda = 'lambda'
{
//ArrayList buf = this.fParameters;
//this.fParameters = new ArrayList();
List params = new ArrayList ();
//Expression statement;
}
( varargslist[ params ] )?
COLON
statement = test
{
if( statement == null ) {
statement = new EmptyExpression( );
}
e = new PythonLambdaExpression( toDLTK( lambda ), params, statement );
}
;
subscriptlist returns [ Expression expression = null ] :
expression0 = subscript
(
options {greedy=true;}:COMMA
k = subscript
{
expression = new BinaryExpression( expression0, Expression.E_COMMA, k );
}
)*
(COMMA)?
;
subscript returns [ PythonSubscriptExpression expression = null ]:
w = DOT DOT DOT
{
expression = new PythonSubscriptExpression( toDLTK( w ) );
}
|
(
{
expression = new PythonSubscriptExpression( );
}
tu = test
{
expression.setTest( tu );
}
(
COLON
(
tu1 = test
{
expression.setCondition( tu1 );
}
)?
(
tu = sliceop
{
expression.setSlice( tu );
}
)?
)?
)
|
(
{
expression = new PythonSubscriptExpression( );
}
COLON
(
tu1 = test
{
expression.setCondition( tu1 );
}
)?
(
tu = sliceop
{
expression.setSlice( tu );
}
)?
)
;
sliceop returns [ Expression e = null ]:
COLON
( e0 = test { e = e0; } )?
;
exprlist returns [ PythonTestListExpression p = new PythonTestListExpression( ); ] :
e = expr
{
p.addExpression( e );
p.setStart(e.sourceStart());
p.setEnd(e.sourceEnd());
}
(options {k=2;greedy=true;}:
COMMA
e = expr
{
p.addExpression( e );
if( e.sourceEnd() > p.sourceEnd() ) {
p.setEnd( e.sourceEnd() );
}
}
)*
(COMMA)?
;
// to be replaced by 'target' in some rules(as in 2.5 grammar)
testlist returns [ Expression p = new EmptyExpression() ]:
{
PythonTestListExpression listExpression = new PythonTestListExpression();
int end = -1;
}
e0 = test
{
p = e0;
listExpression.addExpression( e0 );
if( p != null) {
listExpression.setStart(p.sourceStart());
end = p.sourceEnd();
listExpression.setEnd(end);
}
}
(options {k=2;greedy=true;}:
COMMA
e0 = test
{
if( e0 != null && e0.sourceEnd() > end ) {
end = e0.sourceEnd();
}
listExpression.addExpression( e0 );
p = listExpression;
}
)*
(options {greedy=true;}:COMMA)?
{
if( end != -1 && p != null ) {
p.setEnd(end);
}
}
;
tuplelist returns [ Expression p = null ]:
e0 = test
{
p = e0;
if( p == null ) {
p = new EmptyExpression();
}
//p.addExpression( e );
}
(options {greedy=true;}:
COMMA
e0 = test
{
if( !( p instanceof PythonTupleExpression ) ) {
PythonTupleExpression tuple = new PythonTupleExpression();
tuple.addExpression( p );
p = tuple;
}
PythonTupleExpression tup = (PythonTupleExpression)p;
tup.addExpression( e0 );
}
)*
(options {greedy=true;}:COMMA)?
;
with_stmt returns [Statement st = null]:
w_token = 'with'
exp_what = test
(
'as' exp_as = testlist
)? COLON block = suite
{
DLTKToken token = toDLTK(w_token);
st = new PythonWithStatement(token, exp_what, exp_as, block, token.getColumn(), block.sourceEnd());
}
;
//TODO: NEED to implement
dictmaker returns [ PythonDictExpression d = new PythonDictExpression() ] :
t1 = test
COLON
t2 = test
{
d.putExpression( t1, t2 );
}
(
options {k=2;greedy=true;}:COMMA
t3 = test
COLON
t4 = test
{
d.putExpression( t3, t4 );
}
)*
(COMMA)?
;
classdef returns [ PythonClassDeclaration classDeclaration = null ]:
c = 'class'
tu = NAME
{
classDeclaration = new PythonClassDeclaration( toDLTK( tu ), toDLTK(c) );
}
(
r =LPAREN
(te = testlist)?
m = RPAREN
{
if (null != te)
{
if( te instanceof ExpressionList ) {
classDeclaration.setParents( toDLTK( r ), (ExpressionList)te, toDLTK( m ) );
}
else {
ExpressionList exprList = new ExpressionList();
exprList.setStart(te.sourceStart());
exprList.setEnd(te.sourceEnd());
exprList.addExpression( te );
classDeclaration.setParents( toDLTK( r ), exprList, toDLTK( m ) );
}
}
}
)?
co = COLON
sa = suite
{
classDeclaration.setBody( toDLTK(co), sa, sa.sourceEnd() );
}
;
arglist returns [ ExpressionList expressions = new ExpressionList() ]:
(
k = argument
{
expressions.addExpression( k );
}
(
options {greedy=true;}:COMMA
k = argument
{
expressions.addExpression( k );
}
)*
(
COMMA
(
STAR
k = test
{
expressions.addExpression( k );
}
(
COMMA
DOUBLESTAR
k = test
{
expressions.addExpression( k );
}
)?
|
DOUBLESTAR
k = test
{
expressions.addExpression( k );
}
)?
)?
|
STAR
k = test
{
expressions.addExpression( k );
}
(
COMMA
DOUBLESTAR
k = test
{
expressions.addExpression( k );
}
)?
|
DOUBLESTAR
k = test
{
expressions.addExpression( k );
}
)
;
argument returns [ Expression e = null ]:
e0 = test
{
e = e0;
}
(
ASSIGN
k = test
{
e = new Assignment( e, k );
}
)?
;
/////////////////////////////////////////////////////////////////////
//Lexer rules
//lexer grammar python_v3;ASSIGN
//@lexer::options
//{
// k = 3;
// testLiterals = true;
// charVocabulary='\u0003'..'\ufffe';
// language = Java;
//}
LPAREN : '(' {implicitLineJoiningLevel++;} ;
RPAREN : ')' {implicitLineJoiningLevel--;} ;
LBRACK : '[' {implicitLineJoiningLevel++;} ;
RBRACK : ']' {implicitLineJoiningLevel--;} ;
COLON : ':' ;
COMMA : ',' ;
SEMI : ';' ;
PLUS : '+' ;
MINUS : '-' ;
STAR : '*' ;
SLASH : '/' ;
VBAR : '|' ;
AMPER : '&' ;
LESS : '<' ;
GREATER : '>' ;
ASSIGN : '=' ;
PERCENT : '%' ;
BACKQUOTE : '`' ;
LCURLY : '{' {implicitLineJoiningLevel++;} ;
RCURLY : '}' {implicitLineJoiningLevel--;} ;
CIRCUMFLEX : '^' ;
TILDE : '~' ;
EQUAL : '==' ;
NOTEQUAL : '!=' ;
ALT_NOTEQUAL: '<>' ;
LESSEQUAL : '<=' ;
LEFTSHIFT : '<<' ;
GREATEREQUAL : '>=' ;
RIGHTSHIFT : '>>' ;
PLUSEQUAL : '+=' ;
MINUSEQUAL : '-=' ;
DOUBLESTAR : '**' ;
STAREQUAL : '*=' ;
DOUBLESLASH : '//' ;
SLASHEQUAL : '/=' ;
VBAREQUAL : '|=' ;
PERCENTEQUAL : '%=' ;
AMPEREQUAL : '&=' ;
CIRCUMFLEXEQUAL : '^=' ;
LEFTSHIFTEQUAL : '<<=' ;
RIGHTSHIFTEQUAL : '>>=' ;
DOUBLESTAREQUAL : '**=' ;
DOUBLESLASHEQUAL : '//=' ;
DOT : '.' ;
FLOAT : POINTFLOAT | EXPONENTFLOAT
// : '.' DIGITS (Exponent)?
// | DIGITS ('.' (DIGITS (Exponent)?)? | Exponent)
;
POINTFLOAT
: DIGITS? FRACTION | DIGITS '.'
;
FRACTION
: '.' DIGITS
;
EXPONENTFLOAT
: (DIGITS | POINTFLOAT) Exponent
;
LONGINT
: INT ('l'|'L')
;
fragment
Exponent
: ('e' | 'E') ( '+' | '-' )? DIGITS
;
INT : // Hex
'0' ('x' | 'X') ( '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' )+
('l' | 'L')?
| // Octal
'0' DIGITS*
| '1'..'9' DIGITS*
;
COMPLEX
: INT ('j'|'J')
| FLOAT ('j'|'J')
;
fragment
DIGITS : ( '0' .. '9' )+ ;
NAME: ( 'a' .. 'z' | 'A' .. 'Z' | '_')
( 'a' .. 'z' | 'A' .. 'Z' | '_' | '0' .. '9' )*
;
/** Match various string types. Note that greedy=false implies '''
* should make us exit loop not continue.
*/
STRING
: ('r'|'u'|'ur')?
( '\'\'\'' (options {greedy=false;}:.)* '\'\'\''
| '"""' (options {greedy=false;}:.)* '"""'
| '"' (ESC|~('\\'|'\n'|'"'))* '"'
| '\'' (ESC|~('\\'|'\n'|'\''))* '\''
)
;
fragment
ESC
: '\\' .
;
/** Consume a newline and any whitespace at start of next line */
CONTINUED_LINE
: '\\' ('\r')? '\n' (' '|'\t')* {
//fModule.acceptLine(getColumn());
/*newline();*/ $channel=HIDDEN; }
;
WS : {startPos>0}?=> (' '|'\t')+ {$channel=HIDDEN;}
;
/** Grab everything before a real symbol. Then if newline, kill it
* as this is a blank line. If whitespace followed by comment, kill it
* as it's a comment on a line by itself.
*
* Ignore leading whitespace when nested in [..], (..), {..}.
*/
LEADING_WS
@init {
int spaces = 0;
}
: {startPos==0}?=>
( {implicitLineJoiningLevel>0}? ( ' ' | '\t' )+ {$channel=HIDDEN;}
| ( ' ' { spaces++; }
| '\t' { spaces += 8; spaces -= (spaces \% 8); }
)+
{
// make a string of n spaces where n is column number - 1
char[] indentation = new char[spaces];
for (int i=0; i<spaces; i++) {
indentation[i] = ' ';
}
String s = new String(indentation);
Token tok = new ClassicToken(LEADING_WS,new String(indentation));
emit(tok);
}
// kill trailing newline if present and then ignore
( ('\r')? '\n' {if (token!=null) token.setChannel(99); else $channel=HIDDEN;})*
// {token.setChannel(99); }
)
/*
| // if comment, then only thing on a line; kill so we
// ignore totally also wack any following newlines as
// they cannot be terminating a statement
'#' (~'\n')* ('\n')+
{if (token!=null) token.setChannel(99); else $channel=HIDDEN;}
)?
*/
;
/** Comments not on line by themselves are turned into newlines because
sometimes they are newlines like
b = a # end of line comment
or
a = [1, # weird
2]
This rule is invoked directly by nextToken when the comment is in
first column or when comment is on end of nonwhitespace line.
The problem is that then we have lots of newlines heading to
the parser. To fix that, column==1 implies we should kill whole line.
Consume any newlines following this comment as they are not statement
terminators. Don't let NEWLINE token handle them.
*/
COMMENT
@init {
$channel=HIDDEN;
}
: {startPos==0}?=> (' '|'\t')* '#' (~'\n')* '\n'+
| {startPos>0}?=> '#' (~'\n')* // let NEWLINE handle \n unless char pos==0 for '#'
;
//SPECIAL
//{
// int startCol = getColumn();
//}
// : (~'\n')* // let NEWLINE handle \n unless column = 1 for '#'
// { $setType(Token.SKIP);
// fModule.acceptModifier($getText);
// }
// ( {startCol==1}? ('\n' {
// fModule.acceptLine(getColumn());newline();
//}
// )+ )?
// ;
DECORATOR_S:
'@'
;
/** Treat a sequence of blank lines as a single blank line. If
* nested within a (..), {..}, or [..], then ignore newlines.
* If the first newline starts in column one, they are to be ignored.
*/
NEWLINE
: (('\r')? '\n' )+
{if ( startPos==0 || implicitLineJoiningLevel>0 )
$channel=HIDDEN;
}
;