1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-23 01:51:33 +02:00

b2/: first tentative version of hierarchy parser, with example

This commit is contained in:
Werner Almesberger 2012-04-25 17:14:39 -03:00
parent 7fe553a4fc
commit 6bb8b03ef8
11 changed files with 512 additions and 88 deletions

7
b2/HIERARCHY Normal file
View File

@ -0,0 +1,7 @@
<comp> = R<C<L;
T:<comp> {
R: { R:#R TOL:%R };
C: { C:#F TOL:%C };
L: { L:#H TOL:%L };
}

View File

@ -11,9 +11,9 @@
SHELL = /bin/bash SHELL = /bin/bash
CFLAGS = -Wall $(shell pkg-config --cflags glib-2.0) CFLAGS = -g -Wall $(shell pkg-config --cflags glib-2.0)
SLOPPY = -Wno-unused -Wno-implicit-function-declaration SLOPPY = -Wno-unused -Wno-implicit-function-declaration
OBJS = boom.o chr.o comp.o db.o eval.o param.o util.o lex.yy.o y.tab.o OBJS = boom.o chr.o comp.o db.o dump.o eval.o param.o util.o lex.yy.o y.tab.o
LDLIBS = -lfl $(shell pkg-config --libs glib-2.0) LDLIBS = -lfl $(shell pkg-config --libs glib-2.0)
YACC = bison -y YACC = bison -y

View File

@ -1,4 +1,52 @@
int main(void) /*
* boom.c - BOOM, main function
*
* Copyright 2012 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
extern int yyparse(void);
static void usage(const char *name)
{ {
fprintf(stderr, "usage: %s [file]\n", name);
exit(1);
}
int main(int argc, char **argv)
{
int fd;
switch (argc) {
case 1:
break;
case 2:
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror(argv[1]);
exit(1);
}
if (dup2(fd, 0) < 0) {
perror("dup2");
exit(1);
}
break;
default:
usage(*argv);
}
(void) yyparse();
return 0; return 0;
} }

208
b2/chr.c
View File

@ -10,93 +10,193 @@
*/ */
#include <assert.h>
#include "util.h" #include "util.h"
#include "param.h" #include "param.h"
#include "chr.h" #include "chr.h"
struct condition { const struct format *field_find(const char *name, const struct field *tail)
struct value value;
enum relop relop;
struct condition *next;
};
struct selector {
struct condition *cond;
struct selector *next;
};
struct field {
const char *name;
const struct format *fmt;
struct field *mark;
struct selector *sel;
struct field *next;
};
static struct field *fields = NULL, *curr_field = NULL, *mark = NULL;
const struct format *field_find(const char *name)
{ {
const struct field *f; while (tail) {
if (tail->name == name)
for (f = fields; f; f = f->next) return tail->fmt;
if (f->name == name) tail = tail->prev;
return f->fmt; }
return NULL; return NULL;
} }
void field_add(const char *name, const struct format *fmt) /* ----- Construction of the field hierarchy ------------------------------- */
struct field *field_new(const char *name, const struct format *fmt,
const struct field *prev)
{ {
struct field *field; struct field *field;
if (field_find(name)) if (field_find(name, prev))
yyerrorf("duplicate field \"%s\"", name); yyerrorf("duplicate field \"%s\"", name);
field = alloc_type(struct field); field = alloc_type(struct field);
field->name = name; field->name = name;
field->fmt = fmt; field->fmt = fmt;
field->mark = (void *) 1; /* poison */
field->sel = NULL; field->sel = NULL;
if (curr_field) field->any.fields = NULL;
curr_field->next = field; field->any.rules = NULL;
field->next = NULL;
field->prev = NULL;
return field;
}
struct selector *field_selector(void)
{
struct selector *sel;
sel = alloc_type(struct selector);
sel->cond = NULL;
sel->act.fields = NULL;
sel->act.rules = NULL;
sel->next = NULL;
return sel;
}
struct condition *field_condition(enum relop relop, const char *word)
{
struct condition *cond;
cond = alloc_type(struct condition);
cond->value.u.name = word;
cond->relop = relop;
cond->next = NULL;
return cond;
}
void field_finalize(struct field *field)
{
const struct selector *sel;
struct condition *cond;
for (sel = field->sel; sel; sel = sel->next)
for (cond = sel->cond; cond; cond = cond->next)
if (!evaluate(field->fmt, cond->value.u.name,
&cond->value))
yyerrorf("invalid value in selection");
/* @@@ indicate exact location */
}
/* ----- Dumping ----------------------------------------------------------- */
#define INDENT 8
static void dump_fields(FILE *file, const struct field *field, int level);
static void dump_set_decl(FILE *file, const struct names *first_name)
{
const char *name;
name = nameset_rev_lookup(first_name);
assert(name);
fprintf(file, "<%s>", name);
}
static void dump_field_decl(FILE *file, const struct field *field)
{
if (field->fmt->ops == &param_ops_name)
fprintf(file, "*");
else if (field->fmt->ops == &param_ops_set)
dump_set_decl(file, field->fmt->u.set);
else if (field->fmt->ops == &param_ops_abs)
fprintf(file, "#%s", field->fmt->u.abs);
else if (field->fmt->ops == &param_ops_rel)
fprintf(file, "%%%s", field->fmt->u.rel->u.abs);
else else
fields = field; abort();
curr_field = field;
} }
void field_mark(void) static void dump_action(FILE *file, const struct action *act, int level)
{ {
if (mark) const struct field *field;
mark->mark = curr_field;
mark = curr_field; if (act->fields) {
fprintf(file, " {");
for (field = act->fields; field; field = field->next) {
fprintf(file, " %s:", field->name);
dump_field_decl(file, field);
}
fprintf(file, " }\n");
} else {
fprintf(file, "\n");
}
dump_fields(file, act->rules, level+1);
} }
void field_release(void) static void dump_one_field(FILE *file, const struct field *field, int level)
{ {
curr_field = mark; const struct selector *sel;
if (curr_field) const struct condition *cond;
mark = curr_field->mark;
fprintf(file, "%*s%s:", level*INDENT, "", field->name);
dump_field_decl(file, field);
fprintf(file, " {\n");
for (sel = field->sel; sel; sel = sel->next) {
fprintf(file, "%*s", level*INDENT+INDENT/2, "");
for (cond = sel->cond; cond; cond = cond->next) {
if (cond != sel->cond)
fprintf(file, "|");
switch (cond->relop) {
case rel_lt:
fprintf(file, "<");
break;
case rel_le:
fprintf(file, "<=");
break;
case rel_eq:
break;
case rel_ge:
fprintf(file, ">");
break;
case rel_gt:
fprintf(file, ">=");
break;
default:
fprintf(file, "?");
}
dump(file, field->fmt, &cond->value);
}
fprintf(file, ": ");
dump_action(file, &sel->act, level);
}
if (field->any.fields || field->any.rules) {
fprintf(file, "%*s*:", level*INDENT+INDENT/2, "");
dump_action(file, &field->any, level);
}
fprintf(file, "%*s}\n", level*INDENT, "");
} }
void field_add_selector(enum relop relop, const char *word) static void dump_fields(FILE *file, const struct field *field, int level)
{ {
while (field) {
dump_one_field(file, field, level);
field = field->next;
}
} }
void field_more_selectors(void) void field_dump(FILE *file, const struct field *field)
{ {
if (curr_field->fmt->ops != &param_ops_set) dump_fields(file, field, 0);
;//yyerrorf("
} }
void field_add_wildcard(void)
{
}

View File

@ -13,15 +13,46 @@
#ifndef CHR_H #ifndef CHR_H
#define CHR_H #define CHR_H
#include <stdio.h>
#include "param.h" #include "param.h"
void field_add(const char *name, const struct format *fmt); struct field;
const struct format *field_find(const char *name);
void field_mark(void); struct action {
void field_release(void); struct field *fields;
void field_add_selector(enum relop relop, const char *word); struct field *rules;
void field_more_selectors(void); };
void field_add_wildcard(void);
struct condition {
struct value value;
enum relop relop;
struct condition *next;
};
struct selector {
struct condition *cond;
struct action act;
struct selector *next;
};
struct field {
const char *name;
const struct format *fmt;
struct selector *sel;
struct action any;
struct field *next;
const struct field *prev;
};
const struct format *field_find(const char *name, const struct field *tail);
struct field *field_new(const char *name, const struct format *fmt,
const struct field *prev);
struct selector *field_selector(void);
struct condition *field_condition(enum relop relop, const char *word);
void field_finalize(struct field *field);
void field_dump(FILE *file, const struct field *field);
#endif /* !CHR_H */ #endif /* !CHR_H */

63
b2/dump.c Normal file
View File

@ -0,0 +1,63 @@
/*
* dump.c - Dump a value (for debugging)
*
* Copyright 2012 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdio.h>
#include "bitset.h"
#include "param.h"
void dump_name(FILE *file, const struct format *fmt, const struct value *v)
{
fprintf(file, "%s", v->u.name);
}
void dump_set(FILE *file, const struct format *fmt, const struct value *v)
{
const struct names *name;
int first = 1;
int i;
i = 0;
for (name = fmt->u.set; name; name = name->next) {
if (bitset_get(&v->u.set, i)) {
fprintf(file, "%s%s", first ? "" : "|",
name->equiv->name);
first = 0;
}
i++;
}
}
void dump_abs(FILE *file, const struct format *fmt, const struct value *v)
{
fprintf(file, "%g%s", v->u.abs, fmt->u.abs);
}
void dump_rel(FILE *file, const struct format *fmt, const struct value *v)
{
if (v->u.rel.fract)
fprintf(file, "-%f/+%f%%",
v->u.rel.minus*100, v->u.rel.plus*100);
else
fprintf(file, "-%g/+%g%s",
v->u.rel.minus, v->u.rel.plus, fmt->u.rel->u.abs);
}
void dump(FILE *file, const struct format *fmt, const struct value *v)
{
fmt->ops->dump(file, fmt, v);
}

View File

@ -30,10 +30,12 @@ static int lookup_name(const struct names *name, const char *s)
const struct equiv *eq; const struct equiv *eq;
int n; int n;
for (n = 0; name; n++) for (n = 0; name; n++) {
for (eq = name->equiv; eq; eq = eq->next) for (eq = name->equiv; eq; eq = eq->next)
if (eq->name == s) if (eq->name == s)
return n; return n;
name = name->next;
}
return -1; return -1;
} }

View File

@ -15,6 +15,7 @@
#include "util.h" #include "util.h"
#include "param.h" #include "param.h"
#include "chr.h"
#include "y.tab.h" #include "y.tab.h"

166
b2/lang.y
View File

@ -12,6 +12,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <assert.h>
#include "util.h" #include "util.h"
#include "param.h" #include "param.h"
@ -19,6 +20,41 @@
#include "y.tab.h" #include "y.tab.h"
static struct field_stack {
const struct field *field;
struct field_stack *next;
} *field_stack = NULL;
static void push_field(const struct field *field)
{
struct field_stack *entry;
entry = alloc_type(struct field_stack);
entry->field = field;
entry->next = field_stack;
field_stack = entry;
}
static void pop_field(void)
{
struct field_stack *entry;
assert(field_stack);
entry = field_stack;
field_stack = entry->next;
free(entry);
}
static const struct field *top_field(void)
{
return field_stack ? field_stack->field : NULL;
}
%} %}
@ -28,6 +64,10 @@
struct names *names; struct names *names;
struct format *format; struct format *format;
enum relop relop; enum relop relop;
struct field *field;
struct selector *sel;
struct condition *cond;
struct action act;
}; };
@ -38,12 +78,19 @@
%type <names> names nameq %type <names> names nameq
%type <format> format %type <format> format
%type <relop> relop opt_relop %type <relop> relop opt_relop
%type <field> /*rules*/ opt_rule rule opt_fields fields field
%type <sel> selectors
%type <cond> conditions condition
%type <act> opt_wildcard action
%% %%
all: all:
| nameset ';' rule
| rules {
field_dump(stderr, $1);
}
| nameset all
; ;
nameset: nameset:
@ -89,41 +136,101 @@ nameqs:
} }
; ;
/*
* @@@ for now, we can't select on a collective of fields. maybe later, with
* a syntax change.
*
rules: rules:
field '{'
{ {
field_mark(); $$ = NULL;
} }
selections opt_wildcard '}' | rule rules
{ {
field_release(); $$ = $1;
$$->next = $2;
}
;
*/
opt_rule:
{
$$ = NULL;
}
| rule
{
$$ = $1;
} }
; ;
selections: rule:
| selectors ':' opt_fields rules selections field
{
$1->prev = top_field();
push_field($1);
}
'{' selectors opt_wildcard '}'
{
$$ = $1;
$$->sel = $4;
$$->any = $5;
$$->next = NULL;
field_finalize($$);
pop_field();
}
; ;
selectors: selectors:
selector
| selector '|'
{ {
field_more_selectors(); $$ = NULL;
}
| conditions ':' action selectors
{
$$ = field_selector();
$$->cond = $1;
$$->act = $3;
$$->next = $4;
} }
selectors
; ;
selector: conditions:
condition
{
$$ = $1;
}
| condition '|' conditions
{
$$ = $1;
$$->next = $3;
}
;
condition:
opt_relop WORD opt_relop WORD
{ {
field_add_selector($1, $2); $$ = field_condition($1, $2);
} }
; ;
opt_wildcard: opt_wildcard:
'*' ':'
{ {
field_add_wildcard(); $$.fields = NULL;
$$.rules = NULL;
}
| '*' ':' action
{
$$ = $3;
}
;
action:
{
push_field(top_field());
}
opt_fields opt_rule ';'
{
$$.fields = $2;
$$.rules = $3;
pop_field();
} }
; ;
@ -161,17 +268,38 @@ relop:
; ;
opt_fields: opt_fields:
{
$$ = NULL;
}
| '{' fields '}' | '{' fields '}'
{
$$ = $2;
}
; ;
fields: fields:
| field fields {
$$ = NULL;
}
| field
{
push_field($1);
}
fields
{
$$ = $1;
$$->next = $3;
pop_field();
$$->prev = top_field();
if ($3)
$3->prev = $1;
}
; ;
field: field:
WORD ':' format WORD ':' format
{ {
field_add($1, $3); $$ = field_new($1, $3, top_field());
} }
; ;
@ -199,7 +327,7 @@ format:
{ {
$$ = alloc_type(struct format); $$ = alloc_type(struct format);
$$->ops = &param_ops_rel; $$->ops = &param_ops_rel;
$$->u.rel = field_find($2); $$->u.rel = field_find($2, top_field());
if (!$$->u.rel) if (!$$->u.rel)
yyerrorf("unknown field \"%s\"", $2); yyerrorf("unknown field \"%s\"", $2);
} }

