ref: 732192cde475a07a558f581eecdd21f05cd1607a
dir: /libvcard/vcard.y/
%{ #include <u.h> #include <libc.h> #include "vcard.h" static void iltolower(char *s) { while (*s) { if (*s >= 'A' && *s <= 'Z') *s = *s - 'A' + 'a'; s++; } } Vcard *vcparsecard; extern int yylex(void); void yyerror(char *s) { werrstr("%s (%10s)\n", s, vcstate.s); } static Vcard* mkvcard(Vline *lines) { Vcard *vc; vc = mallocz(sizeof(Vcard), 1); vc->content = lines; return vc; } static void enqueue(Vcard *head, Vcard *tail) { head->next = tail; vcparsecard = head; } static void enqueuel(Vline *head, Vline *tail) { head->next = tail; } static void enqueuep(Vparam *head, Vparam *tail) { head->next = tail; } static Vline* mkline(char *name, Vparam *params, char *value, char *group) { Vline *vl; vl = mallocz(sizeof(Vline), 1); vl->name = name; iltolower(vl->name); if (strcmp(vl->name, "version") == 0) { vl->value = strdup("4.0"); free(value); } else vl->value = value; vl->params = params; vl->group = group; /* fprint(2, "new line:\n"); fprint(2, " name: %s\n", name); fprint(2, " value: %s\n", value); fprint(2, " params: %p\n", params); fprint(2, " group: %s\n", group); */ return vl; } static Vparam* addparam(char *name, char *value) { Vparam *vp; vp = mallocz(sizeof(Vparam), 1); vp->name = name; iltolower(vp->name); vp->value = value; return vp; } static Vparam* appv2param(Vparam* p1, Vparam* p2) { char *s; s = smprint("%s,%s", p1->value, p2->value); if (!s) sysfatal("out of memory: %r"); free(p1->value); free(p2->value); free(p2->name); free(p2); p1->value = s; return p1; } static Vparam* addv2param(char *s) { Vparam *vp; vp = mallocz(sizeof(Vparam), 1); vp->name = strdup("type"); vp->value = s; return vp; } %} %union { int i; Vcard *vc; Vline *vl; Vparam *vp; char *s; } %token <i> BEGIN END CRLF %token <s> WORD SWORD FWORD %type <s> pvalue %type <vc> vclist vcard %type <vl> cline clinel %type <vp> params param %type <vp> v2params v2param %type <s> group name value %% vclist: vcard vclist { $$ = $1; enqueue($1, $2); } | /* empty */ { $$ = nil; } ; vcard: BEGIN clinel END { $$ = mkvcard($2); } | BEGIN clinel END CRLF { $$ = mkvcard($2); } ; clinel: cline | cline clinel { $$ = $1; enqueuel($1, $2); } ; cline: group '.' name params ':' value CRLF { $$ = mkline($3, $4, $6, $1); } | name params ':' value CRLF { $$ = mkline($1, $2, $4, nil); } | name ':' value CRLF { $$ = mkline($1, nil, $3, nil); } | name v2params ':' value CRLF { $$ = mkline($1, $2, $4, nil); } | group '.' name v2params ':' value CRLF { $$ = mkline($3, $4, $6, $1); } ; v2params: ';' v2param { $$ = $2; } | ';' v2param v2params { $$ = $2; appv2param($2, $3); } ; v2param: SWORD { $$ = addv2param($1); }; params: ';' param { $$ = $2; } | ';' param params { $$ = $2; enqueuep($2, $3); } ; param: SWORD '=' pvalue { $$ = addparam($1, $3); }; pvalue: SWORD | '"' WORD '"' { $$ = $2; } | '"' SWORD '"' { $$ = $2; } | '"' FWORD '"' { $$ = $2; } ; group: SWORD; name: SWORD; value: WORD | SWORD | FWORD;