@fink/larix
Version:
A parser for generating fink's AST.
182 lines (158 loc) • 4.31 kB
JavaScript
import { _in_ } from "@fink/js-interop/runtime.js";
import { next_is, has_errors, advance } from "@fink/prattler/parser.js";
import { add_error } from "@fink/prattler/errors.js";
import { add_operator, add_separator } from "@fink/prattler/expressions.js";
import { keywords } from "../../lexer/tokens.js";
import { prefix, terminator } from "../expressions.js";
import { terminated_block, add_named_block } from "../block/init.js";
import { single_expression } from "../block/expr.js";
import { identifier } from "../identifier/init.js";
export const value_expr = ctx => {
const ˆvalue_1 = ctx;
/* istanbul ignore else */
if (next_is(ˆvalue_1, `:`)) {
{
const next_ctx = advance(ctx);
return single_expression(next_ctx, 0);
}
}
{
return [false, ctx];
}
};
export const key_expr = ctx => {
const ˆvalue_3 = ctx.next_token;
/* istanbul ignore else */
if (ˆvalue_3 != null) {
const {
type: ˆp_5
} = ˆvalue_3;
/* istanbul ignore else */
if (_in_(ˆp_5, [`ident`, `...`, `(`, `str-start`])) {
return single_expression(ctx, 0);
}
}
// TODO should this be {value: ? in keywords} and be the first match?
/* istanbul ignore else */
if (ˆvalue_3 != null) {
const {
type: ˆp_6
} = ˆvalue_3;
// TODO should this be {value: ? in keywords} and be the first match?
/* istanbul ignore else */
if (_in_(ˆp_6, keywords)) {
return identifier(advance(ctx));
}
}
{
return add_error(ctx, `Expected record-key but found '${ctx.next_token.value}'.`, ctx.next_token);
}
};
export const get_key_val = (ctx, key_or_default) => {
const ˆvalue_7 = ctx;
/* istanbul ignore else */
if (has_errors(ˆvalue_7)) {
{
const left = key_or_default;
return [left, ctx];
}
}
{
{
let _do_result;
ˆmatch_10: {
const ˆvalue_9 = key_or_default;
/* istanbul ignore else */
if (ˆvalue_9 != null) {
const {
type: ˆp_11
} = ˆvalue_9;
/* istanbul ignore else */
if (ˆp_11 === `assign`) {
_do_result = [key_or_default.left, key_or_default, ctx];
break ˆmatch_10;
}
}
{
{
key_or_default;
const [value, next_ctx] = value_expr(ctx);
_do_result = [key_or_default, value, next_ctx];
}
break ˆmatch_10;
}
}
const [key, value, next_ctx] = _do_result;
_do_result = undefined;
const {
start
} = key.loc;
let _do_result2;
ˆmatch_13: {
const ˆvalue_12 = value;
/* istanbul ignore else */
if (ˆvalue_12 === false) {
_do_result2 = key.loc;
break ˆmatch_13;
}
{
_do_result2 = value.loc;
break ˆmatch_13;
}
}
const {
end
} = _do_result2;
_do_result2 = undefined;
return [{
type: `rec:kv`,
left: key,
right: value,
loc: {
start,
end
}
}, next_ctx];
}
}
};
export const key_val_expr = ctx => {
const [key_or_default, value_ctx] = key_expr(ctx);
{
const ˆvalue_14 = key_or_default;
/* istanbul ignore else */
if (ˆvalue_14 != null) {
const {
type: ˆp_16
} = ˆvalue_14;
/* istanbul ignore else */
if (ˆp_16 === `spread`) {
return [key_or_default, value_ctx];
}
}
{
return get_key_val(value_ctx, key_or_default);
}
}
};
export const record = token_type => ({ ...prefix(token_type),
nud: () => ctx => {
const [{
exprs,
loc
}, next_ctx] = terminated_block(ctx, `}`, key_val_expr);
return [{
type: `rec`,
exprs,
loc
}, next_ctx];
}
});
export const add_record = ctx => {
let ˆpipe_result_17 = ctx;
ˆpipe_result_17 = add_operator(record(`{`))(ˆpipe_result_17);
ˆpipe_result_17 = add_separator(terminator(`,`))(ˆpipe_result_17);
ˆpipe_result_17 = add_separator(terminator(`:`))(ˆpipe_result_17);
ˆpipe_result_17 = add_separator(terminator(`}`))(ˆpipe_result_17);
return ˆpipe_result_17 = add_named_block(`rec`, `rec`, key_val_expr)(ˆpipe_result_17);
};