nishimura/laiz-parsec

View on GitHub
src/fast.php

Summary

Maintainability
F
5 days
Test Coverage
<?php

namespace Laiz\Parsec;

use Laiz\Func\Maybe;
use Laiz\Func\Any;
use function Laiz\Func\Maybe\fromJust;
use function Laiz\Parsec\Stream\uncons;

function _runParser(Parser $p, State $state)
{
    $call = []; // function: [goto label, context]
    $args = []; // function arguments
    $context = []; // function context: function foo() use(...$context)
    $ret = null; // return value

    $call = $p->unParser();
    $args = [$state,
             ['_call_cok', []], ['_call_cerr', []],
             ['_call_eok', []], ['_call_eerr', []]];
    goto _call;

_call_cok:
    $ret = new Consumed(CConsumed, new Reply\Ok(...$args)); goto _ret;
_call_cerr:
    $ret = new Consumed(CConsumed, new Reply\Error(...$args)); goto _ret;
_call_eok:
    $ret = new Consumed(CEmpty, new Reply\Ok(...$args)); goto _ret;
_call_eerr:
    $ret = new Consumed(CEmpty, new Reply\Error(...$args)); goto _ret;

_call_ret:
    $call = $args[3];
    $args = [$context[0], $args[0], unknownError($args[0])];
    goto _call;

_call_zero:
    $call = $args[4];
    $args = [unknownError($args[0])];
    goto _call;

_call_plus:
    $call = $context[0]->unParser();
    $args = [$args[0], $args[1], $args[2], $args[3],
             ['_call_plus_meerr',
              [$args[0], $context[1], $args[1], $args[2], $args[3], $args[4]]]];
    goto _call;

    _call_plus_meerr:
    $call = $context[1]->unParser();
    $args = [$context[0], $context[2], $context[3],
             ['_call_plus_neok', [$context[4], $args[0]]],
             ['_call_plus_neerr', [$context[5], $args[0]]]];
    goto _call;

    _call_plus_neok:
    $call = $context[0];
    $args = [$args[0], $args[1], mergeError($context[1], $args[2])];
    goto _call;

    _call_plus_neerr:
    $call = $context[0];
    $args = [mergeError($context[1], $args[0])];
    goto _call;


_call_map:
    $call = $context[1]->unParser();
    $args = [$args[0],
             ['_call_map_cok', [$args[1], $context[0]]],
             $args[2],
             ['_call_map_eok', [$args[3], $context[0]]],
             $args[4]];
    goto _call;

    _call_map_cok:
    $call = $context[0];
    $args = [$context[1]($args[0]), $args[1], $args[2]];
    goto _call;
    _call_map_eok:
    $call = $context[0];
    $args = [$context[1]($args[0]), $args[1], $args[2]];
    goto _call;

_call_bind:
    $call = $context[0]->unParser();
    $args = [
        $args[0],
        ['_call_bind_mcok', [$context[0], $context[1], $args[1], $args[2]]],
        $args[2],
        ['_call_bind_meok', [$context[0], $context[1], $args[1], $args[2],
                             $args[3], $args[4]]],
        $args[4]
    ];
    goto _call;

    _call_bind_mcok:
        ;
        $any = $context[1]($args[0]);
        if ($any instanceof Any)
            $any = $any->cast($context[0]);
        $call = $any->unParser();
        $args = [
            $args[1], $context[2], $context[3],
            ['_call_bind_mcok_peok', [$context[2], $args[2]]],
            ['_call_bind_mcok_peerr', [$context[3], $args[2]]]
        ];
        goto _call;

        _call_bind_mcok_peok:
            ;
            $call = $context[0];
            $args = [$args[0], $args[1], mergeError($context[1], $args[2])];
            goto _call;
        _call_bind_mcok_peerr:
            ;
            $call = $context[0];
            $args = [mergeError($context[1], $args[0])];
            goto _call;

    _call_bind_meok:
        $any = $context[1]($args[0]);
        if ($any instanceof Any)
            $any = $any->cast($context[0]);
        $call = $any->unParser();
        $args = [
            $args[1], $context[2], $context[3],
            ['_call_bind_meok_peok', [$context[4], $args[2]]],
            ['_call_bind_meok_peerr', [$context[5], $args[2]]]
        ];
        ;
        goto _call;

        _call_bind_meok_peok:
            ;
            $call = $context[0];
            $args = [$args[0], $args[1], mergeError($context[1], $args[2])];
            goto _call;
        _call_bind_meok_peerr:
            ;
            $call = $context[0];
            $args = [mergeError($context[1], $args[0])];
            goto _call;
    ;



_call_unexpected:
    $call = $args[4];
    $args = [newErrorMessage(new Message(UnExpect, $context[0]),
                             $args[0]->pos())];
    goto _call;


_call_tokenprim:
    $input = $args[0]->input();
    if (is_string($input))
        $m = \Laiz\Parsec\Stream\TypeString::uncons($input);
    else if (is_array($input))
        $m = \Laiz\Parsec\Stream\TypeArray::uncons($input);
    else
        $m = uncons($input);
    if ($m instanceof Maybe\Nothing){
        $call = $args[4];
        $args = [unexpectError('', $args[0]->pos())];
        goto _call;
    }

    list($c, $cs) = $m->fromJust();
    $r = $context[3]($c);
    if ($r instanceof Maybe\Nothing){
        $call = $args[4];
        $args = [unexpectError($context[0]($c), $args[0]->pos())];
        goto _call;
    }

    $newpos = $context[1]($args[0]->pos(), $c, $cs);
    if ($context[2] instanceof Maybe\Nothing){
        $newuser = $args[0]->user();
    }else{
        $nextState = $context[2]->fromJust();
        $newuser = $nextState($args[0]->pos(), $c, $cs, $args[0]->user());
    }
    $newstate = new State($cs, $newpos, $newuser);

    $x = $r->fromJust();
    $call = $args[1];
    $args = [$x, $newstate, newErrorUnknown($newpos)];
    goto _call;


_call_labels:
    $call = $context[0]->unParser();
    $args = [$args[0], $args[1], $args[2],
             ['_call_labels_eok', [$args[3], $context[1]]],
             ['_call_labels_eerr', [$args[4], $context[1]]]];
    goto _call;

    _call_labels_eok:
    if (!errorIsUnknown($args[2]))
        $args[2] = setExpectErrors($args[2], $context[1]);
    $call = $context[0];
    goto _call;

    _call_labels_eerr:
    $call = $context[0];
    $args = [setExpectErrors($args[0], $context[1])];
    goto _call;


_call_tokens:
    $showTokens = $context[4];
    $tts = $context[0];
    $s = $args[0];
    $errEof = function() use ($showTokens, $tts, $s){
        return setErrorMessage(
            new Message(Expect, $showTokens($tts)),
            newErrorMessage(new Message(SysUnExpect, ''), $s->pos()));
    };
    $errExpect = function($x) use ($showTokens, $tts, $s){
        return setErrorMessage(
            new Message(Expect, $showTokens($tts)),
            newErrorMessage(new Message(SysUnExpect, $showTokens([$x])), $s->pos()));
    };

    $input = $s->input();
    if (is_string($input))
        $r = \Laiz\Parsec\Stream\TypeString::uncons($input);
    else if (is_array($input))
        $r = \Laiz\Parsec\Stream\TypeArray::uncons($input);
    else
        $r = uncons($input);
    if ($r instanceof Maybe\Nothing){
        $call = $args[4];
        $args = [$errEof()];
        goto _call;
    }else{
        list($x, $xs) = $r->fromJust();
        if ($context[1] === $x){
            $call = ['_call_tokens_walk',
                     [['_call_tokens_ok', [$tts, $args[1], $context[3], $s]],
                      $args[2],
                      $errEof, $errExpect]];
            $args = [$context[2], $xs];
            goto _call;
        }else{
            $call = $args[4];
            $args = [$errExpect($x)];
            goto _call;
        }
    }
    throw new \Exception('Logic Error: _call_tokens');

    _call_tokens_ok:
    $pos2 = $context[2]($context[3]->pos(), $context[0]);
    $s2 = new State($args[0], $pos2, $context[3]->user());
    $call = $context[1];
    $args = [$context[0], $s2, newErrorUnknown($pos2)];
    goto _call;

    _call_tokens_walk:
    if (is_string($args[0]))
        $m = \Laiz\Parsec\Stream\TypeString::uncons($args[0]);
    else if (is_array($args[0]))
        $m = \Laiz\Parsec\Stream\TypeArray::uncons($args[0]);
    else
        $m = uncons($args[0]);
    if ($m instanceof Maybe\Nothing){
        $call = $context[0];
        $args = [$args[1]];
        goto _call;
    }

    list($t, $ts) = $m->fromJust();
    if (is_string($args[1]))
        $rm = \Laiz\Parsec\Stream\TypeString::uncons($args[1]);
    else if (is_array($args[1]))
        $rm = \Laiz\Parsec\Stream\TypeArray::uncons($args[1]);
    else
        $rm = uncons($args[1]);
    if ($rm instanceof Maybe\Nothing){
        $call = $context[1];
        $args = [$context[2]()];
        goto _call;
    }else{
        list($x, $xs) = $rm->fromJust();
        if ($t === $x){
            $args = [$ts, $xs];
            goto _call;
        }else{
            $call = $context[1];
            $args = [$context[3]($x)];
            goto _call;
        }
    }
    throw new \Exception('Logic Error: _call_tokens_walk');

    _call_tokens_empty:
    $call = $args[3];
    $args = [[], $args[0], unknownError($args[0])];
    goto _call;


_call_try:
    $call = $context[0]->unParser();
    $args = [$args[0], $args[1], $args[4], $args[3], $args[4]];
    goto _call;


_call_many_accum:
    $call = $context[1]->unParser();
    $args = [
        $args[0],
        ['_call_many_accum_walk',
         [[], $context[0], $context[1], $args[0], $args[1], $args[2]]],
        $args[2],
        manyErr(),
        ['_call_many_accum_ok', [$args[3], $args[0]]]
    ];
    goto _call;


    _call_many_accum_walk:
    $call = $context[2]->unParser();
    $args = [
        $args[1],
        ['_call_many_accum_walk',
         [$context[1]($args[0], $context[0]),
          $context[1], $context[2], $context[3], $context[4], $context[5]]],
        $context[5],
        manyErr(),
        ['_call_many_accum_walk_ok',
         [$context[4], $context[1], $args[0], $context[0], $args[1]]]
    ];
    // use context[0] instead of curried function <walk x>
    goto _call;

    _call_many_accum_walk_ok:
    $call = $context[0];
    $args = [$context[1]($context[2], $context[3]), $context[4], $args[0]];
    goto _call;

    _call_many_accum_ok:
    $call = $context[0];
    $args = [[], $context[1], $args[0]];
    goto _call;





_call_update_parser_state:
    $call = $args[3];
    $s2 = $context[0]($args[0]);
    $args = [$s2, $s2, unknownError($s2)];
    goto _call;


_call_preg:
    $input = $args[0]->input();
    if ($input === ''){
        $call = $args[4];
        $args = [unexpectError('', $args[0]->pos())];
        goto _call;
    }
    if (!preg_match($context[0], $input, $matches)){
        $call = $args[4];
        $args = [unexpectError($input[0], $args[0]->pos())];
        goto _call;
    }
    $newpos = updatePosString($args[0]->pos(), $matches[0]);
    $newinput = substr($input, strlen($matches[0]));
    $newstate = new State($newinput, $newpos, $args[0]->user());
    $call = $args[1];
    $args = [$matches, $newstate, newErrorUnknown($newpos)];
    goto _call;

    _call:
    if (!is_array($call))
        throw new \Exception('error:' . print_r($call, true)); // BUG
    list($label, $context) = $call;

    if ($label === '_call_ret') goto _call_ret;
    if ($label === '_call_cok') goto _call_cok;
    if ($label === '_call_cerr') goto _call_cerr;
    if ($label === '_call_eok') goto _call_eok;
    if ($label === '_call_eerr') goto _call_eerr;

    if ($label === '_call_map') goto _call_map;
    if ($label === '_call_map_cok') goto _call_map_cok;
    if ($label === '_call_map_eok') goto _call_map_eok;

    if ($label === '_call_bind') goto _call_bind;
    if ($label === '_call_bind_mcok') goto _call_bind_mcok;
    if ($label === '_call_bind_mcok_peok') goto _call_bind_mcok_peok;
    if ($label === '_call_bind_mcok_peerr') goto _call_bind_mcok_peerr;
    if ($label === '_call_bind_meok') goto _call_bind_meok;
    if ($label === '_call_bind_meok_peok') goto _call_bind_meok_peok;
    if ($label === '_call_bind_meok_peerr') goto _call_bind_meok_peerr;

    if ($label === '_call_zero') goto _call_zero;
    if ($label === '_call_plus') goto _call_plus;
    if ($label === '_call_plus_meerr') goto _call_plus_meerr;
    if ($label === '_call_plus_neok') goto _call_plus_neok;
    if ($label === '_call_plus_neerr') goto _call_plus_neerr;

    if ($label === '_call_unexpected') goto _call_unexpected;


    if ($label === '_call_tokenprim') goto _call_tokenprim;
    if ($label === '_call_labels') goto _call_labels;
    if ($label === '_call_labels_eok') goto _call_labels_eok;
    if ($label === '_call_labels_eerr') goto _call_labels_eerr;

    if ($label === '_call_tokens') goto _call_tokens;
    if ($label === '_call_tokens_ok') goto _call_tokens_ok;
    if ($label === '_call_tokens_walk') goto _call_tokens_walk;
    if ($label === '_call_tokens_empty') goto _call_tokens_empty;

    if ($label === '_call_try') goto _call_try;
    if ($label === '_call_many_accum') goto _call_many_accum;
    if ($label === '_call_many_accum_walk') goto _call_many_accum_walk;
    if ($label === '_call_many_accum_ok') goto _call_many_accum_ok;
    if ($label === '_call_many_accum_walk_ok') goto _call_many_accum_walk_ok;

    if ($label === '_call_update_parser_state') goto _call_update_parser_state;
    if ($label === '_call_preg') goto _call_preg;
    goto _ret;



    _ret:
    return $ret;
}

// used in _call_labels
function setExpectErrors(ParseError $err, $msgs){
    if (count($msgs) === 0)
        return setErrorMessage(new Message(Expect, ''), $err);

    $msg = array_shift($msgs);
    $ret = setErrorMessage(new Message(Expect, $msg), $err);

    // foldr
    for ($i = count($msgs) - 1; $i >= 0; $i--){
        $ret = addErrorMessage(new Message(Expect, $msgs[$i]), $ret);
    }
    return $ret;
}