1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-07-03 01:15:29 +03:00
eda-tools/b2/lang.y
2012-05-01 14:57:12 -03:00

555 lines
7.3 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 "db.h"
#include "lang.h"
#include "y.tab.h"
static struct action hierarchy;
static struct currency *curr;
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;
int num;
double fnum;
struct equiv *equiv;
struct names *names;
struct format *format;
enum relop relop;
struct field *field;
struct selector *sel;
struct condition *cond;
struct action act;
struct part *part;
struct param *param;
struct price *price;
struct stock *stock;
struct provider *prov;
};
%token START_HIERARCHY START_CHAR START_INVENTORY
%token START_EXCHANGE START_PROVIDERS
%token TOK_LE TOK_GE TOK_NL
%token <s> WORD
%type <num> int
%type <fnum> float
%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
%type <part> part inventory_item
%type <param> param params
%type <price> prices price
%type <stock> stock
%type <prov> providers provider
%%
all:
START_HIERARCHY hierarchy
| START_CHAR characteristics
| START_INVENTORY inventory
| START_EXCHANGE exchange
| START_PROVIDERS providers
;
/* ----- Characteristics hierarchy ----------------------------------------- */
hierarchy:
nameset hierarchy
| action
{
hierarchy = $1;
field_dump(stderr, $1.fields);
field_dump(stderr, $1.rules);
}
;
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
{
$$ = new_selector();
$$->cond = $1;
$$->act = $3;
$$->next = $4;
}
;
conditions:
condition
{
$$ = $1;
}
| condition '|' conditions
{
$$ = $1;
$$->next = $3;
}
;
condition:
opt_relop WORD
{
$$ = new_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
{
$$ = new_field($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);
}
;
/* ----- Part characteristics --------------------------------------------- */
characteristics:
| TOK_NL
| part characteristics
{
part_finalize($1, &hierarchy);
part_dump(stderr, $1);
}
;
part:
WORD WORD params TOK_NL
{
$$ = part_add($1, $2);
if ($$->param)
yyerror("parameters already defined");
$$->param = $3;
}
;
params:
{
$$ = NULL;
}
| param params
{
$$ = $1;
$$->next = $2;
}
;
param:
WORD '=' WORD
{
$$ = alloc_type(struct param);
$$->u.name = $1;
$$->value.u.name = $3;
}
;
/* ----- Part inventory ---------------------------------------------------- */
inventory:
| TOK_NL
| inventory_item inventory
{
part_dump(stderr, $1);
}
;
inventory_item:
WORD WORD stock TOK_NL
{
$$ = part_add($1, $2);
part_add_stock($$, $3);
}
;
stock:
WORD int int WORD float prices
{
$$ = alloc_type(struct stock);
$$->cat = $1;
$$->avail = $2;
$$->package = $3;
$$->curr = currency_lookup($4);
if (!$$->curr)
yyerrorf("unknown currency %s", $4);
$$->add = $5;
$$->price = $6;
}
;
prices:
price
{
$$ = $1;
}
| price prices
{
$$ = $1;
$$->next = $2;
}
;
price:
int float
{
$$ = alloc_type(struct price);
$$->qty = $1;
$$->value = $2;
$$->next = NULL;
}
;
int:
WORD
{
char *end;
$$ = strtol($1, &end, 10);
if (*end)
yyerrorf("\"%s\" is not an integer", $1);
}
;
float:
WORD
{
char *end;
$$ = strtod($1, &end);
if (*end)
yyerrorf("\"%s\" is not a number", $1);
}
;
/* ----- Currency exchange ------------------------------------------------- */
exchange:
| TOK_NL
| currency exchange
;
currency:
WORD
{
curr = currency_add($1);
}
rates TOK_NL
;
rates:
| rate rates
;
rate:
WORD float
{
const struct currency *to;
/* add and not lookup, since we just introduce the
currency here */
to = currency_add($1);
currency_exchange(curr, to, $2);
}
;
/* ----- Providers --------------------------------------------------------- */
providers:
{
$$ = NULL;
}
| TOK_NL
{
$$ = NULL;
}
| provider providers
{
$$ = $1;
$$->next = $2;
}
;
provider:
WORD WORD float float TOK_NL
{
$$ = provider_add($1);
$$->curr = currency_add($2);
$$->shipping = $3;
$$->minimum = $4;
}
;