Package uk.co.badgersinfoil.metaas.impl

Source Code of uk.co.badgersinfoil.metaas.impl.ASTBuilder

/*
* ASTBuilder.java
*
* Copyright (c) 2006-2007 David Holroyd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package uk.co.badgersinfoil.metaas.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.asdt.core.internal.antlr.AS3Parser;
import uk.co.badgersinfoil.metaas.ActionScriptFactory;
import uk.co.badgersinfoil.metaas.SyntaxException;
import uk.co.badgersinfoil.metaas.dom.ASAssignmentExpression;
import uk.co.badgersinfoil.metaas.dom.ASBinaryExpression;
import uk.co.badgersinfoil.metaas.dom.ASCompilationUnit;
import uk.co.badgersinfoil.metaas.dom.Expression;
import uk.co.badgersinfoil.metaas.dom.Visibility;
import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListToken;
import uk.co.badgersinfoil.metaas.impl.antlr.LinkedListTree;
import uk.co.badgersinfoil.metaas.impl.antlr.PlaceholderLinkedListToken;


/**
* Utilities to build and assemble Abstract Syntax Tree fragments for inclusion
* into the compilation unit being generated.
*/
public class ASTBuilder {

  private ASTBuilder() {
    // hide default ctor
  }

  public static LinkedListTree newExprStmt(LinkedListTree expr) {
    LinkedListTree exprStmt = ASTUtils.newImaginaryAST(AS3Parser.EXPR_STMNT);
    exprStmt.addChildWithTokens(expr);
    exprStmt.appendToken(TokenBuilder.newSemi());
    return exprStmt;
  }

  public static AS3ASTCompilationUnit synthesizeClass(String qualifiedName) {
    LinkedListTree unit = ASTUtils.newImaginaryAST(AS3Parser.COMPILATION_UNIT);
    LinkedListTree pkg = ASTUtils.newAST(AS3Parser.PACKAGE, "package");
    pkg.appendToken(TokenBuilder.newSpace());
    unit.addChildWithTokens(pkg);
    pkg.appendToken(TokenBuilder.newSpace());
    String packageName = packageNameFrom(qualifiedName);
    if (packageName != null) {
      pkg.addChildWithTokens(AS3FragmentParser.parseIdent(packageName));
    }
    LinkedListTree packageBlock = newBlock();
    pkg.addChildWithTokens(packageBlock);
    String className = typeNameFrom(qualifiedName);
   
    LinkedListTree clazz = synthesizeAS3Class(className);
    ASTUtils.addChildWithIndentation(packageBlock, clazz);
    return new AS3ASTCompilationUnit(unit);
  }

  public static ASCompilationUnit synthesizeInterface(String qualifiedName) {
    LinkedListTree unit = ASTUtils.newImaginaryAST(AS3Parser.COMPILATION_UNIT);
    LinkedListTree pkg = ASTUtils.newAST(AS3Parser.PACKAGE, "package");
    unit.addChildWithTokens(pkg);
    pkg.appendToken(TokenBuilder.newSpace());
    String packageName = packageNameFrom(qualifiedName);
    if (packageName != null) {
      pkg.addChildWithTokens(AS3FragmentParser.parseIdent(packageName));
    }
    LinkedListTree packageBlock = newBlock();
    pkg.addChildWithTokens(packageBlock);
   
    LinkedListTree iface = synthesizeAS3Interface(qualifiedName);
    ASTUtils.addChildWithIndentation(packageBlock, iface);
    return new AS3ASTCompilationUnit(unit);
  }

  private static LinkedListTree synthesizeAS3Interface(String qualifiedName) {
    LinkedListTree iface = ASTUtils.newImaginaryAST(AS3Parser.INTERFACE_DEF);
    LinkedListTree modifiers = ASTUtils.newImaginaryAST(AS3Parser.MODIFIERS);
    iface.addChildWithTokens(modifiers);
    modifiers.addChildWithTokens(ASTUtils.newAST(AS3Parser.PUBLIC, "public"));
    modifiers.appendToken(TokenBuilder.newSpace());
    iface.appendToken(TokenBuilder.newInterface());
    iface.appendToken(TokenBuilder.newSpace());
    iface.addChildWithTokens(ASTUtils.newAST(AS3Parser.IDENT, typeNameFrom(qualifiedName)));
    iface.appendToken(TokenBuilder.newSpace());
    iface.addChildWithTokens(newTypeBlock());
    LinkedListTree annos = ASTUtils.newPlaceholderAST(AS3Parser.ANNOTATIONS);
    iface.addChildWithTokens(0, annos);
    return iface;
  }

