From 5d2e5a312ba73bd48913e9ac5babe1c644997b3e Mon Sep 17 00:00:00 2001 From: sanine Date: Wed, 18 Jan 2023 16:42:16 -0600 Subject: parse float_array nodes --- yy/kalmia.h | 4 -- yy/kalmia.l | 21 +++++++- yy/kalmia.y | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- yy/main.c | 11 +++- yy/makefile | 4 +- 5 files changed, 188 insertions(+), 16 deletions(-) delete mode 100644 yy/kalmia.h (limited to 'yy') diff --git a/yy/kalmia.h b/yy/kalmia.h deleted file mode 100644 index 98afd13..0000000 --- a/yy/kalmia.h +++ /dev/null @@ -1,4 +0,0 @@ -#define YYLTYPE KALMIALTYPE -#define YYSTYPE KALMIASTYPE -#include "kalmia.tab.h" -#include "kalmia.lex.h" diff --git a/yy/kalmia.l b/yy/kalmia.l index 697d6ac..7e04f1a 100644 --- a/yy/kalmia.l +++ b/yy/kalmia.l @@ -45,11 +45,27 @@ ATTR ([\x20\x0a\x0d\x09]*)?"=" "/>" { return EMPTY_TAG_CLOSE; } +"float_array" { + /* float_array tag */ + return FLOAT_ARRAY; +} + + +"id"/{ATTR} { + /* id attribute */ + return ID_ATTR; +} +"count"/{ATTR} { + /* count attribute */ + return COUNT_ATTR; +} + + [a-zA-Z_:][a-zA-Z0-9\.\-_:]* { /* generic tag name */ yylval->sval = strdup(yytext); return NAME; } -[a-zA-Z_:][a-zA-Z0-9\.\-_:]*/([\x20\x0a\x0d\x09])*"=" { +[a-zA-Z_:][a-zA-Z0-9\.\-_:]*/{ATTR} { /* generic attribute key */ yylval->sval = strdup(yytext); return ATTR; @@ -60,6 +76,9 @@ ATTR ([\x20\x0a\x0d\x09]*)?"=" } + + + "\"" { /* begin a string */ BEGIN(STRING); 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 + #include + #include } %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 DOUBLE %token DATE; +%token FLOAT_ARRAY +%type float_array +%type float_array_start +%type float_array_attributes + +%token ID_ATTR COUNT_ATTR +%type 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; +} diff --git a/yy/main.c b/yy/main.c index 52ee955..0d97fba 100644 --- a/yy/main.c +++ b/yy/main.c @@ -1,5 +1,10 @@ #include -#include "kalmia.h" + +#define YYLTYPE KALMIALTYPE +#define YYSTYPE KALMIASTYPE +#include "kalmia.tab.h" +#include "kalmia.lex.h" + int main(int argc, char **argv) { @@ -13,10 +18,12 @@ int main(int argc, char **argv) return -1; } + struct kalmia_t result; + yyscan_t scanner; kalmialex_init(&scanner); kalmiaset_in(in, scanner); - kalmiaparse(scanner); + kalmiaparse(scanner, &result); kalmialex_destroy(scanner); return 0; } diff --git a/yy/makefile b/yy/makefile index 76b5c77..a2022a2 100644 --- a/yy/makefile +++ b/yy/makefile @@ -8,8 +8,8 @@ kalmia.tab.c: kalmia.y kalmia.lex.c: kalmia.l flex -o "$@" --header-file="kalmia.lex.h" kalmia.l -kalmia: kalmia.tab.c kalmia.lex.c main.c kalmia.h - gcc -o kalmia ${WARNINGS} main.c kalmia.tab.c kalmia.lex.c +kalmia: kalmia.tab.c kalmia.lex.c main.c + gcc -g -o kalmia ${WARNINGS} main.c kalmia.tab.c kalmia.lex.c clean: rm kalmia.lex.c kalmia.lex.h kalmia.tab.c kalmia.tab.h kalmia -- cgit v1.2.1