%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
%}

%token NUMBER
%token BOOLEAN
%token UNDEFINED
%token QUOTED_STRING
%token REGEX
%token IDENTIFIER

%token LBRACKET
%token RBRACKET
%token LBRACE
%token RBRACE
%token LPAREN
%token RPAREN

%token ARROW
%token OP_EQUIV
%token OP_EQUAL
%token OP_ASSIGN
%token OP_NEQ
%token OP_LT
%token OP_GT
%token OP_LTE
%token OP_GTE
%token OP_RANGE
%token OP_PLUS
%token OP_MINUS
%token OP_MULTIPLY
%token OP_DIVIDE
%token OP_MODULO
%token OP_AND
%token OP_OR
%token OP_REGEX_MATCH
%token OP_NOT
%token OP_EXPONENT
%token DOT
%token LKEY
%token RKEY
%token DOLLAR
%token AMPERSAND
%token COMMA

%left OP_OR
%left OP_AND
%left OP_EQUIV
%left OP_EQUAL
%left OP_NEQ
%left OP_LT OP_GT OP_LTE OP_GTE
%left OP_PLUS OP_MINUS
%left OP_MULTIPLY OP_DIVIDE OP_MODULO
%left OP_NOT OP_EXPONENT
%left DOT LKEY RKEY
%left DOLLAR AMPERSAND

%start start

%%

start: _ parsed:logicals _ { printf("Result: %d\n", parsed); }
     | _ { printf("Result: Undefined\n"); }

primitives: literal_values
          | metavar
          | parenthesized
          | helper_functions
          | logical_not
          | literal_structures
          | quoted_chars
          | embeddedvars
          | regex
          ;

literal_values: hard_quoted_characters
              | quoted_chars
              | NUMBER
              | BOOLEAN
              | UNDEFINED
              | REGEX
              ;

operator: "<=>"
        | OP_EQUAL "="
        | OP_NEQ
        | "<"
        | ">"
        | OP_RANGE
        ;

logical_ops: "&&"
           | "||"
           | OP_REGEX_MATCH
           ;

logical_not: "!" _ ex:primitives { printf("Logical Not\n"); /* Perform logical NOT operation */ }

transform_short: "->" _ transform:logicals { printf("Transform Short\n"); /* Perform transformation */ }
               | "->" _ transform:metatoken { printf("Transform Short\n"); /* Perform transformation */ }
               ;

parenthesized: "(" _ ex:logicals _ RPAREN { printf("Parenthesized\n"); /* Handle parenthesized expression */ }
             | pairs
             | "(" ex:arr+ RPAREN { printf("Parenthesized\n"); /* Handle parenthesized expression */ }
             ;

literal_structures: "[" ex:logicals_list* RBRACKET { printf("Literal Structures\n"); /* Handle literal structures */ }
                  | LBRACE ls:literal_struct_list* RBRACE { printf("Literal Structures\n"); /* Handle literal structures */ }
                  | LBRACE _ par:primitives _ RBRACE { printf("Literal Structures\n"); /* Handle literal structures */ }
                  | LBRACE _ par:primitives* _ RBRACE { printf("Literal Structures\n"); /* Handle literal structures */ }
                  ;

pairs: _ "(" _ left:logicals _ ":" _ right:logicals _ RPAREN _ { printf("Pairs\n"); /* Handle pairs */ }
     | _ "(" _ left:logicals _ right:logicals _ RPAREN _ { printf("Pairs\n"); /* Handle pairs */ }
     ;

arr: _ ex:logicals ":"? _ { printf("Array\n"); /* Handle array expression */ }

sub_opts: opts:primitives { printf("Sub Options\n"); /* Handle sub-options */ }
        | opts:literals { printf("Sub Options\n"); /* Handle sub-options */ }
        | "" { printf("Sub Options\n"); /* Handle sub-options */ }
        ;

logicals: left:operation _ op:logical_ops _ right:logicals { printf("Logical Expression\n"); /* Handle logical expression */ }
         | operation
         ;

operation: left:additive _ op:operator _ right:operation { printf("Operation\n"); /* Handle operation */ }
         | transform
         | additive
         ;

transform: input:additive _ transform:transform_short { printf("Transform\n"); /* Perform transformation */ }

additive: left:multiplicative _ op:[+\-~] !LPAREN _ right:additive { printf("Additive\n"); /* Handle additive operation */ }
        | left:multiplicative _ AMPERSAND _ !LPAREN _ right:additive { printf("Additive\n"); /* Handle additive operation */ }
        | multiplicative
        ;

multiplicative: left:exponential _ rest:(([\*/%]) !LPAREN _ multiplicative)* { printf("Multiplicative\n"); /* Handle multiplicative operation */ }
              | exponential
              ;

exponential: left:primitives _ op:"^" !LPAREN _ right:exponential { printf("Exponential\n"); /* Handle exponential operation */ }
           | primitives
           ;

number: "-" pn:positive_numbers { printf("Number\n"); /* Handle negative number */ }
      | "+" pn:positive_numbers { printf("Number\n"); /* Handle positive number */ }
      | positive_numbers
      ;

positive_numbers: "0x" digits:[A-Fa-f0-9]+ { printf("Positive Number\n"); /* Handle hexadecimal number */ }
                | "0o" digits:[0-7]+ { printf("Positive Number\n"); /* Handle octal number */ }
                | "0b" digits:[0-1]+ { printf("Positive Number\n"); /* Handle binary number */ }
                | digits:[0-9]+ dec:[\.] digits2:[0-9]+ { printf("Positive Number\n"); /* Handle floating-point number */ }
                | digits:[0-9]+ { printf("Positive Number\n"); /* Handle integer number */ }
                ;

_: /* Empty rule */
    ;

%%

int main() {
    yyparse();
    return 0;
}

int yyerror(const char* msg) {
    fprintf(stderr, "Error: %s\n", msg);
    return 1;
}