  private static String typeNameFrom(String qualifiedName) {
    int p = qualifiedName.lastIndexOf('.');
    if (p == -1) {
      return qualifiedName;
    }
    return qualifiedName.substring(p+1);
  }

  private static LinkedListTree synthesizeAS3Class(String className) {
    LinkedListTree clazz = ASTUtils.newImaginaryAST(AS3Parser.CLASS_DEF);
    LinkedListTree modifiers = ASTUtils.newImaginaryAST(AS3Parser.MODIFIERS);
    clazz.addChildWithTokens(modifiers);
    LinkedListTree modPublic = ASTUtils.newAST(AS3Parser.PUBLIC, "public");
    modifiers.addChildWithTokens(modPublic);
    modifiers.appendToken(TokenBuilder.newSpace());
    clazz.appendToken(TokenBuilder.newClass());
    clazz.appendToken(TokenBuilder.newSpace());
    clazz.addChildWithTokens(ASTUtils.newAST(AS3Parser.IDENT, className));
    clazz.appendToken(TokenBuilder.newSpace());
    clazz.addChildWithTokens(newTypeBlock());
    LinkedListTree annos = ASTUtils.newPlaceholderAST(AS3Parser.ANNOTATIONS);
    clazz.addChildWithTokens(0, annos);
    return clazz;
  }

  private static String packageNameFrom(String qualifiedName) {
    int p = qualifiedName.lastIndexOf('.');
    if (p == -1) {
      return null;
    }
    return qualifiedName.substring(0, p);
  }

  public static ASTASMethod newClassMethod(String name, Visibility visibility, String returnType) {
    LinkedListTree def = ASTUtils.newImaginaryAST(AS3Parser.METHOD_DEF);
    LinkedListTree annos = ASTUtils.newPlaceholderAST(AS3Parser.ANNOTATIONS);
    def.addChildWithTokens(annos);
    def.addChildWithTokens(ModifierUtils.toModifiers(visibility));
    def.appendToken(TokenBuilder.newFunction());
    def.appendToken(TokenBuilder.newSpace());
    LinkedListTree acc = ASTUtils.newPlaceholderAST(AS3Parser.ACCESSOR_ROLE);
    def.addChildWithTokens(acc);
    LinkedListTree methName = ASTUtils.newAST(AS3Parser.IDENT, name);
    def.addChildWithTokens(methName);
    def.addChildWithTokens(ASTUtils.newParentheticAST(AS3Parser.PARAMS, AS3Parser.LPAREN, "(", AS3Parser.RPAREN, ")"));
    if (returnType != null) {
      def.addChildWithTokens(AS3FragmentParser.parseTypeSpec(returnType));
    }
    def.appendToken(TokenBuilder.newSpace());
    LinkedListTree block = newBlock();
    def.addChildWithTokens(block);

    return new ASTASMethod(def);
  }

  public static ASTASField newField(String name, Visibility visibility, String type) {
    if (name.indexOf('.') != -1) {
      throw new SyntaxException("field name must not contain '.'");
    }
    LinkedListTree decl = ASTUtils.newImaginaryAST(AS3Parser.VAR_DEF);
    LinkedListTree annos = ASTUtils.newPlaceholderAST(AS3Parser.ANNOTATIONS);
    decl.addChildWithTokens(annos);
    decl.addChildWithTokens(ModifierUtils.toModifiers(visibility));
    decl.addChildWithTokens(ASTUtils.newAST(AS3Parser.VAR, "var"));
    decl.appendToken(TokenBuilder.newSpace());
    LinkedListTree def = ASTUtils.newAST(AS3Parser.IDENT, name);
    decl.addChildWithTokens(def);
    if (type != null) {
      def.addChildWithTokens(AS3FragmentParser.parseTypeSpec(type));
    }
    decl.appendToken(TokenBuilder.newSemi());
    return new ASTASField(decl);
  }

