meta {
f64 := [f64: bool] => str("f64");
str := [str: bool] => str("str");
bool := [bool: bool] => str("bool");
ty := select {f64, str, bool};
type := [opt: opt[bool], ty <- ty]
=> {op: "type", val: ty, optional: opt == some(true)};
ref := [rule: str, as: opt[str]]
=> {op: "ref", rule: rule, as: as};
type_or_ref := select {type, ref};
field := [name: str, tr <- type_or_ref]
=> if tr.op == "type" {
{name: name, type: tr.val, optional: tr.optional}
} else {
{name: name, ref: {rule: tr.rule, as: tr.as}}
};
rep_fields := repeat field:"field";
expr := [code: str] => code;
fields := [fs <- rep_fields, expr <- expr:"expr"]
=> {op: "fields", fields: fs, expr: expr};
repeat := [ref <- ref]
=> {op: "repeat", rule: ref.rule, as: ref.as};
sel := repeat ref:"ref";
select := [sel <- sel]
=> {op: "select", rules: sel};
rule := select {
fields:"fields",
repeat:"repeat",
select:"select"
};
decl := [name: str, rule <- rule:"rule"]
=> if rule.op == "fields" {
{name: name, fields: rule.fields, expr: rule.expr}
} else if rule.op == "repeat" {
{name: name, repeat: {rule: rule.rule, as: rule.as}}
} else if rule.op == "select" {
{name: name, select: rule.rules}
};
rules := repeat decl:"decl";
doc := [rules <- rules:"rules", start: str]
=> {rules: rules, start: start};
-----------------------------------------------------------
doc
}