| 1838 | } |
| 1839 | |
| 1840 | int cbm_parse(const cbm_token_t *tokens, int token_count, // NOLINT(misc-no-recursion) |
| 1841 | cbm_parse_result_t *out) { |
| 1842 | memset(out, 0, sizeof(*out)); |
| 1843 | parser_t p = {.tokens = tokens, .count = token_count, .pos = 0}; |
| 1844 | |
| 1845 | /* Check for unsupported leading keywords */ |
| 1846 | const char *unsup = unsupported_clause_error(peek(&p)->type); |
| 1847 | if (unsup) { |
| 1848 | out->error = heap_strdup(unsup); |
| 1849 | return CBM_NOT_FOUND; |
| 1850 | } |
| 1851 | |
| 1852 | cbm_query_t *q = calloc(CBM_ALLOC_ONE, sizeof(cbm_query_t)); |
| 1853 | |
| 1854 | if (check(&p, TOK_UNWIND)) { |
| 1855 | parse_unwind_clause(&p, q); |
| 1856 | } |
| 1857 | |
| 1858 | bool first_optional = false; |
| 1859 | if (check(&p, TOK_OPTIONAL)) { |
| 1860 | advance(&p); |
| 1861 | first_optional = true; |
| 1862 | } |
| 1863 | if (!expect(&p, TOK_MATCH)) { |
| 1864 | out->error = heap_strdup(p.error[0] ? p.error : "expected MATCH"); |
| 1865 | cbm_query_free(q); |
| 1866 | return CBM_NOT_FOUND; |
| 1867 | } |
| 1868 | |
| 1869 | int pat_cap = CYP_INIT_CAP4; |
| 1870 | q->patterns = malloc(pat_cap * sizeof(cbm_pattern_t)); |
| 1871 | q->pattern_optional = malloc(pat_cap * sizeof(bool)); |
| 1872 | |
| 1873 | if (parse_match_pattern(&p, &q->patterns[0]) < 0) { |
| 1874 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse pattern"); |
| 1875 | cbm_query_free(q); |
| 1876 | return CBM_NOT_FOUND; |
| 1877 | } |
| 1878 | q->pattern_optional[0] = first_optional; |
| 1879 | q->pattern_count = SKIP_ONE; |
| 1880 | |
| 1881 | if (parse_match_chain(&p, q, &pat_cap) < 0) { |
| 1882 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse additional pattern"); |
| 1883 | cbm_query_free(q); |
| 1884 | return CBM_NOT_FOUND; |
| 1885 | } |
| 1886 | |
| 1887 | if (parse_where(&p, &q->where) < 0) { |
| 1888 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse WHERE"); |
| 1889 | cbm_query_free(q); |
| 1890 | return CBM_NOT_FOUND; |
| 1891 | } |
| 1892 | |
| 1893 | if (parse_post_where(&p, q, &pat_cap) < 0) { |
| 1894 | out->error = heap_strdup(p.error[0] ? p.error : "failed to parse query"); |
| 1895 | cbm_query_free(q); |
| 1896 | return CBM_NOT_FOUND; |
| 1897 | } |
no test coverage detected