php-dextrin

Parser
in package

FinalYes

Hand-written recursive-descent `.dxn` parser -- the reverse of {@see Printer}, built directly on {@see Lexer}'s token stream.

A struct decodes against a compiled schema when $registry has one for that name (Validator::materialize(), same as the binary decoder); with no registry, or no schema registered for that name, it decodes to an opaque DXNStruct. Same story for a non-built-in tag against the registry's own tag table -- falls back to DXNCustomTag -- never a hard failure, matching dxn/DXN.md ยง1.4's "opaque tagged value, not an error" contract.

Table of Contents

Constants

BUILT_IN_TAGS  : mixed = ['ordered' => true, 'sorted-set' => true, 'arra...

Properties

$pos  : int
$registry  : Registry|null
$tokens  : array<int, Token>

Methods

parse()  : mixed
__construct()  : mixed
advance()  : Token
advanceAnd()  : mixed
Advances past the current token (already matched by the caller) and returns `$value` -- for literals with no token property worth extracting.
at()  : bool
Reads `$this->pos`, mutable parser state -- PHPStan otherwise assumes a "pure" method called twice with the same argument returns the same result both times, which doesn't hold here once something between the two calls (typically `next()`) advances the cursor.
buildMap()  : array<int|string, mixed>
dispatchTag()  : mixed
flagsStringToArray()  : array<string, bool>
isDiscard()  : bool
materializeStruct()  : mixed
next()  : Token
parseArrayTag()  : array<int, mixed>
parseAt()  : mixed
`@{...}` (set), or `@identifier value` (tag_form). Discard is already stripped in {@see self::parseValue()}.
parseBracketedItems()  : array<int, mixed>
parseBytesTag()  : DXNBytes
parseCharToken()  : DXNChar
parseDocument()  : mixed
Top-level entry: optional header, then exactly one value.
parseEntries()  : array<int, array{0: mixed, 1: mixed}>
`{map_entry*}`, ordered pairs -- used by both `map_lit` and `struct_keyed`. The colon-shorthand key (`MAP_KEY` token) is keyword-typed per the grammar (`name: value` and `:name => value` are the exact same value), so it's wrapped as {@see DXNKeyword} here just like an explicit `:name` would be -- callers (map vs struct) each reduce that down to whatever shape they actually need.
parseFloatToken()  : float
parseKeywordToken()  : DXNKeyword
parseList()  : DXNList
parseOrderedTag()  : DXNOrderedMap
parsePercent()  : mixed
`%{...}` (map) or `%Name{...}`/`%Name[...]` (struct).
parseRationalToken()  : DXNRational
parseRegexToken()  : DXNRegex
parseSet()  : DXNSet
parseSortedSetTag()  : DXNSortedSet
parseStringValue()  : string
parseTuple()  : DXNTuple
parseValue()  : mixed
`value = {skip}, value_body` -- `skip` here is only ever a discard; comments never reach the token stream.
parseValueBody()  : mixed
peek()  : Token
skipDiscards()  : void
structFieldName()  : string
tryConsumeHeader()  : void

Constants

BUILT_IN_TAGS

private mixed BUILT_IN_TAGS = ['ordered' => true, 'sorted-set' => true, 'array' => true, 'uuid' => true, 'uri' => true, 'bytes' => true, 'datetime' => true, 'duration' => true]

Properties

Methods

parse()

public static parse(string $text[, Registry|null $registry = null ]) : mixed
Parameters
$text : string
$registry : Registry|null = null

advanceAnd()

Advances past the current token (already matched by the caller) and returns `$value` -- for literals with no token property worth extracting.

private advanceAnd(mixed $value) : mixed
Parameters
$value : mixed

at()

Reads `$this->pos`, mutable parser state -- PHPStan otherwise assumes a "pure" method called twice with the same argument returns the same result both times, which doesn't hold here once something between the two calls (typically `next()`) advances the cursor.

private at(string $type) : bool
Parameters
$type : string
Tags
phpstan-impure
Return values
bool

buildMap()

private buildMap(array<int, array{0: mixed, 1: mixed}> $pairs) : array<int|string, mixed>
Parameters
$pairs : array<int, array{0: mixed, 1: mixed}>
Return values
array<int|string, mixed>

dispatchTag()

private dispatchTag(string $name, int $offset) : mixed
Parameters
$name : string
$offset : int

flagsStringToArray()

private static flagsStringToArray(string $flags) : array<string, bool>
Parameters
$flags : string
Return values
array<string, bool>

isDiscard()

private isDiscard() : bool
Return values
bool

materializeStruct()

private materializeStruct(string $name, DXNStruct $struct) : mixed
Parameters
$name : string
$struct : DXNStruct

next()

private next(string $type) : Token
Parameters
$type : string
Return values
Token

parseArrayTag()

private parseArrayTag(int $offset) : array<int, mixed>
Parameters
$offset : int
Return values
array<int, mixed>

parseAt()

`@{...}` (set), or `@identifier value` (tag_form). Discard is already stripped in {@see self::parseValue()}.

private parseAt() : mixed

parseBracketedItems()

private parseBracketedItems(string $open, string $close) : array<int, mixed>
Parameters
$open : string
$close : string
Return values
array<int, mixed>

parseBytesTag()

private parseBytesTag(string $name, int $offset) : DXNBytes
Parameters
$name : string
$offset : int
Return values
DXNBytes

parseDocument()

Top-level entry: optional header, then exactly one value.

private parseDocument() : mixed

parseEntries()

`{map_entry*}`, ordered pairs -- used by both `map_lit` and `struct_keyed`. The colon-shorthand key (`MAP_KEY` token) is keyword-typed per the grammar (`name: value` and `:name => value` are the exact same value), so it's wrapped as {@see DXNKeyword} here just like an explicit `:name` would be -- callers (map vs struct) each reduce that down to whatever shape they actually need.

private parseEntries() : array<int, array{0: mixed, 1: mixed}>
Return values
array<int, array{0: mixed, 1: mixed}>

parseFloatToken()

private parseFloatToken(string $text) : float
Parameters
$text : string
Return values
float

parsePercent()

`%{...}` (map) or `%Name{...}`/`%Name[...]` (struct).

private parsePercent() : mixed

parseStringValue()

private parseStringValue(string $tagName, int $offset) : string
Parameters
$tagName : string
$offset : int
Return values
string

parseValue()

`value = {skip}, value_body` -- `skip` here is only ever a discard; comments never reach the token stream.

private parseValue() : mixed

parseValueBody()

private parseValueBody() : mixed

skipDiscards()

private skipDiscards() : void

structFieldName()

private structFieldName(mixed $key) : string
Parameters
$key : mixed
Return values
string

tryConsumeHeader()

private tryConsumeHeader() : void
On this page

Search results