  public static ASTASMethod newInterfaceMethod(String name, Visibility visibility, String returnType) {
    LinkedListTree def = ASTUtils.newImaginaryAST(AS3Parser.METHOD_DEF);
    LinkedListTree annos = ASTUtils.newPlaceholderAST(AS3Parser.ANNOTATIONS);
    def.addChildWithTokens(annos);
    def.addChildWithTokens(ModifierUtils.toModifiers(visibility));
    def.appendToken(TokenBuilder.newFunction());
    def.appendToken(TokenBuilder.newSpace());
    LinkedListTree acc = ASTUtils.newPlaceholderAST(AS3Parser.ACCESSOR_ROLE);
    def.addChildWithTokens(acc);
    LinkedListTree methName = ASTUtils.newAST(AS3Parser.IDENT, name);
    def.addChildWithTokens(methName);
    def.addChildWithTokens(ASTUtils.newParentheticAST(AS3Parser.PARAMS, AS3Parser.LPAREN, "(", AS3Parser.RPAREN, ")"));
    if (returnType != null) {
      def.addChildWithTokens(AS3FragmentParser.parseTypeSpec(returnType));
    }
    def.appendToken(TokenBuilder.newSemi());

    return new ASTASMethod(def);
  }

  public static LinkedListTree newBlock() {
    return newBlock(AS3Parser.BLOCK);
  }

  public static LinkedListTree newTypeBlock() {
    return newBlock(AS3Parser.TYPE_BLOCK);
  }

  private static LinkedListTree newBlock(int type) {
    LinkedListTree ast = ASTUtils.newParentheticAST(type,
                                                    AS3Parser.LCURLY, "{",
                                                    AS3Parser.RCURLY, "}");
    LinkedListToken nl = TokenBuilder.newNewline();
    ast.getInitialInsertionAfter().afterInsert(nl);
    ast.setInitialInsertionAfter(nl);
    return ast;
  }

  public static LinkedListTree newMetadataTag(String name) {
    LinkedListTree ast = ASTUtils.newParentheticAST(AS3Parser.ANNOTATION,
                                                    AS3Parser.LBRACK, "[",
                                                    AS3Parser.RBRACK, "]");
    ast.addChildWithTokens(ASTUtils.newAST(AS3Parser.IDENT, name));
    return ast;
  }

  /**
   * returns a CONDITION node with the given expression as its child
   */
  private static LinkedListTree condition(LinkedListTree expr) {
    LinkedListTree cond =  ASTUtils.newParentheticAST(AS3Parser.CONDITION,
                                                      AS3Parser.LPAREN, "(",
                                                      AS3Parser.RPAREN, ")");
    cond.addChildWithTokens(expr);
    return cond;
  }

  public static LinkedListTree newIf(String condition) {
    return newIf(AS3FragmentParser.parseExpr(condition));
  }
  public static LinkedListTree newIf(LinkedListTree condition) {
    LinkedListTree ifStmt = ASTUtils.newAST(AS3Parser.IF, "if");
    ifStmt.appendToken(TokenBuilder.newSpace());
    ifStmt.addChildWithTokens(condition(condition));
    ifStmt.appendToken(TokenBuilder.newSpace());
    ifStmt.addChildWithTokens(ASTBuilder.newBlock());
    return ifStmt;
  }

  public static LinkedListTree newFor(String init, String condition, String iterate) {
    return newFor(init==null      ? null : AS3FragmentParser.parseForInit(init),
                  condition==null ? null : AS3FragmentParser.parseForCond(condition),
                  iterate==null   ? null : AS3FragmentParser.parseForIter(iterate));
  }
  public static LinkedListTree newFor(LinkedListTree init, LinkedListTree condition, LinkedListTree iterate) {
    LinkedListTree forStmt = ASTUtils.newAST(AS3Parser.FOR, "for");
    forStmt.appendToken(TokenBuilder.newSpace());
    forStmt.appendToken(TokenBuilder.newLParen());
    if (init != null) {
      forStmt.addChildWithTokens(init);
    } else {
      LinkedListTree initStmt = ASTUtils.newPlaceholderAST(AS3Parser.FOR_INIT);
      forStmt.addChildWithTokens(initStmt);
    }
    forStmt.appendToken(TokenBuilder.newSemi());
    forStmt.appendToken(TokenBuilder.newSpace());
    if (condition != null) {
      forStmt.addChildWithTokens(condition);
    } else {
      LinkedListTree condStmt = ASTUtils.newPlaceholderAST(AS3Parser.FOR_CONDITION);
      forStmt.addChildWithTokens(condStmt);
    }
    forStmt.appendToken(TokenBuilder.newSemi());
    forStmt.appendToken(TokenBuilder.newSpace());
    if (iterate != null) {
      forStmt.addChildWithTokens(iterate);
    } else {
      LinkedListTree iterStmt = ASTUtils.newPlaceholderAST(AS3Parser.FOR_ITERATOR);
      forStmt.addChildWithTokens(iterStmt);
    }
    forStmt.appendToken(TokenBuilder.newRParen());
    return forStmt;
  }

