shithub: vcardfs

ref: 732192cde475a07a558f581eecdd21f05cd1607a
dir: /libvcard/vcard.y/

View raw version
%{
#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;