Moved MPRIS to a new project
[stereo.git] / DAAPLib / src / util / queryparser / QueryParser.java
blob08541211cb6ed8164c3b794370da3d56e75f49c1
1 package util.queryparser;
3 import java.io.UnsupportedEncodingException;
4 import java.net.URLDecoder;
6 import org.codehaus.jparsec.OperatorTable;
7 import org.codehaus.jparsec.Parser;
8 import org.codehaus.jparsec.Parsers;
9 import org.codehaus.jparsec.Scanners;
10 import org.codehaus.jparsec.Terminals;
11 import org.codehaus.jparsec.functors.Binary;
12 import org.codehaus.jparsec.functors.Map;
13 import org.codehaus.jparsec.pattern.Patterns;
15 public class QueryParser {
17 private enum BinaryOperator implements Binary<Filter> {
18 AND {
19 public Filter map(Filter a, Filter b) {
20 return new And(a, b);
23 OR {
24 public Filter map(Filter a, Filter b) {
25 return new Or(a, b);
30 public static final Parser<String> SINGLE_QUOTE_STRING =
31 Scanners.pattern(Patterns.regex("((\\\\.)|[^\'\\\\])*") ,"quoted string").between(
32 Scanners.isChar('\''),
33 Scanners.isChar('\'')
34 ).source();
35 public static final Map<String, String> SINGLE_QUOTE_STRING_MAP = new Map<String, String>() {
36 public String map(String text) {
37 return text.substring(1, text.length()-1).replace("\\'", "'");
39 @Override public String toString() {
40 return "SINGLE_QUOTE_STRING";
44 private static final Parser<Filter> TOKEN = Terminals.StringLiteral.PARSER.map(new org.codehaus.jparsec.functors.Map<String, Filter>() {
45 public Token map(String s) {
46 return new Token(s);
48 });
50 private static final Terminals OPERATORS = Terminals.operators("+", ",", "(", ")");
52 private static final Parser<Object> TOKENIZER =
53 Parsers.or(SINGLE_QUOTE_STRING.map(SINGLE_QUOTE_STRING_MAP), OPERATORS.tokenizer());
55 private static Parser<?> term(String... names) {
56 return OPERATORS.token(names);
59 private static <T> Parser<T> op(String name, T value) {
60 return term(name).retn(value);
63 private static Parser<Filter> query(Parser<Filter> atom) {
64 Parser.Reference<Filter> ref = Parser.newReference();
65 Parser<Filter> unit = ref.lazy().between(term("("), term(")")).or(atom);
66 Parser<Filter> parser = new OperatorTable<Filter>()
67 .infixl(op(",", BinaryOperator.OR), 10)
68 .infixl(op("+", BinaryOperator.AND), 20)
69 .build(unit);
70 ref.set(parser);
71 return parser;
74 private static Parser<Void> nodelim = Parsers.always();
76 private static final Parser<Filter> parser = query(TOKEN).from(TOKENIZER, nodelim);
78 public static Filter parse(String source) {
79 /*String decoded = "";
80 char[] chars = source.toCharArray();
81 for (int i = 0; i < chars.length; i++) {
82 if (chars[i] == '%') {
83 int a = chars[++i];
84 int b = chars[++i];
85 if (a >= 'A') a = a-'A';
86 else a = a-'0';
87 if (b >= 'A') b = b-'A';
88 else b = b-'0';
89 decoded += (char)(16*a+b);
91 decoded += chars[i];
92 }*/
93 source = source.replace("+", "%2B");
94 try {
95 source = URLDecoder.decode(source, "UTF-8");
96 } catch (UnsupportedEncodingException e) {
97 e.printStackTrace();
99 System.out.println(source);
100 return parser.parse(source);
103 public static void main(String args[]) {
104 //System.out.println(SINGLE_QUOTE_STRING.parse("'foo'"));
105 System.out.println(QueryParser.parse("'hi: bye'+'ho!:bo+ o\\\'n'"));