[tracker/wip/carlosg/sparql-parser-ng: 27/43] libtracker-data: Fix handling of fn:string-join



commit f834b2c0339ecf48620e2ed58aae62cc445f95c2
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Sep 23 11:55:25 2018 +0200

    libtracker-data: Fix handling of fn:string-join
    
    In a quite unstandard way, this function takes the list of strings
    to join surrounded by parentheses, eg. fn:string-join(('a', 'b'), '|').
    Handle this through allowing nesting of ArgList for this case, it will
    error out in every other case.

 src/libtracker-data/tracker-sparql-grammar.h |  8 +++++++-
 src/libtracker-data/tracker-sparql.c         | 16 ++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)
---
diff --git a/src/libtracker-data/tracker-sparql-grammar.h b/src/libtracker-data/tracker-sparql-grammar.h
index c74eb4401..d6baf45f9 100644
--- a/src/libtracker-data/tracker-sparql-grammar.h
+++ b/src/libtracker-data/tracker-sparql-grammar.h
@@ -1078,11 +1078,17 @@ static const TrackerGrammarRule helper_ExpressionList_or[] = { T(NIL), S(helper_
 static const TrackerGrammarRule rule_ExpressionList[] = { OR(helper_ExpressionList_or), NIL };
 
 /* ArgList ::= NIL | '(' 'DISTINCT'? Expression ( ',' Expression )* ')'
+ *
+ * TRACKER EXTENSION:
+ * First argument may be an ArgList in itself for fn:string-join, resulting in:
+ * ( ArgList | 'DISTINCT'? Expression )
  */
 static const TrackerGrammarRule helper_ArgList_seq_1[] = { L(COMMA), R(Expression), NIL };
 static const TrackerGrammarRule helper_ArgList_gte0[] = { S(helper_ArgList_seq_1), NIL };
 static const TrackerGrammarRule helper_ArgList_opt[] = { L(DISTINCT), NIL };
-static const TrackerGrammarRule helper_ArgList_seq_2[] = {  L(OPEN_PARENS), OPT(helper_ArgList_opt), 
R(Expression), GTE0(helper_ArgList_gte0), L(CLOSE_PARENS), NIL };
+static const TrackerGrammarRule helper_ArgList_seq_3[] = { OPT(helper_ArgList_opt), R(Expression), NIL };
+static const TrackerGrammarRule helper_ArgList_or_2[] = { S(helper_ArgList_seq_3), R(ArgList), NIL };
+static const TrackerGrammarRule helper_ArgList_seq_2[] = {  L(OPEN_PARENS), OR(helper_ArgList_or_2), 
GTE0(helper_ArgList_gte0), L(CLOSE_PARENS), NIL };
 static const TrackerGrammarRule helper_ArgList_or[] = { T(NIL), S(helper_ArgList_seq_2), NIL };
 static const TrackerGrammarRule rule_ArgList[] = { OR(helper_ArgList_or), NIL };
 
diff --git a/src/libtracker-data/tracker-sparql.c b/src/libtracker-data/tracker-sparql.c
index da7dd8506..a962bb439 100644
--- a/src/libtracker-data/tracker-sparql.c
+++ b/src/libtracker-data/tracker-sparql.c
@@ -3553,6 +3553,9 @@ translate_ArgList (TrackerSparql  *sparql,
         */
        if (_accept (sparql, RULE_TYPE_TERMINAL, TERMINAL_TYPE_NIL)) {
        } else if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_OPEN_PARENS)) {
+               if (_check_in_rule (sparql, NAMED_RULE_ArgList))
+                       _raise (PARSE, "Recursive ArgList is not allowed", "ArgList");
+
                if (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_DISTINCT)) {
                        _unimplemented ("DISTINCT in ArgList");
                }
@@ -4870,7 +4873,20 @@ handle_xpath_function (TrackerSparql  *sparql,
                sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_STRING;
        } else if (g_str_equal (function, FN_NS "string-join")) {
                _append_string (sparql, "SparqlStringJoin (");
+               _step (sparql);
+               _expect (sparql, RULE_TYPE_LITERAL, LITERAL_OPEN_PARENS);
+
+               if (!_check_in_rule (sparql, NAMED_RULE_ArgList))
+                       _raise (PARSE, "List of strings to join must be surrounded by parentheses", 
"fn:string-join");
+
                _call_rule (sparql, NAMED_RULE_ArgList, error);
+
+               while (_accept (sparql, RULE_TYPE_LITERAL, LITERAL_COMMA)) {
+                       _append_string (sparql, ", ");
+                       _call_rule (sparql, NAMED_RULE_Expression, error);
+               }
+
+               _expect (sparql, RULE_TYPE_LITERAL, LITERAL_CLOSE_PARENS);
                _append_string (sparql, ") ");
                sparql->current_state.expression_type = TRACKER_PROPERTY_TYPE_STRING;
        } else if (g_str_equal (function, FN_NS "replace")) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]