  public static LinkedListTree newForIn(String declaration, String expression) {
    return newForIn(AS3FragmentParser.parseForInVar(declaration),
                    AS3FragmentParser.parseExpr(expression));
  }
  public static LinkedListTree newForIn(LinkedListTree declaration, LinkedListTree expression) {
    LinkedListTree forStmt = ASTUtils.newAST(AS3Parser.FOR_IN, "for");
    forStmt.appendToken(TokenBuilder.newSpace());
    genForInSetup(forStmt, declaration, expression);
    return forStmt;
  }

  public static LinkedListTree newForEachIn(String declaration, String expression) {
    return newForEachIn(AS3FragmentParser.parseForInVar(declaration),
                        AS3FragmentParser.parseExpr(expression));
  }
  public static LinkedListTree newForEachIn(LinkedListTree declaration, LinkedListTree expression) {
    LinkedListTree forStmt = ASTUtils.newAST(AS3Parser.FOR_EACH, "for");
    forStmt.appendToken(TokenBuilder.newSpace());
    forStmt.appendToken(TokenBuilder.newEach());
    genForInSetup(forStmt, declaration, expression);
    return forStmt;
  }

  /**
   * Common code for both for-in and for-each-in loop setup
   */
  private static void genForInSetup(LinkedListTree forStmt,
                                    LinkedListTree declaration,
                                    LinkedListTree expression)
  {
    forStmt.appendToken(TokenBuilder.newLParen());
    forStmt.addChildWithTokens(declaration);
    forStmt.appendToken(TokenBuilder.newSpace());
    forStmt.appendToken(TokenBuilder.newIn());
    forStmt.appendToken(TokenBuilder.newSpace());
    forStmt.addChildWithTokens(expression);
    forStmt.appendToken(TokenBuilder.newRParen());
  }

  public static LinkedListTree newWhile(String condition) {
    return newWhile(AS3FragmentParser.parseExpr(condition));
  }
  public static LinkedListTree newWhile(LinkedListTree condition) {
    LinkedListTree whileStmt = ASTUtils.newAST(AS3Parser.WHILE, "while");
    whileStmt.appendToken(TokenBuilder.newSpace());
    whileStmt.addChildWithTokens(condition(condition));
    return whileStmt;
  }

  public static LinkedListTree newDoWhile(String condition) {
    return newDoWhile(AS3FragmentParser.parseExpr(condition));
  }
  public static LinkedListTree newDoWhile(LinkedListTree condition) {
    LinkedListTree doWhileStmt = ASTUtils.newAST(AS3Parser.DO, "do");
    doWhileStmt.appendToken(TokenBuilder.newSpace());
    LinkedListTree block = ASTBuilder.newBlock();
    doWhileStmt.addChildWithTokens(block);
    doWhileStmt.appendToken(TokenBuilder.newSpace());
    doWhileStmt.appendToken(TokenBuilder.newWhile());
    doWhileStmt.appendToken(TokenBuilder.newSpace());
    doWhileStmt.addChildWithTokens(condition(condition));
    doWhileStmt.appendToken(TokenBuilder.newSemi());
    return doWhileStmt;
  }

  public static LinkedListTree newSwitch(String condition) {
    return newSwitch(AS3FragmentParser.parseExpr(condition));
  }
  public static LinkedListTree newSwitch(LinkedListTree condition) {
    LinkedListTree switchStmt = ASTUtils.newAST(AS3Parser.SWITCH, "switch");
    switchStmt.appendToken(TokenBuilder.newSpace());
    switchStmt.addChildWithTokens(condition(condition));
    switchStmt.appendToken(TokenBuilder.newSpace());
    LinkedListTree block = ASTBuilder.newBlock();
    switchStmt.addChildWithTokens(block);
    return switchStmt;
  }

  public static LinkedListTree newWith(String expr) {
    return newWith(AS3FragmentParser.parseExpr(expr));
  }
  public static LinkedListTree newWith(LinkedListTree expr) {
    LinkedListTree withStmt = ASTUtils.newAST(AS3Parser.WITH, "with");
    withStmt.appendToken(TokenBuilder.newSpace());
    withStmt.addChildWithTokens(condition(expr));
    return withStmt;
  }

