private function compilePattern(int $line, array $tokens) : Parser { if (!$tokens) { $this->fail(self::E_EMPTY_PATTERN, $line); } $ts = TokenStream::fromSlice($tokens); traverse(either(consume(chain(token(T_NS_SEPARATOR), token(T_NS_SEPARATOR), parentheses()->as('cloaked')))->onCommit(function (Ast $result) use($ts) { $ts->inject(TokenStream::fromSequence(...$result->cloaked)); $ts->skip(...TokenStream::SKIPPABLE); }), rtoken('/^(T_\\w+)·(\\w+)$/')->onCommit(function (Ast $result) { $token = $result->token(); $id = $this->lookupCapture($token); $type = $this->lookupTokenType($token); $this->parsers[] = token($type)->as($id); }), ($parser = chain(rtoken('/^·\\w+$/')->as('parser_type'), token('('), optional(ls(either(future($parser)->as('parser'), string()->as('string'), rtoken('/^T_\\w+·\\w+$/')->as('token'), rtoken('/^T_\\w+$/')->as('constant'), word()->as('word')), token(',')))->as('args'), commit(token(')')), optional(rtoken('/^·\\w+$/')->as('label'))))->onCommit(function (Ast $result) { $this->parsers[] = $this->compileParser($result->array()); }), $this->layer('{', '}', braces()), $this->layer('[', ']', brackets()), $this->layer('(', ')', parentheses()), rtoken('/^···(\\w+)$/')->onCommit(function (Ast $result) { $id = $this->lookupCapture($result->token()); $this->parsers[] = layer()->as($id); }), token(T_STRING, '·')->onCommit(function (Ast $result) use($ts) { $offset = \count($this->parsers); if (0 !== $this->dominance || 0 === $offset) { $this->fail(self::E_BAD_DOMINANCE, $offset, $result->token()->line()); } $this->dominance = $offset; }), rtoken('/·/')->onCommit(function (Ast $result) { $token = $result->token(); $this->fail(self::E_BAD_CAPTURE, $token, $token->line()); }), any()->onCommit(function (Ast $result) { $this->parsers[] = token($result->token()); })))->parse($ts); // check if macro dominance '·' is last token if ($this->dominance === \count($this->parsers)) { $this->fail(self::E_BAD_DOMINANCE, $this->dominance, $ts->last()->line()); } $this->specificity = \count($this->parsers); if ($this->specificity > 1) { if (0 === $this->dominance) { $pattern = chain(...$this->parsers); } else { /* dominat macros are partially wrapped in commit()s and dominance is the offset used as the 'event horizon' point... once the entry point is matched, there is no way back and a parser error arises */ $prefix = array_slice($this->parsers, 0, $this->dominance); $suffix = array_slice($this->parsers, $this->dominance); $pattern = chain(...array_merge($prefix, array_map(commit::class, $suffix))); } } else { /* micro optimization to save one function call for every token on the subject token stream whenever the macro pattern consists of a single parser */ $pattern = $this->parsers[0]; } return $pattern; }
<?php require "../settings.php"; require "gw-common.php"; error_reporting(E_ALL); if (isset($_REQUEST["key"])) { switch ($_REQUEST["key"]) { case "display": $OUTPUT = display(); break; case "future": $OUTPUT = future(); break; case "remove": $OUTPUT = remove(); break; } } else { $OUTPUT = display(); } require "gw-tmpl.php"; function display() { extract($_REQUEST); $fields = array(); $fields["human_date"] = date("D jS M Y"); // eg: Mon 2nd Aug 2006 extract($fields, EXTR_SKIP); $sql = "SELECT * FROM cubit.today WHERE date<=now()"; $today_rslt = db_exec($sql) or errDie("Unable to retrieve today."); $today_out = "";
private function compileParserArgs(array $args) : array { $compiled = []; foreach ($args as $label => $arg) { switch ((string) $label) { case 'this': $compiled[] = future($this->pattern); break; case 'token': $type = $this->lookupTokenType($arg); $label = $this->lookupCapture($arg); $compiled[] = token($type)->as($label); break; case 'label': $compiled[] = token($arg); break; case 'parser': $compiled[] = $this->compileParser($arg['type'], $arg['args'], $arg['label']); break; case 'string': $compiled[] = trim((string) $arg, '"\''); break; case 'constant': // T_* $compiled[] = $this->lookupTokenType($arg); break; case 'function': // function(...){...} $arglist = implode('', $arg['args']); $body = implode('', $arg['body']); $compiled[] = eval("return function({$arglist}){ {$body} };"); break; default: $compiled = array_merge($compiled, $this->compileParserArgs($arg)); } } return $compiled; }