UNPKG

@fink/larix

Version:

A parser for generating fink's AST.

182 lines (158 loc) 4.31 kB
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); };