  public static LinkedListTree newDeclaration(String assignment) {
    return newDeclaration(AS3FragmentParser.parseVariableDeclarator(assignment));
  }
  public static LinkedListTree newDeclaration(LinkedListTree assignment) {
    LinkedListTree declStmt = ASTUtils.newAST(AS3Parser.VAR, "var");
    declStmt.appendToken(TokenBuilder.newSpace());
    declStmt.addChildWithTokens(assignment);
    declStmt.appendToken(TokenBuilder.newSemi());
    return declStmt;
  }

  public static LinkedListTree newReturn(String expr) {
    return newReturn(expr==null ? null : AS3FragmentParser.parseExpr(expr));
  }
  public static LinkedListTree newReturn(LinkedListTree expr) {
    LinkedListTree returnStmt = ASTUtils.newAST(AS3Parser.RETURN, "return");
    if (expr != null) {
      returnStmt.appendToken(TokenBuilder.newSpace());
      returnStmt.addChildWithTokens(expr);
    }
    returnStmt.appendToken(TokenBuilder.newSemi());
    return returnStmt;
  }

  /**
   * @param args a list of ASExpression objects
   */
  public static LinkedListTree newSuperStatement(List args) {
    LinkedListTree superStmt = ASTUtils.newAST(AS3Parser.SUPER, "super");
    LinkedListTree argumentsNode = ASTUtils.newParentheticAST(AS3Parser.ARGUMENTS, AS3Parser.LPAREN, "(", AS3Parser.RPAREN, ")");
    ArgumentUtils.overwriteArgsWithExpressionList(argumentsNode, args);
    superStmt.addChildWithTokens(argumentsNode);
    superStmt.appendToken(TokenBuilder.newSemi());
    return superStmt;
  }

  public static LinkedListTree newBreakStatement() {
    LinkedListTree breakStmt = ASTUtils.newAST(AS3Parser.BREAK, "break");
    breakStmt.appendToken(TokenBuilder.newSemi());
    return breakStmt;
  }

  public static LinkedListTree newTryStatement() {
    LinkedListTree tryStmt = ASTUtils.newAST(AS3Parser.TRY, "try");
    tryStmt.appendToken(TokenBuilder.newSpace());
    tryStmt.addChildWithTokens(newBlock());
    return tryStmt;
  }

  public static LinkedListTree newCatchClause(String var, String type) {
    LinkedListTree tryStmt = ASTUtils.newAST(AS3Parser.CATCH, "catch");
    tryStmt.appendToken(TokenBuilder.newSpace());
    tryStmt.appendToken(TokenBuilder.newLParen());
    tryStmt.addChildWithTokens(AS3FragmentParser.parseSimpleIdent(var));
    if (type != null) {
      tryStmt.addChildWithTokens(AS3FragmentParser.parseTypeSpec(type));
    }
    tryStmt.appendToken(TokenBuilder.newRParen());
    tryStmt.appendToken(TokenBuilder.newSpace());
    tryStmt.addChildWithTokens(newBlock());
    return tryStmt;
  }

  public static LinkedListTree newFinallyClause() {
    LinkedListTree tryStmt = ASTUtils.newAST(AS3Parser.FINALLY, "finally");
    tryStmt.appendToken(TokenBuilder.newSpace());
    tryStmt.addChildWithTokens(newBlock());
    return tryStmt;
  }

  public static LinkedListTree newContinueStatement() {
    LinkedListTree continueStmt = ASTUtils.newAST(AS3Parser.CONTINUE, "continue");
    continueStmt.appendToken(TokenBuilder.newSemi());
    return continueStmt;
  }

  public static ASBinaryExpression newBinaryExpression(LinkedListToken op, Expression left, Expression right) {
    LinkedListTree ast = ASTUtils.newAST(op);
    LinkedListTree leftExpr = ((ASTExpression)left).getAST();
    assertNoParent("left-hand expression", leftExpr);
    LinkedListTree rightExpr = ((ASTExpression)right).getAST();
    if (precidence(ast) < precidence(leftExpr)) {
      leftExpr = parenthise(leftExpr);
    }
    if (precidence(ast) < precidence(rightExpr)) {
      rightExpr = parenthise(rightExpr);
    }
    // don't use addChildWithTokens(); special handling below,
    ast.addChild(leftExpr);
    ast.addChild(rightExpr);
    leftExpr.getStopToken().setNext(op);
    rightExpr.getStartToken().setPrev(op);
    ast.setStartToken(leftExpr.getStartToken());
    ast.setStopToken(rightExpr.getStopToken());
    spaceEitherSide(op);
    return new ASTASBinaryExpression(ast);
  }

