From 84f262401eb07ff42dafdc0081e00cd45388dab5 Mon Sep 17 00:00:00 2001 From: chme Date: Sat, 17 Mar 2018 13:26:08 +0100 Subject: [PATCH] [smartpl.g] Add ORDER BY, LIMIT and HAVING to smart playlist grammar --- src/SMARTPL.g | 44 ++++++++++++++++++++++- src/SMARTPL2SQL.g | 91 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/src/SMARTPL.g b/src/SMARTPL.g index b4b15702..2b16ec29 100644 --- a/src/SMARTPL.g +++ b/src/SMARTPL.g @@ -27,7 +27,26 @@ options { playlist : STR '{' expression '}' EOF ; -expression : aexpr (OR^ aexpr)* +expression : aexpr (OR^ aexpr)* (HAVING^ aexpr)? (ORDERBY^ orderexpr)? (LIMIT^ limitexpr)? + ; + +orderexpr : ordertag SORTDIR + ; + +ordertag : STRTAG + | INTTAG + | DATETAG + | ENUMTAG + | (XXX)? NeverUsedRule + ; + +NeverUsedRule: /* antlr3 seems to have a problem with ordertag, introducing the NeverUsedRule fixes it. See: https://stackoverflow.com/questions/20057063/follow-set-in-is-undefined-in-generated-parser */ + ; + +XXX : 'XXX' /**/ + ; + +limitexpr : INT ; aexpr : nexpr (AND^ nexpr)* @@ -42,6 +61,7 @@ crit : LPAR expression RPAR -> expression | INTTAG INTBOOL INT | DATETAG (AFTER|BEFORE) dateval | ENUMTAG IS ENUMVAL + | GROUPTAG INTBOOL INT ; dateval : DATE @@ -79,6 +99,10 @@ ENUMTAG : 'data_kind' | 'media_kind' ; +GROUPTAG : 'track_count' + | 'album_count' + ; + INCLUDES : 'includes' ; @@ -163,6 +187,24 @@ ENUMVAL : 'music' | 'pipe' ; +ORDERBY : 'order by' + | 'ORDER BY' + ; + +SORTDIR : 'asc' + | 'ASC' + | 'desc' + | 'DESC' + ; + +LIMIT : 'limit' + | 'LIMIT' + ; + +HAVING : 'having' + | 'HAVING' + ; + STR : '"' ~('"')+ '"' ; diff --git a/src/SMARTPL2SQL.g b/src/SMARTPL2SQL.g index c2726ed5..7f317fd4 100644 --- a/src/SMARTPL2SQL.g +++ b/src/SMARTPL2SQL.g @@ -40,8 +40,8 @@ options { @members { } -playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query ] -@init { $title = NULL; $query = NULL; } +playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ] +@init { $title = NULL; $query = NULL; $orderby = NULL; $having = NULL; $limit = -1; } : STR '{' e = expression '}' { pANTLR3_UINT8 val; @@ -56,12 +56,54 @@ playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query ] $query->append8($query, "("); $query->appendS($query, $e.result); $query->append8($query, ")"); + + $limit = $e.limit; + + $orderby = $e.result->factory->newRaw($e.result->factory); + $orderby->appendS($orderby, $e.orderby); + + $having = $e.result->factory->newRaw($e.result->factory); + $having->appendS($having, $e.having); } ; -expression returns [ pANTLR3_STRING result ] -@init { $result = NULL; } - : ^(NOT a = expression) +expression returns [ pANTLR3_STRING result, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ] +@init { $result = NULL; $orderby = NULL; $having = NULL; $limit = -1; } + : ^(LIMIT a = expression INT) + { + $result = $a.result->factory->newRaw($a.result->factory); + $result->appendS($result, $a.result); + + $having = $a.result->factory->newRaw($a.result->factory); + $having->appendS($having, $a.having); + + $orderby = $a.result->factory->newRaw($a.result->factory); + $orderby->appendS($orderby, $a.orderby); + + $limit = atoi((const char *)$INT.text->chars); + } + | ^(ORDERBY a = expression o = ordertag SORTDIR) + { + $result = $a.result->factory->newRaw($a.result->factory); + $result->appendS($result, $a.result); + + $having = $a.result->factory->newRaw($a.result->factory); + $having->appendS($having, $a.having); + + $orderby = $o.result->factory->newRaw($o.result->factory); + $orderby->appendS($orderby, $o.result); + $orderby->append8($orderby, " "); + $orderby->appendS($orderby, $SORTDIR.text->toUTF8($SORTDIR.text)); + } + | ^(HAVING a = expression b = expression) + { + $result = $a.result->factory->newRaw($a.result->factory); + $result->appendS($result, $a.result); + + $having = $b.result->factory->newRaw($b.result->factory); + $having->appendS($having, $b.result); + } + | ^(NOT a = expression) { $result = $a.result->factory->newRaw($a.result->factory); $result->append8($result, "NOT("); @@ -216,6 +258,43 @@ expression returns [ pANTLR3_STRING result ] $result = $ENUMTAG.text->factory->newRaw($ENUMTAG.text->factory); $result->append8($result, str); } + | GROUPTAG INTBOOL INT + { + $result = $GROUPTAG.text->factory->newRaw($GROUPTAG.text->factory); + $result->appendS($result, $GROUPTAG.text->toUTF8($GROUPTAG.text)); + $result->append8($result, " "); + $result->appendS($result, $INTBOOL.text->toUTF8($INTBOOL.text)); + $result->append8($result, " "); + $result->appendS($result, $INT.text->toUTF8($INT.text)); + } + ; + +ordertag returns [ pANTLR3_STRING result ] +@init { $result = NULL; } + : STRTAG + { + $result = $STRTAG.text->factory->newRaw($STRTAG.text->factory); + $result->append8($result, "f."); + $result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text)); + } + | INTTAG + { + $result = $INTTAG.text->factory->newRaw($INTTAG.text->factory); + $result->append8($result, "f."); + $result->appendS($result, $INTTAG.text->toUTF8($INTTAG.text)); + } + | DATETAG + { + $result = $DATETAG.text->factory->newRaw($DATETAG.text->factory); + $result->append8($result, "f."); + $result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text)); + } + | ENUMTAG + { + $result = $ENUMTAG.text->factory->newRaw($ENUMTAG.text->factory); + $result->append8($result, "f."); + $result->appendS($result, $ENUMTAG.text->toUTF8($ENUMTAG.text)); + } ; dateval returns [ int result ] @@ -364,3 +443,5 @@ interval returns [ int result ] } } ; + +