/* * Copyright (C) 2015 Christian Meffert * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ tree grammar SMARTPL2SQL; options { tokenVocab = SMARTPL; ASTLabelType = pANTLR3_BASE_TREE; language = C; } @header { #include #include #include #include #include #include #include #include "logger.h" } @members { } playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query ] @init { $title = NULL; $query = NULL; } : STR '{' e = expression '}' { pANTLR3_UINT8 val; val = $STR.text->toUTF8($STR.text)->chars; val++; val[strlen((const char *)val) - 1] = '\0'; $title = $STR.text->factory->newRaw($STR.text->factory); $title->append8($title, (const char *)val); $query = $e.result->factory->newRaw($e.result->factory); $query->append8($query, "("); $query->appendS($query, $e.result); $query->append8($query, ")"); } ; expression returns [ pANTLR3_STRING result ] @init { $result = NULL; } : ^(NOT a = expression) { $result = $a.result->factory->newRaw($a.result->factory); $result->append8($result, "NOT("); $result->appendS($result, $a.result); $result->append8($result, ")"); } | ^(AND a = expression b = expression) { $result = $a.result->factory->newRaw($a.result->factory); $result->append8($result, "("); $result->appendS($result, $a.result); $result->append8($result, " AND "); $result->appendS($result, $b.result); $result->append8($result, ")"); } | ^(OR a = expression b = expression) { $result = $a.result->factory->newRaw($a.result->factory); $result->append8($result, "("); $result->appendS($result, $a.result); $result->append8($result, " OR "); $result->appendS($result, $b.result); $result->append8($result, ")"); } | STRTAG INCLUDES STR { pANTLR3_UINT8 val; val = $STR.text->toUTF8($STR.text)->chars; val++; val[strlen((const char *)val) - 1] = '\0'; $result = $STR.text->factory->newRaw($STR.text->factory); $result->append8($result, "f."); $result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text)); $result->append8($result, " LIKE '\%"); $result->append8($result, sqlite3_mprintf("\%q", (const char *)val)); $result->append8($result, "\%'"); } | STRTAG IS STR { pANTLR3_UINT8 val; val = $STR.text->toUTF8($STR.text)->chars; val++; val[strlen((const char *)val) - 1] = '\0'; $result = $STR.text->factory->newRaw($STR.text->factory); $result->append8($result, "f."); $result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text)); $result->append8($result, " = '"); $result->append8($result, sqlite3_mprintf("\%q", (const char *)val)); $result->append8($result, "'"); } | INTTAG INTBOOL INT { $result = $INTTAG.text->factory->newRaw($INTTAG.text->factory); $result->append8($result, "f."); $result->appendS($result, $INTTAG.text->toUTF8($INTTAG.text)); $result->append8($result, " "); $result->appendS($result, $INTBOOL.text->toUTF8($INTBOOL.text)); $result->append8($result, " "); $result->appendS($result, $INT.text->toUTF8($INT.text)); } | DATETAG AFTER dateval { char str[15]; sprintf(str, "\%d", $dateval.result); $result = $DATETAG.text->factory->newRaw($DATETAG.text->factory); $result->append8($result, "f."); $result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text)); $result->append8($result, " > "); $result->append8($result, str); } | DATETAG BEFORE dateval { char str[15]; sprintf(str, "\%d", $dateval.result); $result = $DATETAG.text->factory->newRaw($DATETAG.text->factory); $result->append8($result, "f."); $result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text)); $result->append8($result, " > "); $result->append8($result, str); } ; dateval returns [ int result ] @init { $result = 0; } : DATE { pANTLR3_UINT8 datval; datval = $DATE.text->chars; if (strcmp((char *)datval, "today") == 0) { $result = time(NULL); } else if (strcmp((char *)datval, "yesterday") == 0) { $result = time(NULL) - 24 * 3600; } else if (strcmp((char *)datval, "last week") == 0) { $result = time(NULL) - 24 * 3600 * 7; } else if (strcmp((char *)datval, "last month") == 0) { $result = time(NULL) - 24 * 3600 * 30; } else if (strcmp((char *)datval, "last year") == 0) { $result = time(NULL) - 24 * 3600 * 365; } else { struct tm tm; char year[5]; char month[3]; char day[3]; memset((void*)&tm,0,sizeof(tm)); memset(year, 0, sizeof(year)); memset(month, 0, sizeof(month)); memset(day, 0, sizeof(day)); strncpy(year, (const char *)datval, 4); strncpy(month, (const char *)datval + 5, 2); strncpy(day, (const char *)datval + 8, 2); tm.tm_year = atoi(year) - 1900; tm.tm_mon = atoi(month) - 1; tm.tm_mday = atoi(day); $result = mktime(&tm); } } | interval BEFORE DATE { pANTLR3_UINT8 datval; datval = $DATE.text->chars; if (strcmp((char *)datval, "yesterday") == 0) { $result = time(NULL) - 24 * 3600; } else if (strcmp((char *)datval, "last week") == 0) { $result = time(NULL) - 24 * 3600 * 7; } else if (strcmp((char *)datval, "last month") == 0) { $result = time(NULL) - 24 * 3600 * 30; } else if (strcmp((char *)datval, "last year") == 0) { $result = time(NULL) - 24 * 3600 * 365; } else { $result = time(NULL); } $result = $result - $interval.result; } | interval AFTER DATE { pANTLR3_UINT8 datval; datval = $DATE.text->chars; if (strcmp((char *)datval, "yesterday") == 0) { $result = time(NULL) - 24 * 3600; } else if (strcmp((char *)datval, "last week") == 0) { $result = time(NULL) - 24 * 3600 * 7; } else if (strcmp((char *)datval, "last month") == 0) { $result = time(NULL) - 24 * 3600 * 30; } else if (strcmp((char *)datval, "last year") == 0) { $result = time(NULL) - 24 * 3600 * 365; } else { $result = time(NULL); } $result = $result + $interval.result; } | interval AGO { $result = time(NULL) - $interval.result; } ; interval returns [ int result ] @init { $result = 0; } : INT DATINTERVAL { pANTLR3_UINT8 interval; $result = atoi((const char *)$INT.text->chars); interval = $DATINTERVAL.text->chars; if (strcmp((char *)interval, "days") == 0) { $result = $result * 24 * 3600; } else if (strcmp((char *)interval, "weeks") == 0) { $result = $result * 24 * 3600 * 7; } else if (strcmp((char *)interval, "months") == 0) { $result = $result * 24 * 3600 * 30; } else if (strcmp((char *)interval, "weeks") == 0) { $result = $result * 24 * 3600 * 365; } else { $result = 0; } } ;