lotus / jison /measureLayout.jison
k-l-lambda's picture
updated asset files.
8f6ab9b
%{
const root = (type, data) => ({__prototype: "MesaureLayout", type, data});
const singleLayout = n => ({__prototype: "SingleMLayout", measure: Number(n)});
const blockLayout = seq => ({__prototype: "BlockMLayout", seq});
const voltaBlock = (times, body, alternates) => ({__prototype: "VoltaMLayout", times: Number(times), body, alternates});
const abaBlock = (main, rest) => ({__prototype: "ABAMLayout", main, rest});
const segment = n => ({segment: true, length: Number(n)});
const alternates = items => items.map(item => {
if (item.__prototype === "BlockMLayout")
return item.seq;
return [item];
});
const range = (start, end) => {
start = Number(start);
end = Number(end);
if (!(end >= start))
throw new Error(`invalid measure range: ${start}..${end}`);
return Array(end + 1 - start).fill(0).map((_, i) => singleLayout(start + i));
};
const serializeSeq = (item, options) => {
if (item.segment) {
const index = options.index;
options.index += item.length;
return Array(item.length).fill(0).map((_, i) => singleLayout(index + i));
}
return [serialize(item, options)];
};
const serialize = (item, options = {index: 1}) => {
const speard = seq => [].concat(...seq.map(it => serializeSeq(it, options)));
switch (item.__prototype) {
case "BlockMLayout":
item.seq = speard(item.seq);
break;
case "VoltaMLayout":
item.body = speard(item.body);
item.alternates = item.alternates && item.alternates.map(speard);
break;
case "ABAMLayout":
item.main = serialize(item.main, options);
item.rest = speard(item.rest);
break;
}
return item;
};
%}
%lex
%option flex unicode
A [a-z]
N [1-9]
N0 [0-9]
UNSIGNED {N}{N0}*
WORD {A}+
SPECIAL [*,\[\]<>{}]
%%
\s+ {} // spaces
{SPECIAL} return yytext;
{UNSIGNED} return 'UNSIGNED'
{WORD}":" return yytext
".." return yytext
<<EOF>> return 'EOF';
/lex
%start start_symbol
%%
start_symbol
: measure_layout EOF
{
return $1;
}
;
measure_layout
: index_wise_measure_layout
{$$ = root(null, $1);}
| 'i:' index_wise_measure_layout
{$$ = root("index-wise", $2);}
| 's:' segment_wise_measure_layout
{$$ = root("segment-wise", serialize($2));}
;
index_wise_measure_layout
: iw_sequence
{
if ($1.length === 1 && $1[0].__prototype === "BlockMLayout")
$$ = $1[0];
else
$$ = blockLayout($1);
}
;
iw_sequence
: iw_item
{$$ = [$1];}
| range
{$$ = $1;}
| iw_sequence ',' iw_item
{$$ = [...$1, $3];}
| iw_sequence ',' range
{$$ = [...$1, ...$3];}
;
range
: UNSIGNED '..' UNSIGNED
{$$ = range($1, $3);}
;
iw_item
: single
{$$ = $1;}
| iw_block_item
{$$ = $1;}
| iw_volta
{$$ = $1;}
| iw_aba
{$$ = $1;}
;
single
: UNSIGNED
{$$ = singleLayout($1);}
;
iw_block_item
: iw_block
{$$ = blockLayout($1);}
;
iw_block
: '[' iw_sequence ']'
{$$ = $2;}
;
iw_volta
: UNSIGNED '*' iw_block iw_optional_alternates
{$$ = voltaBlock($1, $3, $4);}
;
iw_optional_alternates
: %empty
{$$ = null;}
| iw_alternates
{$$ = $1;}
;
iw_alternates
: '{' iw_sequence '}'
{$$ = alternates($2);}
;
iw_aba
: '<' iw_item ',' iw_sequence '>'
{$$ = abaBlock($2, $4);}
;
segment_wise_measure_layout
: sw_sequence
{
if ($1.length === 1 && $1[0].__prototype === "BlockMLayout")
$$ = $1[0];
else
$$ = blockLayout($1);
}
;
sw_sequence
: sw_item
{$$ = [$1];}
| sw_sequence sw_item
{$$ = [...$1, $2];}
;
sw_item
: segment
{$$ = blockLayout([$1]);}
| sw_block_item
{$$ = $1;}
| sw_volta
{$$ = $1;}
| sw_aba
{$$ = $1;}
;
segment
: UNSIGNED
{$$ = segment($1);}
;
sw_block_item
: sw_block
{$$ = blockLayout($1);}
;
sw_block
: '[' sw_sequence ']'
{$$ = $2;}
;
sw_volta
: UNSIGNED '*' sw_block sw_optional_alternates
{$$ = voltaBlock($1, $3, $4);}
;
sw_optional_alternates
: %empty
{$$ = null;}
| sw_alternates
{$$ = $1;}
;
sw_alternates
: '{' sw_sequence '}'
{$$ = alternates($2);}
;
sw_aba
: '<' sw_item sw_sequence '>'
{$$ = abaBlock($2, $3);}
;