summaryrefslogtreecommitdiff
path: root/yy/kalmia.y
diff options
context:
space:
mode:
Diffstat (limited to 'yy/kalmia.y')
-rw-r--r--yy/kalmia.y164
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;
+}