/* 63: */ /* 64: */ public Type typeCheck(SymbolTable stable) /* 65: */ throws TypeCheckError /* 66: */ { /* 67:120 */ if (this._type != null) { /* 68:120 */ return this._type; /* 69: */ } /* 70:123 */ if (this._variable.isLocal()) /* 71: */ { /* 72:124 */ SyntaxTreeNode node = getParent(); /* 73: */ do /* 74: */ { /* 75:126 */ if ((node instanceof Closure)) /* 76: */ { /* 77:127 */ this._closure = ((Closure) node); /* 78:128 */ break; /* 79: */ } /* 80:130 */ if ((node instanceof TopLevelElement)) { /* 81: */ break; /* 82: */ } /* 83:133 */ node = node.getParent(); /* 84:134 */ } while (node != null); /* 85:136 */ if (this._closure != null) { /* 86:137 */ this._closure.addVariable(this); /* 87: */ } /* 88: */ } /* 89:142 */ this._type = this._variable.getType(); /* 90:146 */ if (this._type == null) /* 91: */ { /* 92:147 */ this._variable.typeCheck(stable); /* 93:148 */ this._type = this._variable.getType(); /* 94: */ } /* 95:152 */ addParentDependency(); /* 96: */ /* 97: */ /* 98:155 */ return this._type; /* 99: */ }
/** * Type check a predicate expression. If the type of the expression is number convert it to * boolean by adding a comparison with position(). Note that if the expression is a parameter, we * cannot distinguish at compile time if its type is number or not. Hence, expressions of * reference type are always converted to booleans. * * <p>This method may be called twice, before and after calling <code>dontOptimize()</code>. If * so, the second time it should honor the new value of <code>_canOptimize</code>. */ public Type typeCheck(SymbolTable stable) throws TypeCheckError { Type texp = _exp.typeCheck(stable); // We need explicit type information for reference types - no good! if (texp instanceof ReferenceType) { _exp = new CastExpr(_exp, texp = Type.Real); } // A result tree fragment should not be cast directly to a number type, // but rather to a boolean value, and then to a numer (0 or 1). // Ref. section 11.2 of the XSLT 1.0 spec if (texp instanceof ResultTreeType) { _exp = new CastExpr(_exp, Type.Boolean); _exp = new CastExpr(_exp, Type.Real); texp = _exp.typeCheck(stable); } // Numerical types will be converted to a position filter if (texp instanceof NumberType) { // Cast any numerical types to an integer if (texp instanceof IntType == false) { _exp = new CastExpr(_exp, Type.Int); } if (_canOptimize) { // Nth position optimization. Expression must not depend on context _nthPositionFilter = !_exp.hasLastCall() && !_exp.hasPositionCall(); // _nthDescendant optimization - only if _nthPositionFilter is on if (_nthPositionFilter) { SyntaxTreeNode parent = getParent(); _nthDescendant = (parent instanceof Step) && (parent.getParent() instanceof AbsoluteLocationPath); return _type = Type.NodeSet; } } // Reset optimization flags _nthPositionFilter = _nthDescendant = false; // Otherwise, expand [e] to [position() = e] final QName position = getParser().getQNameIgnoreDefaultNs("position"); final PositionCall positionCall = new PositionCall(position); positionCall.setParser(getParser()); positionCall.setParent(this); _exp = new EqualityExpr(Operators.EQ, positionCall, _exp); if (_exp.typeCheck(stable) != Type.Boolean) { _exp = new CastExpr(_exp, Type.Boolean); } return _type = Type.Boolean; } else { // All other types will be handled as boolean values if (texp instanceof BooleanType == false) { _exp = new CastExpr(_exp, Type.Boolean); } return _type = Type.Boolean; } }
/** Returns a reference to its parent closure or null if outermost. */ public Closure getParentClosure() { if (_parentClosure == null) { SyntaxTreeNode node = getParent(); do { if (node instanceof Closure) { _parentClosure = (Closure) node; break; } if (node instanceof TopLevelElement) { break; // way up in the tree } node = node.getParent(); } while (node != null); } return _parentClosure; }
public void createSyntaxTree( SyntaxTreeNode node, SyntaxTree tree, LinkedList<LinkedList<String>> partitions) { SyntaxTreeNode whenNode = new SyntaxTreeNode(); node.addSuccessor(whenNode); pre.createSyntaxTree(whenNode, tree, partitions); eff.createSyntaxTree(whenNode, tree, partitions); }
/** Parse all direct children of the <xsl:stylesheet/> element. */ public final void parseOwnChildren(Parser parser) { final SymbolTable stable = parser.getSymbolTable(); final String excludePrefixes = getAttribute("exclude-result-prefixes"); final String extensionPrefixes = getAttribute("extension-element-prefixes"); // Exclude XSLT uri stable.pushExcludedNamespacesContext(); stable.excludeURI(Constants.XSLT_URI); stable.excludeNamespaces(excludePrefixes); stable.excludeNamespaces(extensionPrefixes); final Vector contents = getContents(); final int count = contents.size(); // We have to scan the stylesheet element's top-level elements for // variables and/or parameters before we parse the other elements for (int i = 0; i < count; i++) { SyntaxTreeNode child = (SyntaxTreeNode) contents.elementAt(i); if ((child instanceof VariableBase) || (child instanceof NamespaceAlias)) { parser.getSymbolTable().setCurrentNode(child); child.parseContents(parser); } } // Now go through all the other top-level elements... for (int i = 0; i < count; i++) { SyntaxTreeNode child = (SyntaxTreeNode) contents.elementAt(i); if (!(child instanceof VariableBase) && !(child instanceof NamespaceAlias)) { parser.getSymbolTable().setCurrentNode(child); child.parseContents(parser); } // All template code should be compiled as methods if the // <xsl:apply-imports/> element was ever used in this stylesheet if (!_templateInlining && (child instanceof Template)) { Template template = (Template) child; String name = "template$dot$" + template.getPosition(); template.setName(parser.getQName(name)); } } stable.popExcludedNamespacesContext(); }
/* 27: */ /* 28: */ public void addParentDependency() /* 29: */ { /* 30: 73 */ SyntaxTreeNode node = this; /* 31: 74 */ while ((node != null) && (!(node instanceof TopLevelElement))) { /* 32: 75 */ node = node.getParent(); /* 33: */ } /* 34: 78 */ TopLevelElement parent = (TopLevelElement) node; /* 35: 79 */ if (parent != null) /* 36: */ { /* 37: 80 */ VariableBase var = this._variable; /* 38: 81 */ if (this._variable._ignore) { /* 39: 82 */ if ((this._variable instanceof Variable)) { /* 40: 83 */ var = parent.getSymbolTable().lookupVariable(this._variable._name); /* 41: 85 */ } else if ((this._variable instanceof Param)) { /* 42: 86 */ var = parent.getSymbolTable().lookupParam(this._variable._name); /* 43: */ } /* 44: */ } /* 45: 90 */ parent.addDependency(var); /* 46: */ } /* 47: */ }
/** * Adds a single prefix mapping to this syntax tree node. * * @param prefix Namespace prefix. * @param uri Namespace URI. */ protected void addPrefixMapping(String prefix, String uri) { if (prefix.equals(EMPTYSTRING) && uri.equals(XHTML_URI)) return; super.addPrefixMapping(prefix, uri); }
public void setParser(Parser parser) { super.setParser(parser); _name = makeStylesheetName("__stylesheet_"); }
public static List<TableSchemaAttributeDetail> resolve( SyntaxTreeListNode<SyntaxTreeNode> projectionList, TableSchema schema) throws SQLSemanticException { SyntaxTreeNode node = projectionList.getNode(); List<TableSchemaAttributeDetail> result = new LinkedList<TableSchemaAttributeDetail>(); if (node.getClass().equals(SyntaxTreeRenameNode.class)) { // Case 0 :: renamed aggregate SyntaxTreeRenameNode rdnode = (SyntaxTreeRenameNode) node; if (rdnode.getChild().getClass().equals(SyntaxTreeIdentifierNode.class)) { SyntaxTreeIdentifierNode inode = (SyntaxTreeIdentifierNode) rdnode.getChild(); if (inode.generatingToken.tokenClass == SQLToken.SQLTokenClass .AGGREGATE) { // aggregates are not renamed in the projection, but in the // aggregation int index = schema.indexOfAttributeName(rdnode.name, 0); result.add(schema.getAttributes().get(index)); } else { throw new SQLSemanticException( SQLSemanticException.Type.InternalError); // only rename aggregates } } else { throw new SQLSemanticException(SQLSemanticException.Type.InternalError); } } else if (node.getClass() .equals(SyntaxTreeIdentifierNode.class)) { // Case 1 :: identifier or unnamed aggregate SyntaxTreeIdentifierNode idnode = (SyntaxTreeIdentifierNode) node; if (idnode.generatingToken.tokenClass == SQLToken.SQLTokenClass.STAR) { // Case 1a ::add all attributes from the child schema result = schema.getAttributes(); } else if (idnode.generatingToken.tokenClass == SQLToken.SQLTokenClass .QSTARID) { // Case 1b :: add all attributes that have the right qualifier List<TableSchemaAttributeDetail> allAttributes = schema.getAttributes(); String attributeQualifier = idnode.generatingToken.getQualifierForIdentifier(); if (!schema.getQualifiers().contains(attributeQualifier)) { throw new SQLSemanticException( SQLSemanticException.Type.NoSuchTableException, attributeQualifier); } for (TableSchemaAttributeDetail attribute : allAttributes) { if (attribute.qualifier.equals(attributeQualifier)) { result.add(attribute); } } } else if (idnode.generatingToken.tokenClass == SQLToken.SQLTokenClass .QID) { // Case 1c :: add the first attribute that has the right name and right // qualifier Pair<String, String> nameParts = idnode.generatingToken.getFragmentsForIdentifier(); int currentIndex = schema.indexOfQualifiedAttributeName(nameParts.first, nameParts.second); if (currentIndex < 0) throw new SQLSemanticException( SQLSemanticException.Type.NoSuchAttributeException, nameParts.second); result.add(schema.getAttributes().get(currentIndex)); } else if (idnode.generatingToken.tokenClass == SQLToken.SQLTokenClass .UID) { // Case 1d :: add the first attribute that has the right name Pair<String, String> nameParts = idnode.generatingToken.getFragmentsForIdentifier(); int index = schema.indexOfAttributeName(nameParts.second, 0); if (index < 0) throw new SQLSemanticException( SQLSemanticException.Type.NoSuchAttributeException, nameParts.second); result.add(schema.getAttributes().get(index)); } else { throw new SQLSemanticException(SQLSemanticException.Type.InternalError); } } else { throw new SQLSemanticException(SQLSemanticException.Type.InternalError); } if (projectionList.getNext() != null) { // recursively resolve rest of the list and append result.addAll(resolve(projectionList.getNext(), schema)); } return result; }
/** * Implementiert den LR-Parse-Algorithmus aus dem Drachenbuch (Algorithmus 4.30/ S. 302 in der 2. * deutschen Auflage). Erweitert um die Erzeugung des (vollständigen) Parsebaums und dessen * Reduzierung auf den Abstrakten Syntaxbaum. Erweitert um die Behandlung von ε-Übergängen * Speichert die gelesenen Token um sie mit den Terminalknoten zu verknüpfen. LR-Parse-Algorithmus * aus dem Drachenbuch : <code> * Eingabe: ein Eingabestring w und eine LR-Parsertabelle mit den Funtkionen ACTION und GOTO für eine Grammatik G * Ausgabe: wenn w in L(G) ist, die Reduzierungsschritte einer Bottom-Up-Analyse für w, andernfalls eine Fehlermeldung * Methode: Zunächst liegt s0, der Ausgangszustand, auf dem Stack und w$ befindet sich im Eingabepuffer. Dann führt der Parser das folgende Programm aus: * * Sei a das erste Symbol von w$; * while(1){ * Sei s der oberste Zustand auf dem Stack; * if (ACTION[s,a] = shift t){ * verschiebe t auf den Stack; * Sei a das nächste Eingabesymbol; * } * else if (ACTION[s,a] = reduce A → β){ * Entferne |β| Symbole vom Stack; * Zustand t liegt jetzt oben auf dem Stack; * verschiebe GOTO[t,A] auf den Stack; * gib die Produktion A → β aus; * } * else if (ACTION[s,a] = accept){ * break; // Analyse ist beendet * } * else{ * Fehlerbehandlung aufrufen; * } * } * </code> * * @param lexer ILexer für die Eingabe * @param parseTable LR-Parsertabelle mit den Funtkionen ACTION und GOTO * @return den vollständigen (konkreten) Parsebaum * @throws LRParserException falls kein Parsebaum erzeugt werden konnte. */ public ISyntaxTree parse(ILexer lexer, ParseTable parseTable) { Stack<IToken> tokenStack = new Stack<IToken>(); Stack<SyntaxTreeNode> nodeStack = new Stack<SyntaxTreeNode>(); Stack<State> stateStack = new Stack<State>(); stateStack.push(parseTable.getInitialState()); IToken currentToken = readNextToken(lexer); // tokenStack.push(currentToken); TerminalSymbol currentTerminalSymbol = new TerminalSymbol(currentToken.getText()); while (true) { State currentState = stateStack.peek(); Action currentAction = parseTable.getAction(currentState, currentTerminalSymbol); // TODO printConfiguration():String und logConfiguration:boolean logger.finer(stateStack + " : " + currentToken + " : " + currentAction); if (currentAction instanceof ShiftAction) { State targetState = ((ShiftAction) currentAction).getTargetState(); stateStack.push(targetState); tokenStack.push(currentToken); currentToken = readNextToken(lexer); currentTerminalSymbol = new TerminalSymbol(currentToken.getText()); } else if (currentAction instanceof ReduceAction) { Production p = ((ReduceAction) currentAction).getProduction(); for (int i = 0; i < p.getRhs().size(); i++) { stateStack.pop(); } State s = stateStack.peek(); State targetState = parseTable.getGoto(s, p.getLhs()).getTargetState(); stateStack.push(targetState); // AST aufbauen // SyntaxTreeNode für das NonTerminalSymbol im Kopf der reduzierten Produktion anlegen SyntaxTreeNode currentNode = new SyntaxTreeNode(p.getLhs()); for (int i = p.getRhs().size() - 1; i >= 0; i--) { // Für jedes Symbol im Rumpf der reduzierten Produktion (von rechts nach links) Symbol aSymbol = p.getRhs().get(i); // Zu jedem Symbol im Rumpf der reduzierten Produktion liegt der zugehörige Knoten (in // umgedrehter Reihenfolge - s.o.) auf dem Stack SyntaxTreeNode aChildNode = null; if (aSymbol instanceof TerminalSymbol) { // Für TerminalSymbol einen einfachen Knoten (Blatt) mit dem zugehörigen Token anlegen aChildNode = new SyntaxTreeNode(tokenStack.pop(), (TerminalSymbol) aSymbol); } else if (aSymbol instanceof NonTerminalSymbol) { // Knoten für NonTerminalSymbol vom Stack nehmen aChildNode = nodeStack.pop(); } currentNode.insertTree(aChildNode); } // Neuen Knoten auf den Stack legen nodeStack.push(currentNode); } else if (currentAction instanceof AcceptAction) { logger.finer("Done."); // Wurzel des Parsebaums vom Stack holen SyntaxTreeNode syntaxTree = nodeStack.pop(); return syntaxTree; } else if (currentAction instanceof ErrorAction) { // Zum aktuellen Eingabe-Token konnte keine gültige Action ermittelt werden // Daher wird jetzt erstmal versucht ob es eine Action für ε gibt. if (!(parseTable.getAction(currentState, Grammar.EPSILON) instanceof ErrorAction)) { // Es gibt eine Action für ε --> Aktuelles Eingabetoken zurückstellen // TODO Prüfen, ob dies die richtige Art und Weise ist um einen ε-Übergang herzustellen // (Der Syntaxbaum für ein einfaches Programm sah jedenfalls richtig aus...) storedToken = currentToken; currentToken = new EpsilonToken(currentToken.getLineNumber(), currentToken.getOffset()); currentTerminalSymbol = Grammar.EPSILON; // if (!tokenStack.isEmpty()){ // tokenStack.pop(); // } // tokenStack.push(currentToken); continue; } logger.warning( "Parse Error: Unexpected Token " + currentToken.getText() + " in line " + currentToken.getLineNumber() + ":" + currentToken.getOffset()); StringBuffer strBufPossibleTokens = new StringBuffer(); int i = 0; for (TerminalSymbol t : parseTable.getActionTableForState(currentState).getAllLegalTerminals()) { if (i > 0) strBufPossibleTokens.append(", "); strBufPossibleTokens.append(t); i++; } logger.warning("Parse Error: Expected Tokens are: " + strBufPossibleTokens); throw new LRParserException( "Parse Error: Unexpected Token " + currentToken.getText() + " in line " + currentToken.getLineNumber() + ":" + currentToken.getOffset()); } } }