Skip to content

Instantly share code, notes, and snippets.

@mathiasverraes
Created October 7, 2022 09:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mathiasverraes/5c4d116d0ae41468ade5d6ca02fa11b2 to your computer and use it in GitHub Desktop.
Save mathiasverraes/5c4d116d0ae41468ade5d6ca02fa11b2 to your computer and use it in GitHub Desktop.
Output of my live coding impro at Full Stack Europe 2022
<?php declare(strict_types=1);
// @mathiasverraes
// parser is a function that takes some input and returns (either (structured value AND remainder) OR error)
// parser is a function that takes some input and returns a Result
$a = function ($input) {
$parsed = substr($input, 0, 1);
$remainder = substr($input, 1);
if ($parsed === 'a') return succeed($parsed, $remainder); else return fail("expected a");
};
$char = function (string $char) {
return function ($input) use ($char) {
$parsed = substr($input, 0, 1);
$remainder = substr($input, 1);
if ($parsed === $char) return succeed($parsed, $remainder); else return fail("expected $char");
};
};
$seq = function ($p1, $p2) {
return function ($input) use ($p1, $p2) {
$r1 = $p1($input);
if ($r1->isSuccess()) {
$r2 = $p2($r1->remainder());
return $r2;
} else {
return $r1;
}
};
};
$append = function ($p1, $p2) {
return function ($input) use ($p1, $p2) {
$r1 = $p1($input);
if ($r1->isSuccess()) {
$r2 = $p2($r1->remainder());
if ($r2->isSuccess()) {
return succeed($r1->parsed() . $r2->parsed(), $r2->remainder());
}
return $r2;
} else {
return $r1;
}
};
};
$either = function ($p1, $p2) {
return function ($input) use ($p1, $p2) {
$r1 = $p1($input);
if ($r1->isSuccess()) {
return $r1;
} else {
return $p2($input);
}
};
};
$map = function ($parser, $map) {
return function ($input) use ($map, $parser) {
$r = $parser($input);
if ($r->isSuccess()) {
return succeed($map($r->parsed()), $r->remainder());
} else {
return $r;
}
};
};
final class Result
{
private $parsed;
private $remainder;
private $error;
private bool $success = false;
private function __construct()
{
}
public function parsed()
{
return $this->parsed;
}
public function remainder()
{
return $this->remainder;
}
public function isSuccess(): bool
{
return $this->success;
}
public function isFail(): bool
{
return !$this->success;
}
public function error()
{
return $this->error;
}
public static function succeed($parsed, $remainder): Result
{
$r = (new Result());
$r->success = true;
$r->parsed = $parsed;
$r->remainder = $remainder;
return $r;
}
public static function fail(string $error): Result
{
$r = (new Result());
$r->success = false;
$r->error = $error;
return $r;
}
}
function fail(string $error)
{
return Result::fail($error);
}
function succeed($parsed, $remainder)
{
return Result::succeed($parsed, $remainder);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment