You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2014/11/28 11:18:09 UTC

svn commit: r1642281 [6/14] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/main/antlr4/org/apache/sling/parser/expr/generated/ engine/src/main/antlr4/org/apache/sling/scripting/ engine/src/main/antlr4/org/apache/sling/scripting/sigh...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/TernaryOperator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/TernaryOperator.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/TernaryOperator.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/TernaryOperator.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Defines the Sightly ternary operator: {@code condition ? then : else}.
+ */
+public class TernaryOperator implements ExpressionNode {
+
+    private ExpressionNode condition;
+    private ExpressionNode thenBranch;
+    private ExpressionNode elseBranch;
+
+    public TernaryOperator(ExpressionNode condition, ExpressionNode thenBranch, ExpressionNode elseBranch) {
+        this.condition = condition;
+        this.thenBranch = thenBranch;
+        this.elseBranch = elseBranch;
+    }
+
+    public ExpressionNode getCondition() {
+        return condition;
+    }
+
+    public ExpressionNode getThenBranch() {
+        return thenBranch;
+    }
+
+    public ExpressionNode getElseBranch() {
+        return elseBranch;
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    @Override
+    public String toString() {
+        return "TernaryOperator{" +
+                "condition=" + condition +
+                ", thenBranch=" + thenBranch +
+                ", elseBranch=" + elseBranch +
+                '}';
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/TernaryOperator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperation.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperation.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperation.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.expression.node;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.NodeVisitor;
+
+/**
+ * Defines a unary operation (e.g. !variableName).
+ */
+public class UnaryOperation implements ExpressionNode {
+
+    private UnaryOperator operator;
+    private ExpressionNode target;
+
+    public UnaryOperation(UnaryOperator operator, ExpressionNode target) {
+        this.operator = operator;
+        this.target = target;
+    }
+
+    @Override
+    public <T> T accept(NodeVisitor<T> visitor) {
+        return visitor.evaluate(this);
+    }
+
+    public UnaryOperator getOperator() {
+        return operator;
+    }
+
+    public ExpressionNode getTarget() {
+        return target;
+    }
+
+    @Override
+    public String toString() {
+        return "UnaryOperation{" +
+                "operator=" + operator +
+                ", operand=" + target +
+                '}';
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperation.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperator.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperator.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperator.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.expression.node;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+
+/**
+ * Unary operators used in expressions
+ */
+public enum UnaryOperator {
+
+    /** Evaluates to logical negation of the operand */
+    NOT {
+        @Override
+        public Object eval(RenderContext renderContext, Object operand) {
+            return !renderContext.toBoolean(operand);
+        }
+    },
+
+    /** Evaluates whether the operand is a string of only whitespace characters */
+    IS_WHITESPACE  {
+        @Override
+        public Object eval(RenderContext renderContext, Object operand) {
+            return StringUtils.isWhitespace(renderContext.toString(operand));
+        }
+    },
+
+    /**
+     * Evaluates the length of a collection
+     */
+    LENGTH {
+        @Override
+        public Object eval(RenderContext renderContext, Object operand) {
+            return renderContext.toCollection(operand).size();
+        }
+    };
+
+    public abstract Object eval(RenderContext model, Object operand);
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/expression/node/UnaryOperator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/AggregatePluginInvoke.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/AggregatePluginInvoke.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/AggregatePluginInvoke.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/AggregatePluginInvoke.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.impl.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.PushStream;
+
+/**
+ * Plugin invoke which aggregates the behavior of several plugin invokes
+ */
+public class AggregatePluginInvoke implements PluginInvoke {
+
+    private final List<PluginInvoke> invokes;
+
+    public AggregatePluginInvoke(List<PluginInvoke> invokes) {
+        this.invokes = invokes;
+    }
+
+    @Override
+    public void beforeElement(PushStream stream, String tagName) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeElement(stream, tagName);
+        }
+    }
+
+    @Override
+    public void beforeTagOpen(PushStream stream) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeTagOpen(stream);
+        }
+    }
+
+    @Override
+    public void beforeAttributes(PushStream stream) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeAttributes(stream);
+        }
+    }
+
+    @Override
+    public void beforeAttribute(PushStream stream, String attributeName) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeAttribute(stream, attributeName);
+        }
+    }
+
+    @Override
+    public void beforeAttributeValue(PushStream stream, String attributeName, ExpressionNode attributeValue) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeAttributeValue(stream, attributeName, attributeValue);
+        }
+    }
+
+    @Override
+    public void afterAttributeValue(PushStream stream, String attributeName) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterAttributeValue(stream, attributeName);
+        }
+    }
+
+    @Override
+    public void afterAttribute(PushStream stream, String attributeName) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterAttribute(stream, attributeName);
+        }
+    }
+
+    @Override
+    public void onPluginCall(PushStream stream, PluginCallInfo callInfo, Expression expression) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.onPluginCall(stream, callInfo, expression);
+        }
+    }
+
+    @Override
+    public void afterAttributes(PushStream stream) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterAttributes(stream);
+        }
+    }
+
+    @Override
+    public void afterTagOpen(PushStream stream) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterTagOpen(stream);
+        }
+    }
+
+    @Override
+    public void beforeChildren(PushStream stream) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeChildren(stream);
+        }
+    }
+
+    @Override
+    public void afterChildren(PushStream stream) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterChildren(stream);
+        }
+    }
+
+    @Override
+    public void beforeTagClose(PushStream stream, boolean isSelfClosing) {
+        for (PluginInvoke invoke : invokes) {
+            invoke.beforeTagClose(stream, isSelfClosing);
+        }
+    }
+
+    @Override
+    public void afterTagClose(PushStream stream, boolean isSelfClosing) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterTagClose(stream, isSelfClosing);
+        }
+    }
+
+    @Override
+    public void afterElement(PushStream stream) {
+        for (int i = invokes.size() - 1; i >= 0; i--) {
+            PluginInvoke invoke = invokes.get(i);
+            invoke.afterElement(stream);
+        }
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/AggregatePluginInvoke.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+import org.apache.sling.scripting.sightly.impl.plugin.MarkupContext;
+import org.apache.sling.scripting.sightly.impl.compiler.util.SymbolGenerator;
+
+
+/**
+ * Default implementation for the compiler context
+ * @see org.apache.sling.scripting.sightly.impl.plugin.Plugin
+ */
+public class CompilerContext {
+
+    private SymbolGenerator symbolGenerator;
+    private ExpressionWrapper expressionWrapper;
+
+    public CompilerContext(SymbolGenerator symbolGenerator, ExpressionWrapper wrapper) {
+        this.symbolGenerator = symbolGenerator;
+        this.expressionWrapper = wrapper;
+    }
+
+    public String generateVariable(String hint) {
+        return symbolGenerator.next(hint);
+    }
+
+    public Expression adjustToContext(Expression expression, MarkupContext context) {
+        if (!expression.getOptions().containsKey(Syntax.CONTEXT_OPTION)) {
+            return expressionWrapper.adjustToContext(expression, context);
+        }
+        return expression;
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+import org.apache.sling.scripting.sightly.impl.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.impl.plugin.PluginInvoke;
+
+/**
+ * Data structure used by {@link MarkupHandler}.
+ */
+public class ElementContext {
+    private final String tagName;
+    private final String openTagStartMarkup;
+
+    private final List<PrioritizedInvoke> invokeList = new ArrayList<PrioritizedInvoke>();
+    private final List<Map.Entry<String, Object>> attributes = new ArrayList<Map.Entry<String, Object>>();
+    private PluginInvoke aggregateInvoke;
+
+    public ElementContext(String tagName, String openTagStartMarkup) {
+        this.tagName = tagName;
+        this.openTagStartMarkup = openTagStartMarkup;
+    }
+
+    public String getTagName() {
+        return tagName;
+    }
+
+    public String getOpenTagStartMarkup() {
+        return openTagStartMarkup;
+    }
+
+    public void addPlugin(PluginInvoke invoke, int priority) {
+        invokeList.add(new PrioritizedInvoke(invoke, priority));
+    }
+
+    public void addAttribute(String name, String value) {
+        attributes.add(new AbstractMap.SimpleEntry<String, Object>(name, value));
+    }
+
+    public void addPluginCall(String name, PluginCallInfo info, Expression expression) {
+        attributes.add(new AbstractMap.SimpleEntry<String, Object>(name,
+                new AbstractMap.SimpleEntry<PluginCallInfo, Expression>(info, expression)));
+    }
+
+    public Iterable<Map.Entry<String, Object>> getAttributes() {
+        return attributes;
+    }
+
+    public PluginInvoke pluginInvoke() {
+        if (aggregateInvoke == null) {
+            Collections.sort(invokeList);
+            ArrayList<PluginInvoke> result = new ArrayList<PluginInvoke>();
+            for (PrioritizedInvoke prioritizedInvoke : invokeList) {
+                result.add(prioritizedInvoke.invoke);
+            }
+            aggregateInvoke = new AggregatePluginInvoke(result);
+        }
+        return aggregateInvoke;
+    }
+
+
+    private static final class PrioritizedInvoke implements Comparable<PrioritizedInvoke> {
+
+        private final PluginInvoke invoke;
+        private final int priority;
+
+        private PrioritizedInvoke(PluginInvoke invoke, int priority) {
+            this.invoke = invoke;
+            this.priority = priority;
+        }
+
+        @Override
+        public int compareTo(PrioritizedInvoke o) {
+            if (this.priority < o.priority) {
+                return -1;
+            } else if (this.priority == o.priority) {
+                return  0;
+            }
+            return 1;
+        }
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionParser.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionParser.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionParser.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionParser.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.RecognitionException;
+import org.apache.sling.scripting.sightly.impl.parser.expr.generated.SightlyLexer;
+import org.apache.sling.scripting.sightly.impl.parser.expr.generated.SightlyParser;
+
+public class ExpressionParser {
+
+    /**
+     * Parses the expression string.
+     *
+     * @param expressionString as defined by the Sightly spec (https://github.com/Adobe-Marketing-Cloud/sightly-spec/blob/master/SPECIFICATION.md)
+     * @return Parsed Expression object
+     * @throws NullPointerException is the given exprString is null
+     * @throws ParserException      if an error occurs while parsing the expression
+     */
+    public Interpolation parseInterpolation(String expressionString) throws ParserException {
+        SightlyParser parser = createParser(expressionString);
+        try {
+            return parser.interpolation().interp;
+        } catch (RecognitionException e) {
+            throw new ParserException(e);
+        }
+    }
+
+    private SightlyParser createParser(String string) {
+        SightlyLexer lexer = new SightlyLexer(new ANTLRInputStream(string));
+        CommonTokenStream tokenStream = new CommonTokenStream(lexer);
+        SightlyParser parser = new SightlyParser(tokenStream);
+        parser.removeErrorListeners();
+        parser.addErrorListener(new SightlyParserErrorListener());
+        return parser;
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionParser.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionWrapper.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionWrapper.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionWrapper.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.impl.compiler.Syntax;
+import org.apache.sling.scripting.sightly.impl.filter.Filter;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.BinaryOperation;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.BinaryOperator;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.impl.plugin.MarkupContext;
+
+/**
+ * This object wraps expressions in filter applications depending
+ * on options
+ */
+public class ExpressionWrapper {
+
+    private final List<Filter> filters;
+
+    public ExpressionWrapper(Collection<Filter> filters) {
+        this.filters = new ArrayList<Filter>();
+        this.filters.addAll(filters);
+        Collections.sort(this.filters);
+    }
+
+    public Expression transform(Interpolation interpolation, MarkupContext markupContext) {
+        ArrayList<ExpressionNode> nodes = new ArrayList<ExpressionNode>();
+        HashMap<String, ExpressionNode> options = new HashMap<String, ExpressionNode>();
+        for (Fragment fragment : interpolation.getFragments()) {
+            if (fragment.isString()) {
+                nodes.add(new StringConstant(fragment.getText()));
+            } else {
+                Expression expression = fragment.getExpression();
+                options.putAll(expression.getOptions());
+                nodes.add(transformExpr(expression, markupContext).getRoot());
+            }
+        }
+        ExpressionNode root = join(nodes);
+        if (interpolation.size() > 1 && options.containsKey(Syntax.CONTEXT_OPTION)) {
+            //context must not be calculated by merging
+            options.remove(Syntax.CONTEXT_OPTION);
+        }
+        return new Expression(root, options);
+    }
+
+    private Expression applyFilters(Expression expression) {
+        Expression result = expression;
+        for (Filter filter : filters) {
+            result = filter.apply(result);
+        }
+        return result;
+    }
+
+    public Expression adjustToContext(Expression expression, MarkupContext markupContext) {
+        if (expression.containsOption(Syntax.CONTEXT_OPTION)) {
+            return expression;
+        }
+        Map<String, ExpressionNode> opt = addDefaultContext(Collections.<String, ExpressionNode>emptyMap(), markupContext);
+        Expression result = applyFilters(new Expression(expression.getRoot(), opt));
+        return expression.withNode(result.getRoot());
+    }
+
+    private ExpressionNode join(List<ExpressionNode> nodes) {
+        if (nodes.isEmpty()) {
+            return StringConstant.EMPTY;
+        }
+        ExpressionNode root = nodes.get(0);
+        for (int i = 1; i < nodes.size(); i++) {
+            ExpressionNode node = nodes.get(i);
+            root = new BinaryOperation(BinaryOperator.CONCATENATE, root, node);
+        }
+        return root;
+    }
+
+    private Expression transformExpr(Expression expression, MarkupContext markupContext) {
+        expression = addDefaultContext(expression, markupContext);
+        return applyFilters(expression);
+    }
+
+    private Expression addDefaultContext(Expression expression, MarkupContext context) {
+        return new Expression(expression.getRoot(), addDefaultContext(expression.getOptions(), context));
+    }
+
+    private Map<String, ExpressionNode> addDefaultContext(Map<String, ExpressionNode> options, MarkupContext context) {
+        if (context == null || options.containsKey(Syntax.CONTEXT_OPTION)) {
+            return options;
+        }
+        HashMap<String, ExpressionNode> newOptions = new HashMap<String, ExpressionNode>(options);
+        newOptions.put(Syntax.CONTEXT_OPTION, new StringConstant(context.getName()));
+        return newOptions;
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ExpressionWrapper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Fragment.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Fragment.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Fragment.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Fragment.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+
+/**
+ * A segment in an interpolation.
+ */
+public interface Fragment {
+
+    boolean isString();
+    boolean isExpression();
+
+    Expression getExpression();
+    String getText();
+
+    /**
+     * A fragment which is an expression.
+     */
+    public static class Expr implements Fragment {
+
+        private Expression expression;
+
+        public Expr(Expression expression) {
+            this.expression = expression;
+        }
+
+        @Override
+        public Expression getExpression() {
+            return expression;
+        }
+
+        @Override
+        public String getText() {
+            throw new UnsupportedOperationException("Not a text fragment");
+        }
+
+        public boolean isString() {
+            return false;
+        }
+
+        public boolean isExpression() {
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "Expr{" +
+                    "expression=" + expression +
+                    '}';
+        }
+    }
+
+    /**
+     * A text fragment.
+     */
+    public static class Text implements Fragment {
+        private String text;
+
+        public Text(String text) {
+            this.text = text;
+        }
+
+        @Override
+        public String getText() {
+            return text;
+        }
+
+        public boolean isString() {
+            return true;
+        }
+
+        public boolean isExpression() {
+            return false;
+        }
+
+        @Override
+        public Expression getExpression() {
+            throw new UnsupportedOperationException("Not an expression fragment");
+        }
+
+        @Override
+        public String toString() {
+            return "Text{" +
+                    "text='" + text + '\'' +
+                    '}';
+        }
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Fragment.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Interpolation.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Interpolation.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Interpolation.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Interpolation.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
+
+/**
+ * A sequence with alternating string fragments and Sightly expressions.
+ * These result from parsing HTML attributes or string nodes.
+ * For instance "Hello ${World}!" would result in 3 fragments:
+ * "Hello ", ${World} and "!"
+ */
+public class Interpolation {
+
+    //todo: this should be immutable to maintain the design consistent
+
+    private List<Fragment> fragments = new ArrayList<Fragment>();
+
+    public void addFragment(Fragment fragment) {
+        fragments.add(fragment);
+    }
+
+    public void addExpression(Expression expression) {
+        fragments.add(new Fragment.Expr(expression));
+    }
+
+    public void addText(String text) {
+        fragments.add(new Fragment.Text(text));
+    }
+
+    /**
+     * Get the number of fragments
+     * @return the number of fragments
+     */
+    public int size() {
+        return fragments.size();
+    }
+
+    /**
+     * Return the fragment with the specified index
+     * @param index - the index of the fragments. must be less than the size of the interpolation
+     * @return - the specified fragment
+     * @throws IndexOutOfBoundsException - if the index is negative or greater or equal than size
+     */
+    public Fragment getFragment(int index) {
+        return fragments.get(index);
+    }
+
+    public Iterable<Fragment> getFragments() {
+        return fragments;
+    }
+
+    @Override
+    public String toString() {
+        return "Interpolation{" +
+                "fragments=" + fragments +
+                '}';
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/Interpolation.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserException.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserException.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserException.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserException.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+/**
+ * Plugin runtime exception to be used for either html or expression parser exceptions.
+ */
+public class ParserException extends RuntimeException {
+
+    public ParserException() {
+        super();
+    }
+
+    public ParserException(String message) {
+        super(message);
+    }
+
+    public ParserException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
+
+    public ParserException(Throwable throwable) {
+        super(throwable);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserException.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserHelper.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserHelper.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserHelper.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.StringConstant;
+
+/**
+ * Helper utilities for the ANTLR parser
+ */
+public class ParserHelper {
+
+    public static String unEscape(String original) {
+        return original.replaceAll("\\\\\"", "\"").replaceAll("\\\\'", "'");
+    }
+
+    public static StringConstant createStringConstant(String original) {
+        String escaped = StringEscapeUtils.unescapeJava(original);
+        String trimmed = escaped.substring(1, escaped.length() - 1);
+        return new StringConstant(trimmed);
+    }
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ParserHelper.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SightlyParserErrorListener.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SightlyParserErrorListener.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SightlyParserErrorListener.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SightlyParserErrorListener.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.Parser;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.apache.sling.scripting.sightly.impl.compiler.SightlyParsingException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@code SightlyParserErrorListener} handles parsing error reporting by sending offending input to a logger.
+ */
+public class SightlyParserErrorListener extends BaseErrorListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SightlyParserErrorListener.class);
+
+    @Override
+    public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) {
+        List<String> stack = ((Parser) recognizer).getRuleInvocationStack();
+        Collections.reverse(stack);
+        StringBuilder errorMessage = new StringBuilder();
+        errorMessage.append("Sightly syntax error detected.\n");
+        errorMessage.append("rule stack: ").append(stack).append("\n");
+        errorMessage.append("error starts at column: ").append(charPositionInLine).append("\n");
+        errorMessage.append(msg);
+        throw new SightlyParsingException("Sightly syntax error detected", ((CommonTokenStream) recognizer.getInputStream()).getTokenSource().getInputStream().toString(), e);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SightlyParserErrorListener.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SimpleFrontend.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SimpleFrontend.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SimpleFrontend.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SimpleFrontend.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.frontend;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.impl.compiler.CompilerFrontend;
+import org.apache.sling.scripting.sightly.impl.filter.Filter;
+import org.apache.sling.scripting.sightly.impl.html.dom.HtmlParserService;
+import org.apache.sling.scripting.sightly.impl.html.dom.MarkupHandler;
+import org.apache.sling.scripting.sightly.impl.plugin.Plugin;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.PushStream;
+
+/**
+ * DOM-based compiler implementation
+ */
+public class SimpleFrontend implements CompilerFrontend {
+
+    private final HtmlParserService htmlParserService;
+    private final Map<String, Plugin> plugins;
+    private final List<Filter> filters;
+
+    public SimpleFrontend(HtmlParserService htmlParserService, Collection<Plugin> plugins, Collection<Filter> filters) {
+        this.plugins = new HashMap<String, Plugin>();
+        for (Plugin plugin : plugins) {
+            this.plugins.put(plugin.name(), plugin);
+        }
+        this.filters = new ArrayList<Filter>(filters);
+        this.htmlParserService = htmlParserService;
+    }
+
+    @Override
+    public void compile(PushStream stream, String source) {
+        MarkupHandler markupHandler = new MarkupHandler(stream, plugins, filters);
+        htmlParserService.parse(source, markupHandler);
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/SimpleFrontend.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CoalescingWrites.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CoalescingWrites.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CoalescingWrites.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CoalescingWrites.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.optimization;
+
+import org.apache.sling.scripting.sightly.impl.compiler.ris.Command;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandHandler;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandStream;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.OutText;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.PushStream;
+
+/**
+ * Aggregate consecutive writes in bigger chunks of text
+ */
+public final class CoalescingWrites implements CommandHandler {
+
+    public static final StreamTransformer TRANSFORMER = new StreamTransformer() {
+        @Override
+        public CommandStream transform(CommandStream inStream) {
+            PushStream outputStream = new PushStream();
+            CoalescingWrites instance = new CoalescingWrites(outputStream);
+            inStream.addHandler(instance);
+            return outputStream;
+        }
+    };
+
+    private StringBuilder builder = new StringBuilder();
+    private final PushStream outStream;
+
+    private CoalescingWrites(PushStream stream) {
+        this.outStream = stream;
+    }
+
+    @Override
+    public void onEmit(Command command) {
+        String text = detectText(command);
+        if (text != null) {
+            builder.append(text);
+        } else {
+            flushText();
+            outStream.emit(command);
+        }
+    }
+
+
+    @Override
+    public void onError(String errorMessage) {
+        flushText();
+        outStream.signalError(errorMessage);
+    }
+
+    @Override
+    public void onDone() {
+        flushText();
+        outStream.signalDone();
+    }
+
+    private String detectText(Command command) {
+        if (command instanceof OutText) {
+            return  ((OutText) command).getText();
+        }
+        return null;
+    }
+
+    private void flushText() {
+        if (builder.length() > 0) {
+            outStream.emit(new OutText(builder.toString()));
+            builder = new StringBuilder();
+        }
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CoalescingWrites.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CommandVariableUsage.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CommandVariableUsage.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CommandVariableUsage.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CommandVariableUsage.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.optimization;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.Command;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandVisitor;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Loop;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.OutText;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Procedure;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.VariableBinding;
+
+/**
+ * Extracts the variables used in a command
+ */
+public class CommandVariableUsage implements CommandVisitor {
+
+    private ArrayList<String> variables = new ArrayList<String>();
+
+    public static List<String> extractVariables(Command command) {
+        CommandVariableUsage cvu = new CommandVariableUsage();
+        command.accept(cvu);
+        return cvu.variables;
+    }
+
+    @Override
+    public void visit(Conditional.Start conditionalStart) {
+        variables.add(conditionalStart.getVariable());
+    }
+
+    @Override
+    public void visit(Conditional.End conditionalEnd) {
+    }
+
+    @Override
+    public void visit(VariableBinding.Start variableBindingStart) {
+        addFromExpression(variableBindingStart.getExpression());
+    }
+
+    @Override
+    public void visit(VariableBinding.End variableBindingEnd) {
+    }
+
+    @Override
+    public void visit(VariableBinding.Global globalAssignment) {
+        addFromExpression(globalAssignment.getExpression());
+    }
+
+    private void addFromExpression(ExpressionNode node) {
+        variables.addAll(VariableFinder.findVariables(node));
+    }
+
+    @Override
+    public void visit(OutVariable outVariable) {
+        variables.add(outVariable.getVariableName());
+    }
+
+    @Override
+    public void visit(OutText outText) {
+    }
+
+    @Override
+    public void visit(Loop.Start loopStart) {
+        variables.add(loopStart.getListVariable());
+    }
+
+    @Override
+    public void visit(Loop.End loopEnd) {
+    }
+
+    @Override
+    public void visit(Procedure.Start startProcedure) {
+    }
+
+    @Override
+    public void visit(Procedure.End endProcedure) {
+    }
+
+    @Override
+    public void visit(Procedure.Call procedureCall) {
+        variables.add(procedureCall.getTemplateVariable());
+        variables.add(procedureCall.getArgumentsVariable());
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/CommandVariableUsage.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/DeadCodeRemoval.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/DeadCodeRemoval.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/DeadCodeRemoval.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/DeadCodeRemoval.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.optimization;
+
+import java.util.Stack;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.BooleanConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.NullLiteral;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.NumericConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.Command;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandStream;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.EmitterVisitor;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.Streams;
+import org.apache.sling.scripting.sightly.impl.compiler.visitor.StatefulRangeIgnore;
+import org.apache.sling.scripting.sightly.impl.compiler.visitor.StatefulVisitor;
+import org.apache.sling.scripting.sightly.impl.compiler.visitor.TrackingVisitor;
+import org.apache.sling.scripting.sightly.render.RenderContext;
+
+/**
+ * Removes code under conditionals which are proven to fail. It is probably
+ * a good idea to run this optimization after running
+ * {@link org.apache.sling.scripting.sightly.impl.compiler.optimization.reduce.ConstantFolding}
+ */
+public class DeadCodeRemoval extends TrackingVisitor<Boolean> implements EmitterVisitor {
+    // this could be merged with constant folding for better accuracy
+
+    public static StreamTransformer transformer(final RenderContext renderContext) {
+        return new StreamTransformer() {
+            @Override
+            public CommandStream transform(CommandStream inStream) {
+                StatefulVisitor visitor = new StatefulVisitor();
+                DeadCodeRemoval dcr = new DeadCodeRemoval(visitor.getControl(), renderContext);
+                visitor.initializeWith(dcr);
+                Streams.connect(inStream, dcr.getOutputStream(), visitor);
+                return dcr.getOutputStream();
+            }
+        };
+    }
+
+    private final PushStream outStream = new PushStream();
+    private final StatefulVisitor.StateControl stateControl;
+    private final RenderContext renderContext;
+    private final Stack<Boolean> keepConditionalEndStack = new Stack<Boolean>();
+
+    public DeadCodeRemoval(StatefulVisitor.StateControl stateControl, RenderContext renderContext) {
+        this.stateControl = stateControl;
+        this.renderContext = renderContext;
+    }
+
+    @Override
+    public void visit(VariableBinding.Start variableBindingStart) {
+        Boolean truthValue = decodeConstantBool(variableBindingStart.getExpression());
+        tracker.pushVariable(variableBindingStart.getVariableName(), truthValue);
+        outStream.emit(variableBindingStart);
+    }
+
+    @Override
+    public void visit(Conditional.Start conditionalStart) {
+        Boolean truthValue = tracker.get(conditionalStart.getVariable());
+        boolean keepConditionalEnd;
+        if (truthValue == null) { //no information about the value of this variable
+            keepConditionalEnd = true;
+            outStream.emit(conditionalStart);
+        } else { //we already know what happens with this conditional. We can remove it
+            keepConditionalEnd = false;
+            if (truthValue != conditionalStart.getExpectedTruthValue()) {
+                //this conditional will always fail. We can ignore everything until
+                //the corresponding end-conditional
+                stateControl.push(new StatefulRangeIgnore(stateControl, Conditional.Start.class, Conditional.End.class));
+                return;
+            }
+        }
+        keepConditionalEndStack.push(keepConditionalEnd);
+    }
+
+    @Override
+    public void visit(Conditional.End conditionalEnd) {
+        boolean keep = keepConditionalEndStack.pop();
+        if (keep) {
+            outStream.emit(conditionalEnd);
+        }
+    }
+
+    @Override
+    public PushStream getOutputStream() {
+        return outStream;
+    }
+
+    @Override
+    protected Boolean assignDefault(Command command) {
+        return null;
+    }
+
+    @Override
+    protected void onCommand(Command command) {
+        outStream.emit(command);
+    }
+
+    private Boolean decodeConstantBool(ExpressionNode node) {
+        if (node instanceof StringConstant) {
+            return renderContext.toBoolean(((StringConstant) node).getText());
+        }
+        if (node instanceof BooleanConstant) {
+            return ((BooleanConstant) node).getValue();
+        }
+        if (node instanceof NumericConstant) {
+            return renderContext.toBoolean(((NumericConstant) node).getValue());
+        }
+        if (node instanceof NullLiteral) {
+            return renderContext.toBoolean(null);
+        }
+        return null;
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/DeadCodeRemoval.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SequenceStreamTransformer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SequenceStreamTransformer.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SequenceStreamTransformer.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SequenceStreamTransformer.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.optimization;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandStream;
+
+/**
+ * Applies a list of transformations in sequence
+ */
+public class SequenceStreamTransformer implements StreamTransformer {
+
+    private List<StreamTransformer> transformers;
+
+    public SequenceStreamTransformer(List<StreamTransformer> transformers) {
+        this.transformers = new ArrayList<StreamTransformer>(transformers);
+    }
+
+    @Override
+    public CommandStream transform(CommandStream inStream) {
+        CommandStream stream = inStream;
+        for (StreamTransformer transformer : transformers) {
+            stream = transformer.transform(stream);
+        }
+        return stream;
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SequenceStreamTransformer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/StreamTransformer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/StreamTransformer.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/StreamTransformer.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/StreamTransformer.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.optimization;
+
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandStream;
+
+/**
+ * Interface for stream transformations
+ */
+public interface StreamTransformer {
+
+    /**
+     * Given the input stream, return a transformed out stream
+     * @param inStream the input stream
+     * @return the result stream
+     */
+    CommandStream transform(CommandStream inStream);
+
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/StreamTransformer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SyntheticMapRemoval.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SyntheticMapRemoval.java?rev=1642281&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SyntheticMapRemoval.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SyntheticMapRemoval.java Fri Nov 28 10:18:01 2014
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.sling.scripting.sightly.impl.compiler.optimization;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.scripting.sightly.impl.compiler.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.NullLiteral;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.PropertyAccess;
+import org.apache.sling.scripting.sightly.impl.compiler.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.Command;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.CommandStream;
+import org.apache.sling.scripting.sightly.impl.compiler.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.impl.compiler.util.expression.NodeTransformer;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.EmitterVisitor;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.impl.compiler.util.stream.Streams;
+import org.apache.sling.scripting.sightly.impl.compiler.visitor.TrackingVisitor;
+
+/**
+ * This optimization handles variables initialized to map literals. It
+ * initially assigns the values in the map to variables and wherever
+ * the map literal is accessed, the property access is replaced with
+ * the value variable, thus removing the need for a map lookup.
+ */
+public final class SyntheticMapRemoval extends TrackingVisitor<MapLiteral> implements EmitterVisitor {
+
+    public static final StreamTransformer TRANSFORMER = new StreamTransformer() {
+        @Override
+        public CommandStream transform(CommandStream inStream) {
+            return Streams.map(inStream, new SyntheticMapRemoval());
+        }
+    };
+
+    private static final String VARIABLE_MARKER = "_field$_";
+
+    private final PushStream outputStream = new PushStream();
+    private final NodeTransformer transformer = new PropertyAccessTransformer();
+
+    private SyntheticMapRemoval() {
+    }
+
+    @Override
+    public void visit(VariableBinding.Start variableBindingStart) {
+        ExpressionNode node = variableBindingStart.getExpression();
+        String variable = variableBindingStart.getVariableName();
+        ExpressionNode transformed = transform(node);
+        if (transformed instanceof MapLiteral) {
+            MapLiteral newLiteral = overrideMap(variable, (MapLiteral) transformed);
+            tracker.pushVariable(variable, newLiteral);
+            transformed = newLiteral;
+        } else {
+            tracker.pushVariable(variable, null);
+        }
+        outputStream.emit(new VariableBinding.Start(variable, transformed));
+    }
+
+    @Override
+    public void visit(VariableBinding.End variableBindingEnd) {
+        Map.Entry<String, MapLiteral> entry = tracker.peek();
+        super.visit(variableBindingEnd);
+        MapLiteral literal = entry.getValue();
+        if (literal != null) {
+            //need to un-bind all the introduced variables
+            for (int i = 0; i < literal.getMap().size(); i++) {
+                outputStream.emit(VariableBinding.END);
+            }
+        }
+    }
+
+    private ExpressionNode transform(ExpressionNode node) {
+        return transformer.transform(node);
+    }
+
+    private MapLiteral overrideMap(String variableName, MapLiteral mapLiteral) {
+        Map<String, ExpressionNode> newLiteral = new HashMap<String, ExpressionNode>();
+        for (Map.Entry<String, ExpressionNode> entry : mapLiteral.getMap().entrySet()) {
+            String property = entry.getKey();
+            ExpressionNode valueNode = entry.getValue();
+            String valueVariable = valueVariableName(variableName, property);
+            newLiteral.put(property, new Identifier(valueVariable));
+            outputStream.emit(new VariableBinding.Start(valueVariable, valueNode));
+        }
+        return new MapLiteral(newLiteral);
+    }
+
+    private String valueVariableName(String variableName, String propertyName) {
+        return variableName + VARIABLE_MARKER + propertyName;
+    }
+
+    @Override
+    protected MapLiteral assignDefault(Command command) {
+        return null;
+    }
+
+    @Override
+    public void onCommand(Command command) {
+        outputStream.emit(command);
+    }
+
+    @Override
+    public PushStream getOutputStream() {
+        return outputStream;
+    }
+
+    private class PropertyAccessTransformer extends NodeTransformer {
+        @Override
+        public ExpressionNode evaluate(PropertyAccess propertyAccess) {
+            ExpressionNode target = propertyAccess.getTarget();
+            String variable = extractIdentifier(target);
+            if (variable != null) {
+                MapLiteral literal = tracker.get(variable);
+                if (literal != null) {
+                    String property = extractProperty(propertyAccess.getProperty());
+                    if (property != null) {
+                        ExpressionNode replacementNode = literal.getValue(property);
+                        if (replacementNode == null) {
+                            replacementNode = NullLiteral.INSTANCE;
+                        }
+                        return replacementNode;
+                    }
+                }
+            }
+            return super.evaluate(propertyAccess);
+        }
+
+        private String extractProperty(ExpressionNode expressionNode) {
+            if (expressionNode instanceof StringConstant) {
+                return ((StringConstant) expressionNode).getText();
+            }
+            return null;
+        }
+
+        private String extractIdentifier(ExpressionNode node) {
+            if (node instanceof Identifier) {
+                return ((Identifier) node).getName();
+            }
+            return null;
+        }
+    }
+}

Propchange: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/optimization/SyntheticMapRemoval.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain