diff options
Diffstat (limited to 'yy/kalmia.y')
-rw-r--r-- | yy/kalmia.y | 164 |
1 files changed, 157 insertions, 7 deletions
diff --git a/yy/kalmia.y b/yy/kalmia.y index f1d77f9..0d8b16f 100644 --- a/yy/kalmia.y +++ b/yy/kalmia.y @@ -6,13 +6,51 @@ %code top { #include <stdio.h> + #include <stdlib.h> + #include <stdarg.h> } %code requires { typedef void* yyscan_t; + + struct kalmia_t { + void *current; + int index; + }; + + struct ka_float_array_t { + char *id; + size_t count; + double *buf; + }; } +%parse-param { struct kalmia_t *result } %code { int yylex(YYSTYPE *yylvalp, YYLTYPE *yyllocp, yyscan_t scanner); - int yyerror(YYLTYPE *yyllocp, yyscan_t unused, const char *msg); + int yyerror(YYLTYPE *yyllocp, yyscan_t unused, struct kalmia_t *unused2, const char *msg); + + #define KAI_ABORT -1 + #define KAI_NOMEM -2 + + #define KAI_ABORTF(...) \ + do { \ + kai_abortf_(&yylloc, __VA_ARGS__); \ + YYABORT; \ + } while(0) + void kai_abortf_(YYLTYPE *yyllocp, const char *fmt, ...); + + /* float arrays */ + int kai_set_float_array_attrs(struct ka_float_array_t *a, char *id, char *count); + + #define KAI_WRAP(call) \ + do { \ + int err = call; \ + if (err == KAI_ABORT) { \ + KAI_ABORTF("call returned error: %s", #call); \ + } \ + else if (err == KAI_NOMEM) { \ + KAI_ABORTF("call ran out of memory: %s", #call); \ + } \ + } while(0) } %union { @@ -20,6 +58,7 @@ double dval; char *sval; char cval; + struct ka_float_array_t float_array; } %token PROLOG @@ -31,6 +70,13 @@ %token <dval> DOUBLE %token DATE; +%token <float_array> FLOAT_ARRAY +%type <float_array> float_array +%type <float_array> float_array_start +%type <float_array> float_array_attributes + +%token ID_ATTR COUNT_ATTR +%type <sval> attr %% @@ -46,6 +92,7 @@ element: empty_tag | start_tag end_tag | start_tag content end_tag + | float_array ; content: @@ -60,7 +107,11 @@ empty_tag: ; start_tag: - S_TAG_OPEN NAME attributes TAG_CLOSE { printf("enter tag: %s\n", $2); } + S_TAG_OPEN NAME attributes TAG_CLOSE + { + printf("enter tag: %s\n", $2); + result->current = NULL; + } ; end_tag: @@ -69,11 +120,53 @@ end_tag: attributes: | attribute - | attributes attribute; + | attributes attribute ; attribute: - ATTR '=' '"' TEXT '"' { printf("attribute: %s=%s\n", $1, $4); } + ATTR attr { printf("attribute: %s=%s\n", $1, $2); } + | ID_ATTR attr + | COUNT_ATTR attr + ; + + + +float_array: + float_array_start doubles float_array_close + { + $$ = $1; + printf("float_array[id='%s', count=%lu]{ ", $$.id, $$.count); + for (size_t i=0; i<$$.count; i++) { + printf("%f, ", $$.buf[i]); + } + printf("}\n"); + } + ; + +float_array_start: + S_TAG_OPEN FLOAT_ARRAY float_array_attributes TAG_CLOSE + { + $$ = $3; + result->current = $$.buf; + result->index = 0; + } + ; + +float_array_close: + E_TAG_OPEN FLOAT_ARRAY TAG_CLOSE + ; + +float_array_attributes: + COUNT_ATTR attr + { KAI_WRAP(kai_set_float_array_attrs(&$$, NULL, $2)); } + | COUNT_ATTR attr ID_ATTR attr + { KAI_WRAP(kai_set_float_array_attrs(&$$, $4, $2)); } + | ID_ATTR attr COUNT_ATTR attr + { KAI_WRAP(kai_set_float_array_attrs(&$$, $2, $4)); } + ; + +attr: + '=' '"' TEXT '"' { $$ = $3; } ; @@ -83,14 +176,32 @@ integers: ; doubles: - DOUBLE { printf("%f\n", $1); } - | doubles DOUBLE { printf("%f\n", $2); } + DOUBLE + { + if (result->current != NULL) { + ((double*) result->current)[result->index] = $1; + result->index += 1; + } + } + | doubles DOUBLE + { + if (result->current != NULL) { + ((double*) result->current)[result->index] = $2; + result->index += 1; + } + } + ; %% -int yyerror(YYLTYPE *yyllocp, yyscan_t unused, const char *msg) + +int yyerror( + YYLTYPE *yyllocp, + yyscan_t unused, + struct kalmia_t *unused2, + const char *msg) { fprintf( stderr, "[%d:%d]: %s\n", @@ -98,3 +209,42 @@ int yyerror(YYLTYPE *yyllocp, yyscan_t unused, const char *msg) ); return 1; } + + +void kai_abortf_(YYLTYPE *yyllocp, const char *fmt, ...) +{ + va_list args, args_len; + va_start(args, fmt); + va_copy(args_len, args); + size_t len = vsnprintf(NULL, 0, fmt, args_len) + 1; + va_end(args_len); + + char *buf = malloc(sizeof(char) * len); + if (buf == NULL) { + fprintf(stderr, "failed to allocate buffer for error message!\n"); + return; + } + vsnprintf(buf, len, fmt, args); + va_end(args); + + yyerror(yyllocp, NULL, NULL, buf); +} + + +/* float arrays */ +int kai_set_float_array_attrs( + struct ka_float_array_t *a, char *id, char *count) +{ + a->id = id; + char *end = NULL; + a->count = strtoll(count, &end, 10); + if (end == count) { + return -1; + } + + a->buf = malloc(sizeof(double) * a->count); + if (a->buf == NULL) { + return -2; + } + return 0; +} |