ref: e0cac8cff0fad58496578de0bf11f111f765d3a8
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");
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;