<commit_before>%{
#include "sqli.h"

static void
sqli_parser_error(struct sqli_detect_ctx *ctx, const char *s)
{
    ctx->res.parse_error = true;
}

%}

%define api.pure full
%define api.push-pull push
%define api.prefix {sqli_parser_}
%parse-param {struct sqli_detect_ctx *ctx}
%union {
    struct sqli_token_arg_data data;
}
%define lr.type lalr

%type <data> data_name
%type <data> operator command
%type <data> join_type
%type <data> select_extra_tk
%type <data> union_tk
%type <data> func_args_modifier_tk
%type <data> post_expr_tk
%type <data> delete_modifier
%type <data> load_modifier data_xml

%token TOK_START_DATA
%token TOK_START_STRING
%token TOK_START_RCE
%token <data> TOK_DISTINCT TOK_VARIADIC
%token <data> TOK_DATA TOK_NAME TOK_OPERATOR
%token <data> '.' ',' '(' ')' '*' '[' ']' ';' '=' ':'
%token <data> TOK_OR TOK_AND TOK_IS TOK_NOT TOK_DIV
              TOK_MOD TOK_XOR TOK_REGEXP
              TOK_BINARY TOK_SOUNDS TOK_OUTFILE TOK_MATCH TOK_AGAINST TOK_EXIST
%token <data> TOK_COLLATE TOK_UESCAPE
%token <data> TOK_FOR
%token <data> TOK_FROM TOK_INTO TOK_WHERE
%token <data> TOK_AS TOK_ON TOK_USING
%token <data> TOK_UNION TOK_INTERSECT TOK_EXCEPT TOK_ALL
%token <data> TOK_ORDER TOK_GROUP TOK_BY TOK_HAVING
%token <data> TOK_TOP TOK_PERCENT
%token <data> TOK_DESC TOK_ASC
%token <data> TOK_CROSS TOK_FULL TOK_INNER TOK_LEFT TOK_RIGHT
%token <data> TOK_LIMIT TOK_OFFSET
%token <data> TOK_NATURAL TOK_JOIN
%token <data> TOK_SELECT TOK_UPDATE TOK_INSERT TOK_EXECUTE TOK_DELETE
%token <data> TOK_ATTACH
%token <data> TOK_DROP
%token <data> TOK_COMMA
%token <data> TOK_SET
%token <data> TOK_BETWEEN TOK_LIKE TOK_RLIKE TOK_IN TOK_BOOLEAN TOK_MODE
%token <data> TOK_CASE TOK_WHEN TOK_THEN TOK_ELSE TOK_BEGIN TOK_END
%token <data> TOK_WAITFOR TOK_DELAY TOK_TIME
%token <data> TOK_CREATE TOK_REPLACE TOK_FUNCTION TOK_RETURNS TOK_LANGUAGE TOK_STRICT
%token <data> TOK_SHUTDOWN
%token <data> TOK_DECLARE
%token <data> TOK_TABLE TOK_DATABASE
%token <data> TOK_USE
%token <data> TOK_WHILE
%token <data> TOK_IGNORE TOK_LOW_PRIORITY TOK_QUICK
%token <data> TOK_PRINT
%token <data> TOK_LOAD TOK_DATA2 TOK_XML TOK_CONCURRENT TOK_LOCAL TOK_INFILE
%token <data> TOK_PROCEDURE
%token <data> TOK_GOTO
%token <data> TOK_CALL
%token <data> TOK_CURSOR
%token <data> TOK_PATH
%token <data> TOK_VALUES
%token <data> TOK_OPEN
%token <data> TOK_OVER
%token <data> TOK_WITHIN
%token <data> TOK_ALTER TOK_RECOVERY TOK_SIMPLE
%token <data> TOK_LOCK TOK_SHARE
%token <data> TOK_IF
%token TOK_FUNC
%token TOK_ERROR

%destructor {
    sqli_token_data_destructor(&$$);
} <data>

%%

context:  start_data
        | start_string
        | start_rce
        ;

start_data: TOK_START_DATA data_cont
        | TOK_START_DATA expr post_exprs_opt ','[u1] data_cont {
            YYUSE($u1);
        }
        ;

start_string: TOK_START_STRING {
            ctx->lexer.instring = true;
        } data_cont
        ;

data_name:  TOK_DATA
        |   TOK_NAME
        |   TOK_DATA2
        /* Tokens-as-identifiers here */
        ;
<commit_msg>strings placed next to each other are concatenated<commit_after>%{
#include "sqli.h"

static void
sqli_parser_error(struct sqli_detect_ctx *ctx, const char *s)
{
    ctx->res.parse_error = true;
}

%}

%define api.pure full
%define api.push-pull push
%define api.prefix {sqli_parser_}
%parse-param {struct sqli_detect_ctx *ctx}
%union {
    struct sqli_token_arg_data data;
}
%define lr.type lalr

