configparser.y 4.55 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

%pure-parser
%error-verbose
%locations

%parse-param {yyscan_t * scanner}
%lex-param {yyscan_t * scanner}
%parse-param {ParserParams * param}

// Note lower versions might also work
%require "2.3"

%name-prefix="cfgp_"
%defines

%{


#include <assert.h>
20 21
#include "src/modelconfig/configglue.h"
#include "codes/tools.h"
22 23 24 25 26 27 28 29 30 31

#if defined __GNUC__
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-function"
#elif defined __SUNPRO_CC
#pragma disable_warn
#elif defined _MSC_VER
#pragma warning(push, 1)
#endif

32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

%}

%code requires {
  
  #ifndef YY_TYPEDEF_YY_SCANNER_T
  #define YY_TYPEDEF_YY_SCANNER_T
  typedef void* yyscan_t;
  #endif
   
}
    

%union {
        struct
        {
            char string_buf [512];
            unsigned int curstringpos;
        };

}

%{
#include "src/modelconfig/configlex.h"

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
int cfgp_error (YYLTYPE * loc, yyscan_t * scanner, ParserParams * p, 
                        const char * msg)
{
   if (loc)
   {
     return cfgp_parser_error (p, msg, loc->first_line, 
     loc->first_column, loc->last_line, loc->last_column);
   }
   else
   {
     return cfgp_parser_error (p, msg, 0,0,0,0);
   }
}

%}

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
%start configfile
%token <string_buf> LITERAL_STRING
%token OPENSECTION
%token CLOSESECTION
%token <string_buf> IDENTIFIER
%token EQUAL_TOKEN
%token SEMICOLUMN
%token KOMMA
%token LOPEN
%token LCLOSE


%initial-action {
   param->stacktop = 0;
   param->sectionstack[0] = 0;
   param->parser_error_code = 0;
   param->parser_error_string = 0;
}

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185


%%

initdummy: /* empty */ {
                /* used to initialize vars */
                param->stacktop = 0;
          } 

configfile: initdummy sectioncontents ;

sectioncontents: sectioncontents entry | ;

entry: key | subsection;


key: singlekey | multikey  ;
  
singlekey: IDENTIFIER EQUAL_TOKEN LITERAL_STRING SEMICOLUMN {
                const char * key = & $<string_buf>1 [0];
                const char * value = & $<string_buf>3 [0];
                cf_createKey (param->configfile,
                      param->sectionstack[param->stacktop], key, &value, 1);
         }

multikeynonzero: KOMMA LITERAL_STRING {
                   param->keyvals[param->count++] = strdup ($<string_buf>2);
                   ALWAYS_ASSERT (param->count < param->maxsize); 
               }

multikeyentry : multikeynonzero multikeyentry | ;

multikeyinit : /* empty */ {
             param->maxsize = 1000;
             param->count = 0;
             param->keyvals = malloc (sizeof(char*)*param->maxsize);
             }

multikeystart : LITERAL_STRING  { 
                param->keyvals[param->count++] = strdup ($<string_buf>1);
                ALWAYS_ASSERT (param->count < param->maxsize); 
             }

/* this can probably be simplified */
multikeybody: multikeystart multikeyentry | ; 
          
multikey: IDENTIFIER EQUAL_TOKEN LOPEN multikeyinit multikeybody LCLOSE
        SEMICOLUMN {
                unsigned int i;
               /* when this is reduced we have all the keys */
               const char * key = & $<string_buf>1 [0];
                const char ** value = (const char **) param->keyvals;
                cf_createKey (param->configfile,
                      param->sectionstack[param->stacktop], key, value,
                      param->count);

                /* can free strings */
                for (i=0; i<param->count; ++i)
                {
                        free (param->keyvals[i]);
                }
                free (param->keyvals);
                param->keyvals = 0;
            }

opt_semicolumn: SEMICOLUMN | ;

subsection_openaction: IDENTIFIER OPENSECTION
                     {
                         SectionHandle newsection;
                         ALWAYS_ASSERT(param->stacktop < ARRAY_SIZEOF(param->sectionstack));
                         
                         cf_createSection (param->configfile,
                         param->sectionstack[param->stacktop], $1,
                         &newsection);

                         /*cf_openSection (param->configfile,
                             param->sectionstack[param->stacktop], $1, &newsection); */
                         param->sectionstack[++param->stacktop] = newsection;
                     }; 

subsection_closeaction: CLOSESECTION opt_semicolumn
                      {
                          ALWAYS_ASSERT (param->stacktop > 0);
                          SectionHandle old = param->sectionstack[param->stacktop--];
                          cf_closeSection (param->configfile, old);
                      };

subsection: subsection_openaction sectioncontents subsection_closeaction ;


%%