phpeggy
Version:
PHP target for Peggy parser generator
242 lines (224 loc) • 7.45 kB
JavaScript
"use strict";
module.exports = function(useCache) {
return [
"private function peg_cleanup_state(): void",
"{",
...useCache
? [" $this->peg_cache = [];"]
: [],
" $this->peg_currPos = 0;",
" $this->peg_reportedPos = 0;",
" $this->peg_cachedPos = 0;",
" $this->peg_cachedPosDetails = new pegCachedPosDetails();",
" $this->peg_maxFailPos = 0;",
" $this->peg_maxFailExpected = [];",
" $this->peg_silentFails = 0;",
" $this->input = [];",
" $this->input_length = 0;",
" $this->options = [];",
' $this->peg_source = "";',
"}",
"",
"private function input_substr(",
" int $start,",
" int $length",
"): string {",
" if ($length === 1 && $start < $this->input_length) {",
" return $this->input[$start];",
" }",
' $substr = "";',
" $max = \\min($start + $length, $this->input_length);",
" for ($i = $start; $i < $max; $i++) {",
" $substr .= $this->input[$i];",
" }",
" return $substr;",
"}",
"",
"private function text(): string",
"{",
" return $this->input_substr($this->peg_reportedPos, $this->peg_currPos - $this->peg_reportedPos);",
"}",
"",
"private function offset(): int",
"{",
" return $this->peg_reportedPos;",
"}",
"",
"private function range(): pegRange",
"{",
" return new pegRange($this->peg_source, $this->peg_reportedPos, $this->peg_currPos);",
"}",
"",
"private function location(",
" bool $fail = false",
"): pegLocation {",
" $start = $this->peg_reportedPos;",
" $end = $this->peg_currPos;",
" if ($fail) {",
" $start = $this->peg_maxFailPos;",
" $end = $this->peg_maxFailPos + ($this->peg_maxFailPos < \\count($this->input) ? 1 : 0);",
" }",
" $compute_pd_start = clone $this->peg_computePosDetails($start);",
" $compute_pd_end = clone $this->peg_computePosDetails($end);",
"",
" return new pegLocation(",
" $this->peg_source,",
" new pegPosition($start, $compute_pd_start->line, $compute_pd_start->column),",
" new pegPosition($end, $compute_pd_end->line, $compute_pd_end->column),",
" );",
"}",
"",
"private function line(): int",
"{",
" return $this->peg_computePosDetails($this->peg_reportedPos)->line;",
"}",
"",
"private function column(): int",
"{",
" return $this->peg_computePosDetails($this->peg_reportedPos)->column;",
"}",
"",
"/**",
" * @throws SyntaxError",
" */",
"private function expected(",
" string $description,",
" ?int $where = null",
"): void {",
" throw $this->peg_buildException(",
" null,",
' [new pegExpectation("other", $description)],',
" $where ?? $this->peg_reportedPos",
" );",
"}",
"",
"/**",
" * @throws SyntaxError",
" */",
"private function error(",
" string $message,",
" ?int $where = null",
"): void {",
" throw $this->peg_buildException(",
" $message,",
" null,",
" $where ?? $this->peg_reportedPos,",
" );",
"}",
"",
"private function peg_advancePos(",
" pegCachedPosDetails $details,",
" int $startPos,",
" int $endPos",
"): void {",
" for ($p = $startPos; $p < $endPos; $p++) {",
" $ch = $this->input_substr($p, 1);",
' if ($ch === "\\n") {',
" if (!$details->seenCR) {",
" $details->line++;",
" }",
" $details->column = 1;",
" $details->seenCR = false;",
' } elseif ($ch === "\\r" || $ch === "\\u2028" || $ch === "\\u2029") {',
" $details->line++;",
" $details->column = 1;",
" $details->seenCR = true;",
" } else {",
" $details->column++;",
" $details->seenCR = false;",
" }",
" }",
"}",
"",
"private function peg_computePosDetails(",
" int $pos",
"): pegCachedPosDetails {",
" if ($this->peg_cachedPos !== $pos) {",
" if ($this->peg_cachedPos > $pos) {",
" $this->peg_cachedPos = 0;",
" $this->peg_cachedPosDetails = new pegCachedPosDetails();",
" }",
" $this->peg_advancePos($this->peg_cachedPosDetails, $this->peg_cachedPos, $pos);",
" $this->peg_cachedPos = $pos;",
" }",
"",
" return $this->peg_cachedPosDetails;",
"}",
"",
"private function peg_fail(",
" pegExpectation $expected",
"): void {",
" if ($this->peg_currPos < $this->peg_maxFailPos) {",
" return;",
" }",
"",
" if ($this->peg_currPos > $this->peg_maxFailPos) {",
" $this->peg_maxFailPos = $this->peg_currPos;",
" $this->peg_maxFailExpected = [];",
" }",
"",
" $this->peg_maxFailExpected[] = $expected;",
"}",
"",
"private function peg_buildException_expectedComparator(",
" pegExpectation $a,",
" pegExpectation $b",
"): int {",
" return $a->description <=> $b->description;",
"}",
"",
"/** @param pegExpectation[]|null $expected */",
"private function peg_buildException(",
" ?string $message,",
" ?array $expected,",
" int $pos",
"): SyntaxError {",
" $posDetails = $this->peg_computePosDetails($pos);",
" $found = $pos < $this->input_length ? $this->input[$pos] : null;",
"",
" if ($expected !== null) {",
' \\usort($expected, [$this, "peg_buildException_expectedComparator"]);',
" $i = 1;",
// This works because the bytecode generator guarantees that every
// expectation object exists only once, so it's enough to use |===| instead
// of deeper structural comparison.
" while ($i < \\count($expected)) {",
" if ($expected[$i - 1] === $expected[$i]) {",
" \\array_splice($expected, $i, 1);",
" } else {",
" $i++;",
" }",
" }",
" }",
"",
" if ($message === null && $expected !== null) {",
" $expectedDescs = \\array_fill(0, \\count($expected), null);",
"",
" for ($i = 0; $i < \\count($expected); $i++) {",
" $expectedDescs[$i] = $expected[$i]->description;",
" }",
"",
" $expectedDesc = \\count($expected) > 1",
' ? \\implode(", ", \\array_slice($expectedDescs, 0, -1))',
' . " or "',
' . ($expectedDescs[\\count($expected) - 1] ?? "")',
' : $expectedDescs[0] ?? "";',
"",
' $foundDesc = $found === null ? "end of input" : \\json_encode($found, JSON_THROW_ON_ERROR);',
"",
' $message = \\sprintf("Expected %s but %s found.", $expectedDesc, $foundDesc);',
" }",
"",
" return new SyntaxError(",
" $message,",
" $expected,",
' $found ?? "",',
" $pos,",
" $posDetails->line,",
" $posDetails->column,",
" $this->location(true)",
" );",
"}",
"",
];
};