package de.skuzzle.polly.core.parser.ast.lang; import de.skuzzle.polly.core.parser.Token; import de.skuzzle.polly.core.parser.ast.declarations.Declaration; import de.skuzzle.polly.core.parser.ast.declarations.types.Type; /** * Superclass for all operators. Operators are represented as a normal function call and * must thus exist as an expression that can be executed when that call is resolved. * * <p>Subclasses should only be used in declarations, but not as Node in the AST.</p> * * @author Simon Taddiken */ public abstract class Operator extends Function { /** * All possible operator types and their string representation. * * @author Simon Taddiken */ public static enum OpType { // casting STRING(Type.STRING.getName().getId()), NUMBER(Type.NUM.getName().getId()), DATE(Type.DATE.getName().getId()), TIMESPAN(Type.TIMESPAN.getName().getId()), CHANNEL(Type.CHANNEL.getName().getId()), USER(Type.USER.getName().getId()), // math functions MIN("min"), MAX("max"), LOG("log"), LN("ln"), SQRT("sqrt"), ROUND("round"), CEIL("ceil"), FLOOR("floor"), SIG("sig"), TAN("tan"), COS("cos"), SIN("sin"), ASIN("asin"), ATAN("atan"), ATAN2("atan2"), HYPOT("hypot"), ACOS("acos"), ABS("abs"), TO_DEGREES("toDegrees"), TO_RADIANS("toRadians"), EXP("exp"), // further functions FOLD_LEFT("foldl"), MAP("map"), ID("id"), COMP("comp"), SORT("sort"), DAY("day"), TRANSPOSE("^T"), ADD("+"), ADDWAVE("+~"), SUB("-"), MUL("*"), DIV("/"), BOOLEAN_AND("&&"), BOOLEAN_OR("||"), AND_OR("&|"), XOR("^^"), DOLLAR("$"), DOTDOT(".."), EGT(">="), ELT("<="), EQ("=="), EXCLAMATION("!"), GT(">"), INDEX("[]"), INTDIV("\\"), INT_AND("&"), INT_OR("|"), LEFT_SHIFT("<<"), LT("<"), MOD("%"), NEQ("!="), POWER("^"), QUESTION("?"), QUEST_EXCL("?!"), RADIX("0x:"), RIGHT_SHIFT(">>"), URIGHT_SHIFT(">>>"), WAVE("~"), IMPLICATION("=>"), EQUIVALENCE("<=>"), IF("if"); private final String id; private OpType(String id) { this.id = id; } public String getId() { return this.id; } /** * Converts from {@link TokenType} to Operator types. * @param token Token to convert into operator type. * @return The operator type. */ public static OpType fromToken(Token token) { switch (token.getType()) { case ADD: return OpType.ADD; case ADDWAVE: return OpType.ADDWAVE; case BOOLEAN_AND: return OpType.BOOLEAN_AND; case BOOLEAN_OR: return OpType.BOOLEAN_OR; case AND_OR: return OpType.AND_OR; case XOR: return OpType.XOR; case DIV: return OpType.DIV; case DOLLAR: return OpType.DOLLAR; case DOTDOT: return OpType.DOTDOT; case EGT: return OpType.EGT; case ELT: return OpType.ELT; case EQ: return OpType.EQ; case EXCLAMATION: return OpType.EXCLAMATION; case GT: return OpType.GT; case INDEX: return OpType.INDEX; case INTDIV: return OpType.INTDIV; case INT_AND: return OpType.INT_AND; case INT_OR: return OpType.INT_OR; case LEFT_SHIFT: return OpType.LEFT_SHIFT; case LT: return OpType.LT; case MOD: return OpType.MOD; case MUL: return OpType.MUL; case NEQ: return OpType.NEQ; case POWER: return OpType.POWER; case QUESTION: return OpType.QUESTION; case QUEST_EXCALAMTION: return OpType.QUEST_EXCL; case RADIX: return OpType.RADIX; case RIGHT_SHIFT: return OpType.RIGHT_SHIFT; case SUB: return OpType.SUB; case URIGHT_SHIFT:return OpType.URIGHT_SHIFT; case WAVE: return OpType.WAVE; case OPENSQBR: return OpType.INDEX; case IF: return OpType.IF; case TRANSPOSE: return OpType.TRANSPOSE; case IMPLICATION: return OpType.IMPLICATION; case EQUIVALENCE: return OpType.EQUIVALENCE; default: throw new IllegalArgumentException("not a valid operator token: " + token); } } } private final OpType op; /** * Creates a new operator. * * @param op The operator type */ public Operator(OpType op) { super(op.getId()); this.op = op; } /** * Gets the identifier that represents this operator. * * @return The identifier. */ public OpType getOp() { return this.op; } /** * Creates a proper declaration for this operator. * * @return A declaration. */ public Declaration createDeclaration() { // HACK: save type, because it will be changed by call to super.createDeclaration final Type t = this.getUnique(); final Declaration vd = super.createDeclaration(); // restore saved type this.setUnique(t); return vd; } /** * Throws a RuntimeException indicating that a operator was declared and called with * a wrong {@link OpType}. * * @param op The invalied operator type. */ protected void invalidOperatorType(OpType op) { throw new RuntimeException("This should not have happened. " + "Operator call with invalid operator type: " + op); } }