mirror of
git://projects.qi-hardware.com/eda-tools.git
synced 2024-11-05 07:32:49 +02:00
335 lines
4.2 KiB
Plaintext
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 = ¶m_ops_name;
|
|
}
|
|
| '<' WORD '>'
|
|
{
|
|
$$ = alloc_type(struct format);
|
|
$$->ops = ¶m_ops_set;
|
|
$$->u.set = find_nameset($2);
|
|
if (!$$->u.set)
|
|
yyerrorf("unknown name set \"%s\"", $2);
|
|
}
|
|
| '#' WORD
|
|
{
|
|
$$ = alloc_type(struct format);
|
|
$$->ops = ¶m_ops_abs;
|
|
$$->u.abs = $2;
|
|
}
|
|
| '%' WORD
|
|
{
|
|
$$ = alloc_type(struct format);
|
|
$$->ops = ¶m_ops_rel;
|
|
$$->u.rel = field_find($2, top_field());
|
|
if (!$$->u.rel)
|
|
yyerrorf("unknown field \"%s\"", $2);
|
|
}
|
|
;
|