  public static ASAssignmentExpression newAssignExpression(LinkedListToken op, Expression left, Expression right) {
    LinkedListTree ast = ASTUtils.newAST(op);
    LinkedListTree leftExpr = ((ASTExpression)left).getAST();
    assertNoParent("left-hand expression", leftExpr);
    LinkedListTree rightExpr = ((ASTExpression)right).getAST();
    if (precidence(ast) < precidence(leftExpr)) {
      leftExpr = parenthise(leftExpr);
    }
    if (precidence(ast) < precidence(rightExpr)) {
      rightExpr = parenthise(rightExpr);
    }
    // don't use addChildWithTokens(); special handling below,
    ast.addChild(leftExpr);
    ast.addChild(rightExpr);
    leftExpr.getStopToken().setNext(op);
    rightExpr.getStartToken().setPrev(op);
    ast.setStartToken(leftExpr.getStartToken());
    ast.setStopToken(rightExpr.getStopToken());
    spaceEitherSide(op);
    return new ASTASAssignmentExpression(ast);
  }

  public static void assertNoParent(String astDescription, LinkedListTree ast)
  {
    if (ast.getParent() != null) {
      throw new SyntaxException(astDescription+" cannot be added to a second parent node");
    }
  }

  private static LinkedListTree parenthise(LinkedListTree expr) {
    LinkedListTree result = ASTUtils.newParentheticAST(AS3Parser.ENCPS_EXPR, AS3Parser.LPAREN, "(", AS3Parser.RPAREN, ")");
    result.addChildWithTokens(expr);
    return result;
  }

  private static int precidence(LinkedListTree ast) {
    switch (ast.getType()) {
      case AS3Parser.ASSIGN:
      case AS3Parser.STAR_ASSIGN:
      case AS3Parser.DIV_ASSIGN:
      case AS3Parser.MOD_ASSIGN:
      case AS3Parser.PLUS_ASSIGN:
      case AS3Parser.MINUS_ASSIGN:
      case AS3Parser.SL_ASSIGN:
      case AS3Parser.SR_ASSIGN:
      case AS3Parser.BSR_ASSIGN:
      case AS3Parser.BAND_ASSIGN:
      case AS3Parser.BXOR_ASSIGN:
      case AS3Parser.BOR_ASSIGN:
      case AS3Parser.LAND_ASSIGN:
      case AS3Parser.LOR_ASSIGN:
        return 13;
      case AS3Parser.QUESTION:
        return 12;
      case AS3Parser.LOR:
        return 11;
      case AS3Parser.LAND:
        return 10;
      case AS3Parser.BOR:
        return 9;
      case AS3Parser.BXOR:
        return 8;
      case AS3Parser.BAND:
        return 7;
      case AS3Parser.STRICT_EQUAL:
      case AS3Parser.STRICT_NOT_EQUAL:
      case AS3Parser.NOT_EQUAL:
      case AS3Parser.EQUAL:
        return 6;
      case AS3Parser.IN:
      case AS3Parser.LT:
      case AS3Parser.GT:
      case AS3Parser.LE:
      case AS3Parser.GE:
      case AS3Parser.IS:
      case AS3Parser.AS:
      case AS3Parser.INSTANCEOF:
        return 5;
      case AS3Parser.SL:
      case AS3Parser.SR:
      case AS3Parser.BSR:
        return 4;
      case AS3Parser.PLUS:
      case AS3Parser.MINUS:
        return 3;
      case AS3Parser.STAR:
      case AS3Parser.DIV:
      case AS3Parser.MOD:
        return 2;
      default:
        return 1;
    }
  }

  public static LinkedListTree newFieldAccessExpression(LinkedListTree target, LinkedListTree name) {
    LinkedListToken op = TokenBuilder.newDot();
    LinkedListTree ast = ASTUtils.newAST(op);
    assertNoParent("target expression", target);
    // don't use addChildWithTokens(); special handling below,
    ast.addChild(target);
    ast.addChild(name);
    target.getStopToken().setNext(op);
    name.getStartToken().setPrev(op);
    ast.setStartToken(target.getStartToken());
    ast.setStopToken(name.getStopToken());
    return ast;
  }

  public static LinkedListTree newConditionalExpression(LinkedListTree conditionExpr,
                                                        LinkedListTree thenExpr,
                                                        LinkedListTree elseExpr)
  {
    LinkedListToken op = TokenBuilder.newQuestion();
    LinkedListToken colon = TokenBuilder.newColon();
    LinkedListTree ast = ASTUtils.newAST(op);
    // don't use addChildWithTokens(); special handling below,
    ast.addChild(conditionExpr);
    conditionExpr.getStopToken().setNext(op);
    ast.addChild(thenExpr);
    thenExpr.getStartToken().setPrev(op);
    thenExpr.getStopToken().setNext(colon);
    ast.addChild(elseExpr);
    elseExpr.getStartToken().setPrev(colon);
    ast.setStartToken(conditionExpr.getStartToken());
    ast.setStopToken(elseExpr.getStopToken());
    spaceEitherSide(op);
    spaceEitherSide(colon);
    return ast;
  }

  private static void spaceEitherSide(LinkedListToken token) {
    token.beforeInsert(TokenBuilder.newSpace());
    token.afterInsert(TokenBuilder.newSpace());
  }

  public static LinkedListTree newFunctionExpression() {
    LinkedListTree def = ASTUtils.newImaginaryAST(AS3Parser.FUNC_DEF);
    def.appendToken(TokenBuilder.newFunction());
    def.appendToken(TokenBuilder.newSpace());
    // TODO: placeholder for name?
    def.addChildWithTokens(ASTUtils.newParentheticAST(AS3Parser.PARAMS, AS3Parser.LPAREN, "(", AS3Parser.RPAREN, ")"));
    def.appendToken(TokenBuilder.newSpace());
    LinkedListTree block = newBlock();
    def.addChildWithTokens(block);
    return def;
  }

  public static LinkedListTree newArrayLiteral() {
    LinkedListTree lit = ASTUtils.newParentheticAST(AS3Parser.ARRAY_LITERAL, AS3Parser.LBRACK, "[", AS3Parser.RBRACK, "]");
    return lit;
  }

  public static LinkedListTree newObjectLiteral() {
    LinkedListTree lit = newBlock(AS3Parser.OBJECT_LITERAL);
    return lit;
  }

  public static LinkedListTree newObjectField(String name,
                                              LinkedListTree value)
  {
    LinkedListTree field = ASTUtils.newImaginaryAST(AS3Parser.OBJECT_FIELD);
    field.addChildWithTokens(AS3FragmentParser.parseSimpleIdent(name));
    field.appendToken(TokenBuilder.newColon());
    field.appendToken(TokenBuilder.newSpace());
    field.addChildWithTokens(value);
    return field;
  }

  public static LinkedListTree newThrowStatement(LinkedListTree ast) {
    LinkedListTree thrw = ASTUtils.newAST(AS3Parser.THROW, "throw");
    thrw.appendToken(TokenBuilder.newSpace());
    thrw.addChildWithTokens(ast);
    thrw.appendToken(TokenBuilder.newSemi());
    return thrw;
  }

  public static LinkedListTree dup(LinkedListTree ast) {
    Map tokens = dupTokStream(ast);
    return dupTree(ast, tokens);
  }

  private static LinkedListTree dupTree(LinkedListTree ast, Map tokens) {
    LinkedListToken newTok = (LinkedListToken)tokens.get(ast.getToken());
    LinkedListTree result = new LinkedListTree(newTok);
    result.setStartToken((LinkedListToken)tokens.get(ast.getStartToken()));
    result.setStopToken((LinkedListToken)tokens.get(ast.getStopToken()));
    result.setTokenListUpdater(ast.getTokenListUpdater());
    result.setInitialInsertionAfter(ast.getInitialInsertionAfter());
    result.setInitialInsertionBefore(ast.getInitialInsertionBefore());
    for (ASTIterator i=new ASTIterator(ast); i.hasNext(); ) {
      LinkedListTree newChild = dupTree(i.next(), tokens);
      result.addChild(newChild);
    }
    return result;
  }

  private static Map dupTokStream(LinkedListTree ast) {
    Map tokens = new HashMap();
    LinkedListToken last = null;
    for (LinkedListToken tok=ast.getStartToken(); tok!=null&&tok.getType()!=-1; tok=tok.getNext()) {
      LinkedListToken newTok = dupTok(tok);
      tokens.put(tok, newTok);
      if (last != null) {
        last.setNext(newTok);
      }
      if (tok == ast.getStopToken()) {
        break;
      }
      last = newTok;
    }
    return tokens;
  }

