blob: 4c73a2cfd7fa84fd06805c0a53c4ef4cda6a5cca [file] [log] [blame]
/*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
options
{
STATIC = false;
UNICODE_INPUT = true;
}
PARSER_BEGIN(FilterParser)
package org.apache.sling.resource.filter.impl;
import java.util.ArrayList;
import java.util.List;
import org.apache.sling.resource.filter.impl.node.*;
public final class FilterParser
{
}
PARSER_END(FilterParser)
SKIP :
{
" "
| "\t"
}
TOKEN :
{
< #PLUS: "+" >
| < #MINUS: "-" >
| < #DIGIT: [ "0"-"9" ] >
| < #EXP: ["e","E"] ( < PLUS > | < MINUS > )? >
| < #OFFSET: ["+","-"]["0"-"2"] <DIGIT> ":" ["0"-"5"] <DIGIT> >
| < #YYYYMMDD: <INTEGER> <INTEGER> <INTEGER> <INTEGER> <MINUS> ["0"-"1"] <INTEGER> <MINUS> ["0"-"3"] <DIGIT> >
| < #TIME: ["0"-"2"] <DIGIT> ":" ["0"-"5"] <DIGIT> ( ":" ["0"-"5"] <DIGIT> ("." <DIGIT> <DIGIT> <DIGIT>)? )? >
| < OFFSETDATETIME: <YYYYMMDD> "T" <TIME> <OFFSET> >
| < DATETIME: <YYYYMMDD> "T" <TIME> >
| < DATE: <YYYYMMDD> >
| < NUMBER: <INTEGER> | <INTEGER> <FRACTIONAL_DIGITS> | <INTEGER> <EXPONENT> | <INTEGER> <FRACTIONAL_DIGITS> <EXPONENT> >
| < INTEGER: (<MINUS>)? ( <DIGITS> ) >
| < FRACTIONAL_DIGITS: "." <DIGITS> >
| < EXPONENT: <EXP> <DIGITS> >
| < DIGITS: ( <DIGIT> )+ >
}
TOKEN :
{
< STRING : < SQUOTE > | < DQUOTE > >{matchedToken.image = image.substring(1, lengthOfMatch - 1);}
| < #SQUOTE :
(
"'"
( "\\" ~[ ] | ~[ "'", "\\" ] )*
"'"
) >
| < #DQUOTE :
(
"\""
( "\\" ~[ ] | ~[ "\"", "\\" ] )*
"\""
) >
}
TOKEN :
{
< AND :
(
"&&"
| "and"
) >
| < OR :
(
"||"
| "or"
) >
| < NULL : "null" >
| < LPAREN : "(" >
| < RPAREN : ")" >
| < COMMA : "," >
| < BOOLEAN: "true" | "false" >
| < EQUAL : "==" | "is" >
| < NOT_EQUAL : "!=" | "is not" >
| < GREATER_THAN : ">" | "greater than" >
| < GREATER_THAN_OR_EQUAL : ">=" >
| < LESS_THAN : "<" | "less than" >
| < LESS_THAN_OR_EQUAL : "<=" >
| < LIKE : "~=" | "like" >
| < LIKE_NOT : "like not" | "not like" >
| < CONTAINS : "contains" >
| < CONTAINS_NOT : "contains not" >
| < CONTAINS_ANY : "contains any" >
| < CONTAINS_NOT_ANY : "contains not any" >
| < IN : "in" >
| < NOT_IN : "not in" >
| < DYNAMIC_ARG : "$" >
| < FUNCTION_NAME : (~[ "\"", "'", "$", "(", ")", ",", "=", "<", ">", " ", "[", "]","+","-",".","0"-"9" ])+ >
| < PROPERTY: "[" ( "\\" ~[ ] | ~[ "]", "\\" ] )* "]" >{matchedToken.image = image.substring(1, lengthOfMatch - 1);}
}
<*> TOKEN : { <UNKNOWN: ~[]> }
Node parse() :
{
final Node node;
}
{
node = or() < EOF >
{
return node;
}
}
Node or() :
{
final List < Node > nodes = new ArrayList < Node > (3);
Node node;
}
{
node = and()
{
nodes.add(node);
}
(
< OR > node = and()
{
nodes.add(node);
}
)*
{
return nodes.size() != 1 ? new Node(FilterParserConstants.OR, nodes) : nodes.get(0);
}
}
Node and() :
{
final List < Node > nodes = new ArrayList < Node > (3);
Node node;
}
{
node = constraint()
{
nodes.add(node);
}
(
< AND > node = constraint()
{
nodes.add(node);
}
)*
{
return nodes.size() != 1 ? new Node(FilterParserConstants.AND, nodes) : nodes.get(0);
}
}
Node constraint() :
{
final Node node;
}
{
(
node = group()
| node = comparison()
)
{
return node;
}
}
Node group() :
{
final Node node;
}
{
< LPAREN > node = or() < RPAREN >
{
return node;
}
}
Node comparison() :
{
Node leftValue;
Token op;
Node rightValue;
}
{
leftValue = argument()
op = comparisonValue()
rightValue = argument()
{
return new Node(op.kind, op.image, leftValue, rightValue);
}
}
Token comparisonValue() :
{
}
{
(
< EQUAL >
| < NOT_EQUAL >
| < GREATER_THAN >
| < GREATER_THAN_OR_EQUAL >
| < LESS_THAN >
| < LESS_THAN_OR_EQUAL >
| < LIKE >
| < LIKE_NOT >
| < CONTAINS >
| < CONTAINS_NOT >
| < CONTAINS_ANY >
| < CONTAINS_NOT_ANY >
| < IN >
| < NOT_IN >
)
{
return token;
}
}
List < Node > Arguments() :
{
Object value = new ArrayList();
}
{
< LPAREN > [ value = commaSepArguments() ] < RPAREN >
{
return (List) value;
}
}
List < Node > commaSepArguments() :
{
final List < Node > list = new ArrayList < Node > (3);
Node arg;
}
{
arg = argument()
{
list.add(arg);
}
(
< COMMA >
arg = argument()
{
list.add(arg);
}
)*
{
return list;
}
}
Node argument() :
{
Node selector = null;
}
{
(
selector = literal()
| selector = property()
| selector = dynamicArg()
| selector = function()
)
{
return selector;
}
}
Node function() :
{
String functionName = null;
List < Node > children = null;
}
{
< FUNCTION_NAME >
{
functionName = token.image;
}
< LPAREN > [ children = commaSepArguments() ] < RPAREN >
{
return new Node(FilterParserConstants.FUNCTION_NAME, functionName, children);
}
}
Node dynamicArg() :
{
String functionName = null;
}
{
< DYNAMIC_ARG >< FUNCTION_NAME >
{
functionName = token.image;
return new Node(FilterParserConstants.DYNAMIC_ARG, functionName);
}
}
Node literal() :
{
}
{
(
< STRING >
| < NUMBER >
| < NULL >
| < BOOLEAN >
| < DATE >
| < DATETIME >
| < OFFSETDATETIME >
)
{
return new Node(token.kind, token.image);
}
}
Node property() :
{
}
{
< PROPERTY >
{
return new Node(token.kind, token.image);
}
}