tlvc.y

changeset 0
59c92fa19678
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tlvc.y	Mon Sep 01 00:14:59 2025 +0800
@@ -0,0 +1,81 @@
+%locations
+%define parse.error verbose
+
+%{
+#include "tlvast.h"
+#include "tlvc.yy.h"
+extern void yyerror(const char *s);
+int field_index = 0;
+%}
+
+%union {
+    int num;
+    char *str;
+    struct tlv_field *field;
+    struct tlv_field_list_head *field_list;
+    struct tlv *msg;
+}
+
+%token <str> IDENT
+%token <num> TYPE
+%token <num> NUMBER
+%token MESSAGE
+
+%type <msg> message
+%type <field> field
+%type <field_list> field_list
+
+%%
+
+input:
+    /* empty */
+  | input message {
+        TAILQ_INSERT_TAIL(&g_tlvs, $2, entries);
+    }
+;
+
+message:
+    MESSAGE IDENT NUMBER '{' field_list '}' {
+        struct tlv *m = malloc(sizeof(*m));
+        m->name = strdup($2);
+        m->tag  = $3;
+        TAILQ_INIT(&m->fields);
+
+        struct tlv_field *f;
+        TAILQ_FOREACH(f, $5, entries) {
+            TAILQ_INSERT_TAIL(&m->fields, f, entries);
+        }
+
+        $$ = m;
+    }
+;
+
+field_list:
+    /* empty */ {
+        $$ = NULL;
+    }
+  | field_list field {
+        if ($1 == NULL) {
+            struct tlv_field_list_head *list = malloc(sizeof(*list));
+            TAILQ_INIT(list);
+            TAILQ_INSERT_TAIL(list, $2, entries);
+            $$ = list;
+        } else {
+            TAILQ_INSERT_TAIL($1, $2, entries);
+            $$ = $1;
+        }
+	field_index = 0;
+    }
+;
+
+field:
+    TYPE IDENT ';' {
+        struct tlv_field *f = malloc(sizeof(*f));
+        f->type = $1;
+        f->name = strdup($2);
+        f->tag  = field_index++;
+        $$ = f;
+    }
+;
+
+%%

mercurial