View File

@ -36,12 +36,14 @@ static void check_duplicates(const struct names *n)
const struct equiv *ea; const struct equiv *ea;
for (na = n; na; na = na->next) { for (na = n; na; na = na->next) {
for (ea = na->equiv; ea; ea = ea->next) for (ea = na->equiv; ea; ea = ea->next) {
if (duplicate(ea->name, ea->next)) if (duplicate(ea->name, ea->next))
yyerrorf("duplicate name \"%s\"", ea->name); yyerrorf("duplicate name \"%s\"", ea->name);
for (nb = na->next; nb; nb = nb->next) for (nb = na->next; nb; nb = nb->next)
if (duplicate(ea->name, nb->equiv)) if (duplicate(ea->name, nb->equiv))
yyerrorf("duplicate name \"%s\"", ea->name); yyerrorf("duplicate name \"%s\"",
ea->name);
}
} }
} }
@ -69,10 +71,41 @@ const struct names *find_nameset(const char *name)
} }
struct lookup_data {
const struct names *first_name;
const char *name;
};
static gboolean rev_traverse(gpointer key, gpointer value, gpointer data)
{
struct lookup_data *d = data;
if (d->first_name == value) {
d->name = key;
return TRUE;
}
return FALSE;
}
const char *nameset_rev_lookup(const struct names *first_name)
{
struct lookup_data data = {
.first_name = first_name,
.name = NULL,
};
g_tree_foreach(tree, rev_traverse, (void *) &data);
return data.name;
}
#define MKOPS(type) \ #define MKOPS(type) \
const struct param_ops param_ops_##type = { \ const struct param_ops param_ops_##type = { \
.eval = eval_##type, \ .eval = eval_##type, \
.comp = comp_##type, \ .comp = comp_##type, \
.dump = dump_##type, \
} }

