/*
 * COPYRIGHT (c) International Business Machines Corp. 2021
 *
 * This program is provided under the terms of the Common Public License,
 * version 1.0 (CPL-1.0). Any use, reproduction or distribution for this
 * software constitutes recipient's acceptance of CPL-1.0 terms which can be
 * found in the file LICENSE file or at
 * https://opensource.org/licenses/cpl1.0.php
 */
%{
/* Generic Config Parser */

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include "cfgparse.h"
#include "configuration.h"

/* Ignore -Wsign-compare for autogenerated code. */
#pragma GCC diagnostic ignored "-Wsign-compare"

#define YY_USER_ACTION \
    yylloc->first_line = yylloc->last_line; \
    yylloc->first_column = yylloc->last_column; \
    for(int i = 0; yytext[i] != '\0'; i++) { \
        if(yytext[i] == '\n') { \
            yylloc->last_line++; \
            yylloc->last_column = 0; \
        } \
        else { \
            yylloc->last_column++; \
        } \
    }

#define YYSTYPE CONFIGSTYPE
#define YYLTYPE CONFIGLTYPE
%}

%option reentrant
%option noyywrap nounput noinput yylineno stack bison-bridge bison-locations noyy_top_state
%option prefix="config"
/* Option only relevant if speed is preferred over size.  Typically not the case for DSOs. */
/* %option full */
%option warn
%option extra-type="int"
%option header-file="cfglex.h"
%x COMMENT STRING MAIN

%%

version                        { yy_push_state(MAIN, yyscanner); return FILEVERSION; }

<INITIAL,MAIN>[\t ]+           /* ignore spaces */;

<INITIAL,MAIN>\n               return EOL;

<MAIN>=                        return EQUAL;

<MAIN>\{                       return BEGIN_DEF;

<MAIN>\}                       return END_DEF;

<MAIN>\(                       return BEGIN_LIST;

<MAIN>\)                       return END_LIST;

<INITIAL,MAIN>#                yy_push_state(COMMENT, yyscanner);

<MAIN>\"                       yy_push_state(STRING, yyscanner);

<MAIN>0|[1-9][0-9]*            {  yylval->num = strtoul(yytext, NULL, 10); return NUMBER;  }

<MAIN>0x[0-9a-fA-F]+           {  yylval->num = strtoul(yytext, NULL, 16); return NUMBER;  }

<MAIN>[0-9]+"."[0-9]+          {  /* version */
                                  unsigned long major, minor;
                                  char *dot = strchr(yytext, '.');

                                  *dot = '\0';
                                  major = strtoul(yytext, NULL, 10);
                                  minor = strtoul(dot + 1, NULL, 10);

                                  yylval->num = (uint32_t)major << 16 | (uint32_t)minor;
                                  return VERSION_TOK;
                               }

<MAIN>,                        {  return COMMA;  }

<MAIN>[a-zA-Z./][a-zA-Z0-9_\-./]* {  yylval->str = strdup(yytext); return BARE;  }

<COMMENT>\n                    {  yy_pop_state(yyscanner); return EOL;  }

<COMMENT>[^\n]+                {  if (yyextra) { yylval->str = strdup(yytext); return COMMENT_TOK; }  }

<STRING>\"                     yy_pop_state(yyscanner);

<STRING>[^\"]+                 {  yylval->str = strdup(yytext); return STRING_TOK; }

.                              { yy_push_state(MAIN, yyscanner); yyless(0); }

%%
