package org.python.pydev.parser.grammar24;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.python.pydev.core.FullRepIterable;
import org.python.pydev.core.log.Log;
import org.python.pydev.parser.grammarcommon.AbstractTreeBuilder;
import org.python.pydev.parser.grammarcommon.Decorators;
import org.python.pydev.parser.grammarcommon.DefaultArg;
import org.python.pydev.parser.grammarcommon.ExtraArg;
import org.python.pydev.parser.grammarcommon.ExtraArgValue;
import org.python.pydev.parser.grammarcommon.ITreeBuilder;
import org.python.pydev.parser.grammarcommon.ITreeConstants;
import org.python.pydev.parser.grammarcommon.JJTPythonGrammarState;
import org.python.pydev.parser.jython.ParseException;
import org.python.pydev.parser.jython.SimpleNode;
import org.python.pydev.parser.jython.ast.Assert;
import org.python.pydev.parser.jython.ast.Assign;
import org.python.pydev.parser.jython.ast.Call;
import org.python.pydev.parser.jython.ast.ClassDef;
import org.python.pydev.parser.jython.ast.Comprehension;
import org.python.pydev.parser.jython.ast.Ellipsis;
import org.python.pydev.parser.jython.ast.Expr;
import org.python.pydev.parser.jython.ast.FunctionDef;
import org.python.pydev.parser.jython.ast.Global;
import org.python.pydev.parser.jython.ast.ImportFrom;
import org.python.pydev.parser.jython.ast.Index;
import org.python.pydev.parser.jython.ast.Lambda;
import org.python.pydev.parser.jython.ast.List;
import org.python.pydev.parser.jython.ast.ListComp;
import org.python.pydev.parser.jython.ast.NameTok;
import org.python.pydev.parser.jython.ast.Print;
import org.python.pydev.parser.jython.ast.Raise;
import org.python.pydev.parser.jython.ast.Repr;
import org.python.pydev.parser.jython.ast.Return;
import org.python.pydev.parser.jython.ast.Slice;
import org.python.pydev.parser.jython.ast.Starred;
import org.python.pydev.parser.jython.ast.Subscript;
import org.python.pydev.parser.jython.ast.Suite;
import org.python.pydev.parser.jython.ast.TryExcept;
import org.python.pydev.parser.jython.ast.TryFinally;
import org.python.pydev.parser.jython.ast.While;
import org.python.pydev.parser.jython.ast.Yield;
import org.python.pydev.parser.jython.ast.aliasType;
import org.python.pydev.parser.jython.ast.argumentsType;
import org.python.pydev.parser.jython.ast.comprehensionType;
import org.python.pydev.parser.jython.ast.decoratorsType;
import org.python.pydev.parser.jython.ast.excepthandlerType;
import org.python.pydev.parser.jython.ast.exprType;
import org.python.pydev.parser.jython.ast.keywordType;
import org.python.pydev.parser.jython.ast.sliceType;
import org.python.pydev.parser.jython.ast.stmtType;
import org.python.pydev.parser.jython.ast.suiteType;
public final class TreeBuilder24 extends AbstractTreeBuilder implements ITreeBuilder, ITreeConstants {
public TreeBuilder24(JJTPythonGrammarState stack) {
super(stack);
}
@Override
public final SimpleNode onCloseNode(SimpleNode n, int arity) throws Exception {
exprType value;
exprType[] exprs;
Suite orelseSuite;
stmtType[] body;
exprType iter;
exprType target;
int l;
switch (n.getId()) {
case JJTEXPR_STMT:
value = (exprType) stack.popNode();
if (arity > 1) {
exprs = makeExprs(arity - 1);
ctx.setStore(exprs);
return new Assign(exprs, value, null);
} else {
return new Expr(value);
}
case JJTINDEX_OP:
sliceType slice = (sliceType) stack.popNode();
value = (exprType) stack.popNode();
return new Subscript(value, slice, Subscript.Load);
case JJTPRINT_STMT:
boolean nl = true;
if (stack.nodeArity() == 0) {
Print p = new Print(null, null, true);
return p;
}
if (stack.peekNode().getId() == JJTCOMMA) {
stack.popNode();
nl = false;
}
Print p = new Print(null, makeExprs(), nl);
return p;
case JJTPRINTEXT_STMT:
nl = true;
if (stack.peekNode().getId() == JJTCOMMA) {
stack.popNode();
nl = false;
}
exprs = makeExprs(stack.nodeArity() - 1);
p = new Print(((exprType) stack.popNode()), exprs, nl);
return p;
case JJTBEGIN_FOR_ELSE_STMT:
return new Suite(null);
case JJTBEGIN_ELSE_STMT:
return new Suite(null);
case JJTBEGIN_WHILE_STMT:
return new While(null, null, null);
case JJTWHILE_STMT:
orelseSuite = null;
if (stack.nodeArity() == 5) {
orelseSuite = popSuiteAndSuiteType();
}
body = popSuite();
exprType test = (exprType) stack.popNode();
While w = (While) stack.popNode();
w.test = test;
w.body = body;
w.orelse = orelseSuite;
return w;
case JJTCALL_OP:
exprType starargs = null;
exprType kwargs = null;
l = arity - 1;
if (l > 0 && stack.peekNode().getId() == JJTEXTRAKEYWORDVALUELIST) {
ExtraArgValue nkwargs = (ExtraArgValue) stack.popNode();
kwargs = nkwargs.value;
this.addSpecialsAndClearOriginal(nkwargs, kwargs);
l--;
}
if (l > 0 && stack.peekNode().getId() == JJTEXTRAARGVALUELIST) {
ExtraArgValue nstarargs = (ExtraArgValue) stack.popNode();
starargs = nstarargs.value;
this.addSpecialsAndClearOriginal(nstarargs, starargs);
l--;
}
int nargs = l;
SimpleNode[] tmparr = new SimpleNode[l];
for (int i = l - 1; i >= 0; i--) {
tmparr[i] = stack.popNode();
if (tmparr[i] instanceof keywordType) {
nargs = i;
}
}
exprType[] args = new exprType[nargs];
for (int i = 0; i < nargs; i++) {
//what can happen is something like print sum(x for x in y), where we have already passed x in the args, and then get 'for x in y'
if (tmparr[i] instanceof comprehensionType) {
args = new exprType[] { new ListComp(args[0],
new comprehensionType[] { (comprehensionType) tmparr[i] }, ListComp.EmptyCtx) };
} else {
args[i] = (exprType) tmparr[i];
}
}
keywordType[] keywords = new keywordType[l - nargs];
for (int i = nargs; i < l; i++) {
if (!(tmparr[i] instanceof keywordType)) {
throw new ParseException("non-keyword argument following keyword", tmparr[i]);
}
keywords[i - nargs] = (keywordType) tmparr[i];
}
exprType func = (exprType) stack.popNode();
Call c = new Call(func, args, keywords, starargs, kwargs);
addSpecialsAndClearOriginal(n, c);
return c;
case JJTFUNCDEF:
//get the decorators
//and clear them for the next call (they always must be before a function def)
Suite suite = (Suite) stack.popNode();
body = suite.body;
argumentsType arguments = makeArguments(stack.nodeArity() - 2);
NameTok nameTok = makeName(NameTok.FunctionName);
Decorators decs = (Decorators) stack.popNode();
decoratorsType[] decsexp = decs.exp;
FunctionDef funcDef = new FunctionDef(nameTok, arguments, body, decsexp, null, false);
if (decs.exp.length == 0) {
addSpecialsBefore(decs, funcDef);
}
addSpecialsAndClearOriginal(suite, funcDef);
setParentForFuncOrClass(body, funcDef);
return funcDef;
case JJTDEFAULTARG:
value = (arity == 1) ? null : ((exprType) stack.popNode());
return new DefaultArg(((exprType) stack.popNode()), value, n.getId());
case JJTEXTRAARGLIST:
return new ExtraArg(makeName(NameTok.VarArg), JJTEXTRAARGLIST);
case JJTEXTRAKEYWORDLIST:
return new ExtraArg(makeName(NameTok.KwArg), JJTEXTRAKEYWORDLIST);
/*
case JJTFPLIST:
fpdefType[] list = new fpdefType[arity];
for (int i = arity-1; i >= 0; i--) {
list[i] = popFpdef();
}
return new FpList(list);
*/
case JJTCLASSDEF:
suite = (Suite) stack.popNode();
body = suite.body;
exprType[] bases = makeExprs(stack.nodeArity() - 1);
nameTok = makeName(NameTok.ClassName);
ClassDef classDef = new ClassDef(nameTok, bases, body, null, null, null, null);
addSpecialsAndClearOriginal(suite, classDef);
setParentForFuncOrClass(body, classDef);
return classDef;
case JJTBEGIN_RETURN_STMT:
return new Return(null);
case JJTRETURN_STMT:
value = arity == 2 ? ((exprType) stack.popNode()) : null;
Return ret = (Return) stack.popNode();
ret.value = value;
return ret;
case JJTYIELD_STMT:
return new Yield(((exprType) stack.popNode()), false);
case JJTRAISE_STMT:
exprType tback = arity >= 3 ? ((exprType) stack.popNode()) : null;
exprType inst = arity >= 2 ? ((exprType) stack.popNode()) : null;
exprType type = arity >= 1 ? ((exprType) stack.popNode()) : null;
return new Raise(type, inst, tback, null);
case JJTGLOBAL_STMT:
Global global = new Global(makeIdentifiers(NameTok.GlobalName), null);
return global;
case JJTASSERT_STMT:
exprType msg = arity == 2 ? ((exprType) stack.popNode()) : null;
test = (exprType) stack.popNode();
return new Assert(test, msg);
case JJTBEGIN_TRY_STMT:
//we do that just to get the specials
return new TryExcept(null, null, null);
case JJTTRY_STMT:
orelseSuite = null;
if (stack.peekNode() instanceof Suite) {
arity--;
arity--;
orelseSuite = popSuiteAndSuiteType();
}
l = arity - 1;
excepthandlerType[] handlers = new excepthandlerType[l];
for (int i = l - 1; i >= 0; i--) {
handlers[i] = (excepthandlerType) stack.popNode();
}
suite = (Suite) stack.popNode();
TryExcept tryExc = (TryExcept) stack.popNode();
tryExc.body = suite.body;
tryExc.handlers = handlers;
tryExc.orelse = orelseSuite;
addSpecials(suite, tryExc);
return tryExc;
case JJTBEGIN_TRY_ELSE_STMT:
//we do that just to get the specials
return new Suite(null);
case JJTBEGIN_EXCEPT_CLAUSE:
return new excepthandlerType(null, null, null);
case JJTEXCEPT_CLAUSE:
suite = (Suite) stack.popNode();
body = suite.body;
exprType excname = arity == 4 ? ((exprType) stack.popNode()) : null;
if (excname != null) {
ctx.setStore(excname);
}
type = arity >= 3 ? ((exprType) stack.popNode()) : null;
excepthandlerType handler = (excepthandlerType) stack.popNode();
handler.type = type;
handler.name = excname;
handler.body = body;
addSpecials(suite, handler);
return handler;
case JJTBEGIN_FINALLY_STMT:
//we do that just to get the specials
return new Suite(null);
case JJTTRYFINALLY_STMT:
suiteType finalBody = popSuiteAndSuiteType();
body = popSuite();
//We have a try..except in the stack, but we will change it for a try..finally
//This is because we recognize a try..except in the 'try:' token, but actually end up with a try..finally
TryExcept tryExcept = (TryExcept) stack.popNode();
TryFinally tryFinally = new TryFinally(body, finalBody);
tryFinally.beginLine = tryExcept.beginLine;
tryFinally.beginColumn = tryExcept.beginColumn;
addSpecialsAndClearOriginal(tryExcept, tryFinally);
return tryFinally;
case JJTEXTRAKEYWORDVALUELIST:
return new ExtraArgValue(((exprType) stack.popNode()), JJTEXTRAKEYWORDVALUELIST);
case JJTEXTRAARGVALUELIST:
return new ExtraArgValue(((exprType) stack.popNode()), JJTEXTRAARGVALUELIST);
case JJTKEYWORD:
value = (exprType) stack.popNode();
nameTok = makeName(NameTok.KeywordName);
return new keywordType(nameTok, value, false);
case JJTTUPLE:
if (stack.nodeArity() > 0 && stack.peekNode() instanceof comprehensionType) {
comprehensionType[] generators = new comprehensionType[arity - 1];
for (int i = arity - 2; i >= 0; i--) {
SimpleNode compNode = stack.popNode();
if (!(compNode instanceof comprehensionType)) {
stack.getGrammar().addAndReport(
new ParseException("Expecting comprehensionType. Found: "
+ FullRepIterable.getLastPart(compNode.getClass().toString()), compNode),
"Comprehension not found (treated)");
} else {
generators[i] = (comprehensionType) compNode;
}
}
return new ListComp(((exprType) stack.popNode()), generators, ListComp.TupleCtx);
}
return makeTuple(n);
case JJTLIST:
if (stack.nodeArity() > 0 && stack.peekNode() instanceof comprehensionType) {
comprehensionType[] generators = new comprehensionType[arity - 1];
for (int i = arity - 2; i >= 0; i--) {
generators[i] = (comprehensionType) stack.popNode();
}
return new ListComp(((exprType) stack.popNode()), generators, ListComp.ListCtx);
}
return new List(makeExprs(), List.Load);
case JJTDICTIONARY:
return defaultCreateDictionary(arity);
case JJTSTR_1OP:
return new Repr(((exprType) stack.popNode()));
case JJTLAMBDEF:
test = (exprType) stack.popNode();
arguments = makeArguments(arity - 1);
Lambda lambda = new Lambda(arguments, test);
// if(arguments == null || arguments.args == null || arguments.args.length == 0){
// lambda.getSpecialsBefore().add("lambda");
// }else{
// lambda.getSpecialsBefore().add("lambda ");
// }
return lambda;
case JJTELLIPSIS:
return new Ellipsis();
case JJTSLICE:
SimpleNode[] arr = new SimpleNode[arity];
for (int i = arity - 1; i >= 0; i--) {
arr[i] = stack.popNode();
}
exprType[] values = new exprType[3];
int k = 0;
java.util.List<Object> specialsBefore = new ArrayList<Object>();
java.util.List<Object> specialsAfter = new ArrayList<Object>();
for (int j = 0; j < arity; j++) {
if (arr[j].getId() == JJTCOLON) {
if (arr[j].specialsBefore != null) {
specialsBefore.addAll(arr[j].specialsBefore);
arr[j].specialsBefore.clear(); //this nodes may be reused among parses, so, we have to erase the specials
}
if (arr[j].specialsAfter != null) {
specialsAfter.addAll(arr[j].specialsAfter);
arr[j].specialsAfter.clear();
}
k++;
} else {
values[k] = (exprType) arr[j];
if (specialsBefore.size() > 0) {
values[k].getSpecialsBefore().addAll(specialsBefore);
specialsBefore.clear();
}
if (specialsAfter.size() > 0) {
values[k].getSpecialsBefore().addAll(specialsAfter);
specialsAfter.clear();
}
}
}
SimpleNode sliceRet;
if (k == 0) {
sliceRet = new Index(values[0]);
} else {
sliceRet = new Slice(values[0], values[1], values[2]);
}
//this may happen if we have no values
sliceRet.getSpecialsBefore().addAll(specialsBefore);
sliceRet.getSpecialsAfter().addAll(specialsAfter);
specialsBefore.clear();
specialsAfter.clear();
return sliceRet;
case JJTLIST_FOR:
exprType[] ifs = new exprType[arity - 2];
for (int i = arity - 3; i >= 0; i--) {
ifs[i] = (exprType) stack.popNode();
}
iter = (exprType) stack.popNode();
target = (exprType) stack.popNode();
ctx.setStore(target);
return new Comprehension(target, iter, ifs);
case JJTIMPORTFROM:
aliasType[] aliases = makeAliases(arity - 1);
return new ImportFrom(makeName(NameTok.ImportModule), aliases, 0); //relative import is always level 0 here (only actually added on version 25)
case JJTSTAR_EXPR:
Starred starred = (Starred) n;
starred.value = (exprType) this.stack.popNode();
ctx.setStore(starred);
return starred;
default:
Log.log("Error at TreeBuilder: default not treated:" + n.getId());
return null;
}
}
NameTok[] getVargAndKwarg(java.util.List<SimpleNode> args) throws Exception {
NameTok varg = null;
NameTok kwarg = null;
for (Iterator<SimpleNode> iter = args.iterator(); iter.hasNext();) {
SimpleNode node = iter.next();
if (node.getId() == JJTEXTRAKEYWORDLIST) {
ExtraArg a = (ExtraArg) node;
kwarg = a.tok;
addSpecialsAndClearOriginal(a, kwarg);
} else if (node.getId() == JJTEXTRAARGLIST) {
ExtraArg a = (ExtraArg) node;
varg = a.tok;
addSpecialsAndClearOriginal(a, varg);
}
}
return new NameTok[] { varg, kwarg };
}
private argumentsType makeArguments(DefaultArg[] def, NameTok varg, NameTok kwarg) throws Exception {
exprType fpargs[] = new exprType[def.length];
exprType defaults[] = new exprType[def.length];
int startofdefaults = 0;
boolean defaultsSet = false;
for (int i = 0; i < def.length; i++) {
DefaultArg node = def[i];
exprType parameter = node.parameter;
fpargs[i] = parameter;
if (node.specialsBefore != null && node.specialsBefore.size() > 0) {
parameter.getSpecialsBefore().addAll(node.specialsBefore);
}
if (node.specialsAfter != null && node.specialsAfter.size() > 0) {
parameter.getSpecialsAfter().addAll(node.specialsAfter);
}
ctx.setParam(fpargs[i]);
defaults[i] = node.value;
if (node.value != null && defaultsSet == false) {
defaultsSet = true;
startofdefaults = i;
}
}
// System.out.println("start "+ startofdefaults + " " + l);
exprType[] newdefs = new exprType[def.length - startofdefaults];
System.arraycopy(defaults, startofdefaults, newdefs, 0, newdefs.length);
return new argumentsType(fpargs, varg, kwarg, newdefs, null, null, null, null, null, null);
}
private argumentsType makeArguments(int l) throws Exception {
NameTok kwarg = null;
NameTok stararg = null;
if (l > 0 && stack.peekNode().getId() == JJTEXTRAKEYWORDLIST) {
ExtraArg node = (ExtraArg) stack.popNode();
kwarg = node.tok;
l--;
addSpecialsAndClearOriginal(node, kwarg);
}
if (l > 0 && stack.peekNode().getId() == JJTEXTRAARGLIST) {
ExtraArg node = (ExtraArg) stack.popNode();
stararg = node.tok;
l--;
addSpecialsAndClearOriginal(node, stararg);
}
ArrayList<SimpleNode> list = new ArrayList<SimpleNode>();
for (int i = l - 1; i >= 0; i--) {
list.add(stack.popNode());
}
Collections.reverse(list);//we get them in reverse order in the stack
return makeArguments(list.toArray(new DefaultArg[0]), stararg, kwarg);
}
}