UNPKG

@fink/prattler

Version:

A generic Pratt/top down operator precedence parser.

148 lines (143 loc) 2.81 kB
import { add_error } from "./errors.js"; export const auto = { auto: true }; export const error_nud = ctx => { const { curr_token } = ctx; const { value } = curr_token; return add_error(ctx, `Unexpected token \`${value}\` at start of expression.`, curr_token); }; export const error_led = ctx => { const { curr_token } = ctx; const { value } = curr_token; return add_error(ctx, `Cannot use \`${value}\` as an infix operator.`, curr_token); }; export const left_binding = token_type => ({ token_type, nud: () => error_nud, lbp: lbp => () => lbp, led: () => error_led }); export const non_binding = token_type => ({ token_type, nud: () => error_nud, lbp: () => () => 0, led: () => error_led }); export const add_expr = (expr_builder, lbp_value) => ({ expr_builders, ...ctx }) => { const { next_lbp, lbps, nuds, leds } = expr_builders; let _do_result; ˆmatch_2: { const ˆvalue_1 = lbp_value; if (ˆvalue_1 === auto) { _do_result = next_lbp; break ˆmatch_2; } { _do_result = lbp_value; break ˆmatch_2; } } const final_lbp_value = _do_result; _do_result = undefined; const { token_type, nud, lbp, led } = expr_builder; return { ...ctx, expr_builders: { next_lbp: next_lbp + 2, nuds: { ...nuds, [token_type]: nud(final_lbp_value) }, lbps: { ...lbps, [token_type]: lbp(final_lbp_value) }, leds: { ...leds, [token_type]: led(final_lbp_value) } } }; }; export const add_ignorable = token_type => ({ igns, ...ctx }) => ({ ...ctx, igns: { ...igns, [token_type]: true } }); export const add_separator = expr_builder => add_expr(expr_builder, 0); export const add_operator = expr_builder => add_expr(expr_builder, auto); export const add_identifier = expr_builder => add_expr(expr_builder, auto); export const add_literal = expr_builder => add_expr(expr_builder, auto); export const is_ignorable = (ctx, token) => ctx.igns[token.type] === true; export const nud = ctx => { const { curr_token: { type }, expr_builders: { nuds } } = ctx; const { [type]: nud_fn } = nuds; return nud_fn(ctx); }; export const led = (ctx, left) => { const { curr_token: { type }, expr_builders: { leds } } = ctx; const { [type]: led_fn } = leds; return led_fn(ctx, left); }; export const next_lbp = (ctx, left) => { const { next_token: { type }, expr_builders: { lbps } } = ctx; const { [type]: lbp_fn } = lbps; return lbp_fn(ctx, left); }; export const init_expr_builders = () => ({ next_lbp: 2, nuds: {}, lbps: { end: () => 0 }, leds: {}, igns: {} });