  private static LinkedListToken dupTok(LinkedListToken tok) {
    LinkedListToken result;
    if (tok instanceof PlaceholderLinkedListToken) {
      result = new PlaceholderLinkedListToken(((PlaceholderLinkedListToken)tok).getHeld());
    } else {
      result = new LinkedListToken(tok.getType(),
                                         tok.getText());
    }
    result.setChannel(tok.getChannel());
    result.setCharPositionInLine(tok.getCharPositionInLine());
    result.setLine(tok.getLine());
    return result;
  }

  public static LinkedListTree newDescendantExpression(LinkedListTree target,
                                                       LinkedListTree selector)
  {
    LinkedListToken op = TokenBuilder.newE4XDescendant();
    LinkedListTree ast = ASTUtils.newAST(op);
    assertNoParent("left-hand expression", target);
    // TODO: is this needed..?
    if (precidence(ast) < precidence(target)) {
      target = parenthise(target);
    }
    if (precidence(ast) < precidence(selector)) {
      selector = parenthise(selector);
    }
    // don't use addChildWithTokens(); special handling below,
    ast.addChild(target);
    ast.addChild(selector);
    target.getStopToken().setNext(op);
    selector.getStartToken().setPrev(op);
    ast.setStartToken(target.getStartToken());
    ast.setStopToken(selector.getStopToken());
    return ast;
  }

  public static LinkedListTree newFilterExpression(LinkedListTree target,
                                                   LinkedListTree selector)
  {
    LinkedListTree ast = ASTUtils.newImaginaryAST(AS3Parser.E4X_FILTER);
    assertNoParent("target expression", target);
    assertNoParent("query expression", target);
    // don't use addChildWithTokens(); special handling below,
    ast.addChildWithTokens(target);
    ast.appendToken(TokenBuilder.newDot());
    ast.appendToken(TokenBuilder.newLParen());
    ast.addChildWithTokens(selector);
    ast.appendToken(TokenBuilder.newRParen());
    return ast;
  }

  public static LinkedListTree newStarAttribute() {
    LinkedListTree ast = ASTUtils.newImaginaryAST(AS3Parser.E4X_ATTRI_STAR);
    ast.appendToken(TokenBuilder.newAt());
    ast.appendToken(TokenBuilder.newStar());
    return ast;
  }

  public static LinkedListTree newPropertyAttribute(String propertyName) {
    LinkedListTree ast = ASTUtils.newImaginaryAST(AS3Parser.E4X_ATTRI_PROPERTY);
    ast.appendToken(TokenBuilder.newAt());
    LinkedListTree prop = AS3FragmentParser.parseQualifiedIdent(propertyName);
    ast.addChildWithTokens(prop);
    return ast;
  }

  public static LinkedListTree newExpressionAttribute(LinkedListTree expr) {
    LinkedListTree ast = ASTUtils.newImaginaryAST(AS3Parser.E4X_ATTRI_EXPR);
    ast.appendToken(TokenBuilder.newAt());
    ast.appendToken(TokenBuilder.newLBrack());
    ast.addChildWithTokens(expr);
    ast.appendToken(TokenBuilder.newRBrack());
    return ast;
  }

  public static LinkedListTree newString(String value) {
    return ASTUtils.newAST(AS3Parser.STRING_LITERAL, ActionScriptFactory.str(value));
  }

  public static LinkedListTree newDefaultXMLNamespace(LinkedListTree namespace) {
    LinkedListTree ast = ASTUtils.newImaginaryAST(AS3Parser.DEFAULT_XML_NAMESPACE);
    ast.appendToken(TokenBuilder.newDefault());
    ast.appendToken(TokenBuilder.newSpace());
    ast.appendToken(TokenBuilder.newXml());
    ast.appendToken(TokenBuilder.newSpace());
    ast.appendToken(TokenBuilder.newNamespace());
    ast.appendToken(TokenBuilder.newSpace());
    ast.appendToken(TokenBuilder.newAssign());
    ast.appendToken(TokenBuilder.newSpace());
    ast.addChildWithTokens(namespace);
    ast.appendToken(TokenBuilder.newSemi());
    return ast;
  }
}
TOP

Related Classes of uk.co.badgersinfoil.metaas.impl.ASTBuilder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.