| 1997 | } |
| 1998 | |
| 1999 | int cbm_parse(const cbm_token_t *tokens, int token_count, // NOLINT(misc-no-recursion) |
| 2000 | cbm_parse_result_t *out) { |
| 2001 | memset(out, 0, sizeof(*out)); |
| 2002 | parser_t p = {.tokens = tokens, .count = token_count, .pos = 0}; |
| 2003 | |
| 2004 | /* Check for unsupported leading keywords */ |
| 2005 | const char *unsup = unsupported_clause_error(peek(&p)->type); |
| 2006 | if (unsup) { |
| 2007 | out->error = heap_strdup(unsup); |
| 2008 | return CBM_NOT_FOUND; |
| 2009 | } |
| 2010 | |
| 2011 | cbm_query_t *q = calloc(CBM_ALLOC_ONE, sizeof(cbm_query_t)); |
| 2012 | |
| 2013 | if (check(&p, TOK_UNWIND)) { |
| 2014 | parse_unwind_clause(&p, q); |
| 2015 | } |
| 2016 | |
| 2017 | bool first_optional = false; |
| 2018 | if (check(&p, TOK_OPTIONAL)) { |
| 2019 | advance(&p); |
| 2020 | first_optional = true; |
| 2021 | } |
| 2022 | if (!expect(&p, TOK_MATCH)) { |
| 2023 | out->error = heap_strdup(p.error[0] ? p.error : "expected MATCH"); |
| 2024 | cbm_query_free(q); |
| 2025 | return CBM_NOT_FOUND; |
| 2026 | } |
| 2027 | |
| 2028 | int pat_cap = CYP_INIT_CAP4; |
| 2029 | q->patterns = malloc(pat_cap * sizeof(cbm_pattern_t)); |
| 2030 | q->pattern_optional = malloc(pat_cap * sizeof(bool)); |
| 2031 | |
| 2032 | if (parse_match_pattern(&p, &q->patterns[0]) < 0) { |
| 2033 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse pattern"); |
| 2034 | cbm_query_free(q); |
| 2035 | return CBM_NOT_FOUND; |
| 2036 | } |
| 2037 | q->pattern_optional[0] = first_optional; |
| 2038 | q->pattern_count = SKIP_ONE; |
| 2039 | |
| 2040 | if (parse_match_chain(&p, q, &pat_cap) < 0) { |
| 2041 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse additional pattern"); |
| 2042 | cbm_query_free(q); |
| 2043 | return CBM_NOT_FOUND; |
| 2044 | } |
| 2045 | |
| 2046 | if (parse_where(&p, &q->where) < 0) { |
| 2047 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse WHERE"); |
| 2048 | cbm_query_free(q); |
| 2049 | return CBM_NOT_FOUND; |
| 2050 | } |
| 2051 | |
| 2052 | if (parse_post_where(&p, q, &pat_cap) < 0) { |
| 2053 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse query"); |
| 2054 | cbm_query_free(q); |
| 2055 | return CBM_NOT_FOUND; |
| 2056 | } |
no test coverage detected