View File

@ -13,6 +13,8 @@
#ifndef PARAM_H #ifndef PARAM_H
#define PARAM_H #define PARAM_H
#include <stdio.h>
#include "bitset.h" #include "bitset.h"
@ -72,11 +74,14 @@ struct param_ops {
struct value *res); struct value *res);
int (*comp)(const struct value *a, enum relop relop, int (*comp)(const struct value *a, enum relop relop,
const struct value *b); const struct value *b);
void (*dump)(FILE *file, const struct format *fmt,
const struct value *v);
}; };
void register_nameset(const char *name, const struct names *set); void register_nameset(const char *name, const struct names *set);
const struct names *find_nameset(const char *name); const struct names *find_nameset(const char *name);
const char *nameset_rev_lookup(const struct names *first_name);
int eval_name(const struct format *fmt, const char *s, struct value *res); int eval_name(const struct format *fmt, const char *s, struct value *res);
int eval_set(const struct format *fmt, const char *s, struct value *res); int eval_set(const struct format *fmt, const char *s, struct value *res);
@ -91,6 +96,12 @@ int comp_rel(const struct value *a, enum relop relop, const struct value *b);
int compare(const struct format *fmt, int compare(const struct format *fmt,
const struct value *a, enum relop relop, const struct value *b); const struct value *a, enum relop relop, const struct value *b);
void dump_name(FILE *file, const struct format *fmt, const struct value *v);
void dump_set(FILE *file, const struct format *fmt, const struct value *v);
void dump_abs(FILE *file, const struct format *fmt, const struct value *v);
void dump_rel(FILE *file, const struct format *fmt, const struct value *v);
void dump(FILE *file, const struct format *fmt, const struct value *v);
extern const struct param_ops param_ops_name; extern const struct param_ops param_ops_name;
extern const struct param_ops param_ops_set; extern const struct param_ops param_ops_set;
extern const struct param_ops param_ops_abs; extern const struct param_ops param_ops_abs;