%type <data> data data_name
%type <data> operator command
%type <data> join_type
%type <data> select_extra_tk
%type <data> union_tk
%type <data> func_args_modifier_tk
%type <data> post_expr_tk
%type <data> delete_modifier
%type <data> load_modifier data_xml

%token TOK_START_DATA
%token TOK_START_STRING
%token TOK_START_RCE
%token <data> TOK_DISTINCT TOK_VARIADIC
%token <data> TOK_DATA TOK_NAME TOK_OPERATOR
%token <data> '.' ',' '(' ')' '*' '[' ']' ';' '=' ':'
%token <data> TOK_OR TOK_AND TOK_IS TOK_NOT TOK_DIV
              TOK_MOD TOK_XOR TOK_REGEXP
              TOK_BINARY TOK_SOUNDS TOK_OUTFILE TOK_MATCH TOK_AGAINST TOK_EXIST
%token <data> TOK_COLLATE TOK_UESCAPE
%token <data> TOK_FOR
%token <data> TOK_FROM TOK_INTO TOK_WHERE
%token <data> TOK_AS TOK_ON TOK_USING
%token <data> TOK_UNION TOK_INTERSECT TOK_EXCEPT TOK_ALL
%token <data> TOK_ORDER TOK_GROUP TOK_BY TOK_HAVING
%token <data> TOK_TOP TOK_PERCENT
%token <data> TOK_DESC TOK_ASC
%token <data> TOK_CROSS TOK_FULL TOK_INNER TOK_LEFT TOK_RIGHT
%token <data> TOK_LIMIT TOK_OFFSET
%token <data> TOK_NATURAL TOK_JOIN
%token <data> TOK_SELECT TOK_UPDATE TOK_INSERT TOK_EXECUTE TOK_DELETE
%token <data> TOK_ATTACH
%token <data> TOK_DROP
%token <data> TOK_COMMA
%token <data> TOK_SET
%token <data> TOK_BETWEEN TOK_LIKE TOK_RLIKE TOK_IN TOK_BOOLEAN TOK_MODE
%token <data> TOK_CASE TOK_WHEN TOK_THEN TOK_ELSE TOK_BEGIN TOK_END
%token <data> TOK_WAITFOR TOK_DELAY TOK_TIME
%token <data> TOK_CREATE TOK_REPLACE TOK_FUNCTION TOK_RETURNS TOK_LANGUAGE TOK_STRICT
%token <data> TOK_SHUTDOWN
%token <data> TOK_DECLARE
%token <data> TOK_TABLE TOK_DATABASE
%token <data> TOK_USE
%token <data> TOK_WHILE
%token <data> TOK_IGNORE TOK_LOW_PRIORITY TOK_QUICK
%token <data> TOK_PRINT
%token <data> TOK_LOAD TOK_DATA2 TOK_XML TOK_CONCURRENT TOK_LOCAL TOK_INFILE
%token <data> TOK_PROCEDURE
%token <data> TOK_GOTO
%token <data> TOK_CALL
%token <data> TOK_CURSOR
%token <data> TOK_PATH
%token <data> TOK_VALUES
%token <data> TOK_OPEN
%token <data> TOK_OVER
%token <data> TOK_WITHIN
%token <data> TOK_ALTER TOK_RECOVERY TOK_SIMPLE
%token <data> TOK_LOCK TOK_SHARE
%token <data> TOK_IF
%token TOK_FUNC
%token TOK_ERROR

%destructor {
    sqli_token_data_destructor(&$$);
} <data>

%%

context:  start_data
        | start_string
        | start_rce
        ;

start_data: TOK_START_DATA data_cont
        | TOK_START_DATA expr post_exprs_opt ','[u1] data_cont {
            YYUSE($u1);
        }
        ;

start_string: TOK_START_STRING {
            ctx->lexer.instring = true;
        } data_cont
        ;

data:     TOK_DATA
        | data TOK_DATA {
            if ($1.flags == SQLI_VALUE_NEEDFREE) {
                $$.value.str = realloc($1.value.str, $1.value.len +
                                       $2.value.len);
                if ($$.value.str) {
                    $1.flags = 0;
                }
            } else {
                $$.value.str = malloc($1.value.len + $2.value.len);
                memcpy($$.value.str, $1.value.str, $1.value.len);
                $$.flags = SQLI_VALUE_NEEDFREE;
            }
            memcpy($$.value.str + $1.value.len, $2.value.str, $2.value.len);
            $$.value.len = $1.value.len + $2.value.len;

            sqli_token_data_destructor(&$1);
            sqli_token_data_destructor(&$2);
        }
        ;

data_name:  data
        |   TOK_NAME
        |   TOK_DATA2
        /* Tokens-as-identifiers here */
        ;

{'fraction_non_alphanumeric': 0.10166277712952158, 'fraction_numerical': 0.003646441073512252, 'mean_word_length': 3.8288732394366196, 'pattern_counts': {'":': 0, '<': 111, '<?xml version=': 0, '>': 115, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4588634', 'n_tokens_mistral': 2860, 'n_tokens_neox': 2809, 'n_words': 635}