1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-05 07:32:49 +02:00
eda-tools/b2/lang.y

335 lines
4.2 KiB
Plaintext

%{
/*
* lang.y - BOOM grammar
*
* 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 <assert.h>
#include "util.h"
#include "param.h"
#include "chr.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;
}
%}
%union {
const char *s;
struct equiv *equiv;
struct names *names;
struct format *format;
enum relop relop;
struct field *field;
struct selector *sel;
struct condition *cond;
struct action act;
};
%token TOK_LE TOK_GE
%token <s> WORD
%type <equiv> nameqs
%type <names> names nameq
%type <format> format
%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:
rule
{
field_dump(stderr, $1);
}
| nameset all
;
nameset:
'<' WORD '>' '=' names ';'
{
register_nameset($2, $5);
}
;
names:
nameq
{
$$ = $1;
}
| nameq '<' names
{
$$ = $1;
$$->next = $3;
}
;
nameq:
nameqs
{
$$ = alloc_type(struct names);
$$->equiv = $1;
$$->next = NULL;
}
;
nameqs:
WORD
{
$$ = alloc_type(struct equiv);
$$->name = $1;
$$->next = NULL;
}
| WORD '=' nameqs
{
$$ = alloc_type(struct equiv);
$$->name = $1;
$$->next = $3;
}
;
/*
* @@@ for now, we can't select on a collective of fields. maybe later, with
* a syntax change.
*
rules:
{
$$ = NULL;
}
| rule rules
{
$$ = $1;
$$->next = $2;
}
;
*/
opt_rule:
{
$$ = NULL;
}
| rule
{
$$ = $1;
}
;
rule:
field
{
$1->prev = top_field();
push_field($1);
}
'{' selectors opt_wildcard '}'
{
$$ = $1;
$$->sel = $4;
$$->any = $5;
$$->next = NULL;
field_finalize($$);
pop_field();
}
;
selectors:
{
$$ = NULL;
}
| conditions ':' action selectors
{
$$ = field_selector();
$$->cond = $1;
$$->act = $3;
$$->next = $4;
}
;
conditions:
condition
{
$$ = $1;
}
| condition '|' conditions
{
$$ = $1;
$$->next = $3;
}
;
condition:
opt_relop WORD
{
$$ = field_condition($1, $2);
}
;
opt_wildcard:
{
$$.fields = NULL;
$$.rules = NULL;
}
| '*' ':' action
{
$$ = $3;
}
;
action:
{
push_field(top_field());
}
opt_fields opt_rule ';'
{
$$.fields = $2;
$$.rules = $3;
pop_field();
}
;
opt_relop:
{
$$ = rel_eq;
}
| relop
{
$$ = $1;
}
;
relop:
'='
{
$$ = rel_eq;
}
| '<'
{
$$ = rel_le;
}
| '>'
{
$$ = rel_gt;
}
| TOK_LE
{
$$ = rel_le;
}
| TOK_GE
{
$$ = rel_ge;
}
;
opt_fields:
{
$$ = NULL;
}
| '{' fields '}'
{
$$ = $2;
}
;
fields:
{
$$ = NULL;
}
| field
{
push_field($1);
}
fields
{
$$ = $1;
$$->next = $3;
pop_field();
$$->prev = top_field();
if ($3)
$3->prev = $1;
}
;
field:
WORD '=' format
{
$$ = field_new($1, $3, top_field());
}
;
format:
'*'
{
$$ = alloc_type(struct format);
$$->ops = &param_ops_name;
}
| '<' WORD '>'
{
$$ = alloc_type(struct format);
$$->ops = &param_ops_set;
$$->u.set = find_nameset($2);
if (!$$->u.set)
yyerrorf("unknown name set \"%s\"", $2);
}
| '#' WORD
{
$$ = alloc_type(struct format);
$$->ops = &param_ops_abs;
$$->u.abs = $2;
}
| '%' WORD
{
$$ = alloc_type(struct format);
$$->ops = &param_ops_rel;
$$->u.rel = field_find($2, top_field());
if (!$$->u.rel)
yyerrorf("unknown field \"%s\"", $2);
}
;