UNPKG

@fink/prattler

Version:

A generic Pratt/top down operator precedence parser.

257 lines (213 loc) 4.51 kB
const { is_empty } = require("@fink/std-lib/iter.js"); const { next, iter, unfold, filter } = require("@fink/std-lib/iter.js"); const { init_expr_builders, is_ignorable, next_lbp, led, nud } = require("./expressions.js"); const { add_error } = require("./errors.js"); const start_token = { start: true, loc: { start: { pos: 0, line: 1, column: 0 }, end: { pos: 0, line: 1, column: 0 } } }; exports.start_token = start_token; const has_errors = ctx => { const ˆvalue_1 = ctx; if (ˆvalue_1 != null) { const { errors: ˆp_3 } = ˆvalue_1; if (!is_empty(ˆp_3)) { return true; } } { return false; } }; exports.has_errors = has_errors; const curr_value = ({ curr_token }) => curr_token.value; exports.curr_value = curr_value; const curr_loc = ({ curr_token }) => curr_token.loc; exports.curr_loc = curr_loc; const next_value = ({ next_token }) => next_token.value; exports.next_value = next_value; const next_loc = ({ next_token }) => next_token.loc; exports.next_loc = next_loc; const next_is = (ctx, expected) => expected === next_value(ctx); exports.next_is = next_is; const next_is_end = ctx => { const ˆvalue_4 = ctx; if (ˆvalue_4 != null) { const { next_token: ˆp_6 } = ˆvalue_4; if (ˆp_6 != null) { const { type: ˆp_7 } = ˆp_6; if (ˆp_7 === `end`) { return true; } } } // {tokens: {done: true}}: // console.log '>>>>>' // true { return false; } }; exports.next_is_end = next_is_end; const advance = (..._args) => { while (true) { const [ctx] = _args; const { next_token: curr_token, tokens, ignored_tokens } = ctx; { const ˆvalue_8 = curr_token; if (ˆvalue_8 != null) { const { type: ˆp_10 } = ˆvalue_8; if (ˆp_10 === `end`) { return { ...ctx, curr_token }; } } { { const [next_token, next_tokens] = next(tokens); { const ˆvalue_11 = next_token; if (is_ignorable(ctx, ˆvalue_11)) { _args = [{ ...ctx, tokens: next_tokens, ignored_tokens: [...ignored_tokens, next_token] }]; continue; } { { const next_ctx = { ...ctx, tokens: next_tokens, curr_token, next_token, ignored_tokens }; return next_ctx; } } } } } } } }; exports.advance = advance; const expression = (ctx, rbp) => { const ˆvalue_13 = ctx; if (next_is_end(ˆvalue_13)) { return add_error(ctx, `Unexpected end of code.`, ctx.curr_token); } { { let _do_result; { let ˆpipe_result_15 = ctx; ˆpipe_result_15 = advance(ˆpipe_result_15); ˆpipe_result_15 = nud(ˆpipe_result_15); ˆpipe_result_15 = unfold(([left, ctx]) => { const ˆvalue_16 = ctx; if (has_errors(ˆvalue_16)) { return [left, ctx, true]; } if (rbp < next_lbp(ˆvalue_16, left)) { { const led_ctx = advance(ctx); const [next_left, next_ctx] = led(led_ctx, left); return [next_left, next_ctx, false]; } } { return [left, ctx, true]; } })(ˆpipe_result_15); _do_result = ˆpipe_result_15 = filter(([,, found]) => found)(ˆpipe_result_15); } const [[left, next_ctx]] = _do_result; _do_result = undefined; return [left, next_ctx]; } } }; exports.expression = expression; const init_parser = ({ code, filename, tokens }) => { const expr_builders = init_expr_builders(); const start_loc = { pos: 0, line: 1, column: 0 }; return { code, filename, tokens: iter(tokens), curr_token: { loc: { start: start_loc, end: start_loc } }, next_token: { loc: { start: start_loc, end: start_loc } }, ignored_tokens: [], expr_builders, errors: [] }; }; exports.init_parser = init_parser; const start_parser = ctx => advance(ctx); exports.start_parser = start_parser;