mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-16 20:54:40 +02:00
b2/: first tentative version of hierarchy parser, with example
This commit is contained in:
parent
7fe553a4fc
commit
6bb8b03ef8
7
b2/HIERARCHY
Normal file
7
b2/HIERARCHY
Normal 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 };
|
||||||
|
}
|
@ -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
|
||||||
|
50
b2/boom.c
50
b2/boom.c
@ -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
208
b2/chr.c
@ -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 == ¶m_ops_name)
|
||||||
|
fprintf(file, "*");
|
||||||
|
else if (field->fmt->ops == ¶m_ops_set)
|
||||||
|
dump_set_decl(file, field->fmt->u.set);
|
||||||
|
else if (field->fmt->ops == ¶m_ops_abs)
|
||||||
|
fprintf(file, "#%s", field->fmt->u.abs);
|
||||||
|
else if (field->fmt->ops == ¶m_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 != ¶m_ops_set)
|
dump_fields(file, field, 0);
|
||||||
;//yyerrorf("
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void field_add_wildcard(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
45
b2/chr.h
45
b2/chr.h
@ -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
63
b2/dump.c
Normal 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);
|
||||||
|
}
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
166
b2/lang.y
@ -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 = ¶m_ops_rel;
|
$$->ops = ¶m_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);
|
||||||
}
|
}
|
||||||
|
41
b2/param.c
41
b2/param.c
@ -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, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
11
b2/param.h
11
b2/param.h
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user