Archive / / / / / Echo.Query.Expression.vala.txt
2008-12-04 19:23:35 UTC
previous next
/* vim: set noexpandtab tabstop=4 shiftwidth=4 nowrap textwidth=100 * * Echo Media Player * Copyright (C) 2008 Shane O'Connell * * [ The original file includes a copyright header in this location describing * the file as being released under the terms of the GNU General Public * License. It has been removed in order to display the file as part of the * archive. ] */ using Echo.Interfaces; public abstract class Echo.Query.Expression : GLib.Object { public static Expression? create_from_string(string str) { assert(str != null); var tokens = new GLib.SList<string>(); int ch = 0; while (ch < str.length) { // Skip whitespace while (ch < str.length && str[ch] == ' ') str++; if (ch >= str.length) break; // Get a token switch (str[ch]) { case '(': case ')': case '-': case ':': tokens.append(str[ch]); ch++; break; case '"': ch++; if (ch >= str.length) break; int start = ch; while (ch < str.length && str[ch] != '"') ch++; tokens.append(str.substring(start, ch - start)); if (ch < str.length) ch++; break; default: int start = ch; while (ch < str.length && str[ch] != ' ' && str[ch] != '"' && str[ch] != '(' && str[ch] != ')' && str[ch] != ':') ch++; tokens.append(str.substring(start, ch - start)); break; } } string[] array_tokens = new string[tokens.length()]; int i = 0; foreach (string token in tokens) array_tokens[i++] = token; return create_from_tokens(array_tokens, 0, array_tokens.length); } private static Expression? create_from_tokens(string[] tokens, int offset, int stop_offset) { if (offset >= stop_offset) return null; // There's nothing else in this expression (maybe an unfinished AND/OR?) // Get the left side of this assumed binary expression Expression left_expression = parse_left_expression(tokens, ref offset); // If there's nothing else then this wasn't a binary expression if (offset >= stop_offset) return left_expression; switch (tokens[offset]) { case "OR": return new OrExpression(left_expression, create_from_tokens(tokens, offset + 1, stop_offset)); case "AND": return new AndExpression(left_expression, create_from_tokens(tokens, offset + 1, stop_offset)); default: return new AndExpression(left_expression, create_from_tokens(tokens, offset, stop_offset)); } } private static Expression parse_left_expression(string[] tokens, ref int offset) { if (tokens[offset] == "(") { offset++; int nest_count = 0; for (int stop_offset = offset; stop_offset < tokens.length; stop_offset++) { if (tokens[stop_offset] == "(") nest_count++; if (tokens[stop_offset] == ")") if (nest_count == 0) return create_from_tokens(tokens, offset, stop_offset); else nest_count--; } return create_from_tokens(tokens, offset, tokens.length); } if (tokens[offset] == "-" || tokens[offset] == "NOT") { offset++; // Skip the - or NOT return new NotExpression(parse_left_expression(tokens, ref offset)); } if ((offset + 1) < tokens.length && tokens[offset + 1] == ':') { switch (tokens[offset]) { case "rating": return new RatingExpression(tokens, ref offset); case "artist": return new ArtistMatchExpression(tokens, ref offset); case "album": return new AlbumMatchExpression(tokens, ref offset); default: // Skip the unknown thing offset += 2; return new MatchExpression(tokens, ref offset); } } else return new MatchExpression(tokens, ref offset); } public bool evaluate_for_track(ITrack track) { } }