Skip to content

Repository files navigation

Parser

Character-by-character string parsing library.

https://travis-ci.com/kuria/parser.svg?branch=master
  • line number tracking (can be disabled for performance)
  • supports CR, LF and CRLF line endings
  • verbose exceptions
  • many methods to navigate and operate the parser
    • forward / backward peeking and seeking
    • forward / backward character consumption
    • state stack
  • character types
  • expectations
  • PHP 7.1+

Create a new parser instance with string input.

The parser begins at the first character.

<?phpuseKuria\Parser\Parser;
$input = 'foo bar baz';
$parser = newParser($input);

The parser has several public properties that can be used to inspect its current state:

  • $parser->i - current position
  • $parser->char - current character (or NULL at the end of input)
  • $parser->lastChar - last character (or NULL at the start of input)
  • $parser->line - current line (or NULL if line tracking is disabled)
  • $parser->end - end of input indicator (TRUE at the end, FALSE otherwise)
  • $parser->vars - user-defined variables attached to the current state

Warning

All of the public properties (with the exception of $parser->vars) are read-only and must not be modified directly by the calling code.

Use the built-in parser methods to mutate the parser state. See Parser method overview.

Refer to doc comments of the respective methods for more information.

Also see Character types.

Static methods

  • getCharType($char): int - determine character type
  • getCharTypeName($charType): string - get human-readable character type name

Instance methods

  • getInput(): string - get the input string
  • setInput($input): void - replace the input string (this also resets the parser)
  • getLength(): int - get length of the input string
  • isTrackingLineNumbers(): bool - see if line number tracking is enabled
  • type(): int - get type of the current character
  • is(...$types): bool - check whether the current character is of one of the specified types
  • atNewline(): bool - see if the parser is at the start of a newline sequence
  • eat(): ?string - go to the next character and return the current one (returns NULL at the end)
  • spit(): ?string - go to the previous character and return the current one (returns NULL at the beginning)
  • shift(): ?string - go to the next character and return it (returns NULL at the end)
  • unshift(): ?string - go to the previous character and return it (returns NULL at the beginning)
  • peek($offset, $absolute = false): ?string - get character at the given offset or absolute position (does not affect state)
  • seek($offset, $absolute = false): void - alter current position
  • reset(): void - reset states, vars and rewind to the beginning
  • rewind(): void - rewind to the beginning
  • eatChar($char): ?string - consume specific character and return the next character
  • tryEatChar(): bool - attempt to consume specific character and return success state
  • eatType($type): string - consume all characters of the specified type
  • eatTypes($typeMap): string - consume all characters of the specified types
  • eatWs(): string - consume whitespace, if any
  • eatUntil($delimiterMap, $skipDelimiter = true, $allowEnd = false): string - consume all characters until the specified delimiters
  • eatUntilEol($skip = true): string - consume all character until end of line or input
  • eatEol(): string - consume end of line sequence
  • eatRest(): string - consume reamaining characters
  • getChunk($start, $end): string - get chunk of the input (does not affect state)
  • detectEol(): ?string - find and return the next end of line sequence (does not affect state)
  • countStates(): int - get number of stored states
  • pushState(): void - store the current state
  • revertState(): void - revert to the last stored state and pop it
  • popState(): void - pop the last stored state without reverting to it
  • clearStates(): void - throw away all stored states
  • expectEnd(): void - ensure that the parser is at the end
  • expectNotEnd(): void - ensure that the parser is not at the end
  • expectChar($expectedChar): void - ensure that the current character matches the expectation
  • expectCharType($expectedType): void - ensure that the current character is of the given type
<?phpuseKuria\Parser\Parser;
/** * INI parser (example) */class IniParser
{
/** * Parse an INI string */publicfunctionparse(string$string): array
{
// create parser$parser = newParser($string);
// prepare variables$data = [];
$currentSection = null;
// parsewhile (!$parser->end) {
// skip whitespace$parser->eatWs();
if ($parser->end) {
break;
}
// parse the current thingif ($parser->char === '[') {
// a section$currentSection = $this->parseSection($parser);
} elseif ($parser->char === ';') {
// a comment$this->skipComment($parser);
} else {
// a key=value pair
[$key, $value] = $this->parseKeyValue($parser);
// add to outputif ($currentSection === null) {
$data[$key] = $value;
} else {
$data[$currentSection][$key] = $value;
}
}
}
return$data;
}
/** * Parse a section and return its name */privatefunctionparseSection(Parser$parser): string
{
// we should be at the [ character now, eat it$parser->eatChar('[');
// eat everything until ]$sectionName = $parser->eatUntil(']');
return$sectionName;
}
/** * Skip a commented-out line */privatefunctionskipComment(Parser$parser): void
{
// we should be at the ; character now, eat it$parser->eatChar(';');
// eat everything until the end of line$parser->eatUntilEol();
}
/** * Parse a key=value pair */privatefunctionparseKeyValue(Parser$parser): array
{
// we should be at the first character of the key// eat characters until = is found$key = $parser->eatUntil('=');
// eat everything until the end of line// that is our value$value = trim($parser->eatUntilEol());
return [$key, $value];
}
}

Using the parser

<?php$iniParser = newIniParser();
$iniString = <<<INI; An example commentname=Footype=Bar[options]size=150x100onload=INI;
$data = $iniParser->parse($iniString);
print_r($data);

Output:

Array
(
[name] => Foo
[type] => Bar
[options] => Array
(
[size] => 150x100
[onload] =>
)
)

The table below lists the default character types.

These types are available as constants on the Parser class:

  • Parser::C_NONE - no character (NULL)
  • Parser::C_WS - whitespace (tab, linefeed, vertical tab, form feed, carriage return and space)
  • Parser::C_NUM - numeric character (0-9)
  • Parser::C_STR - string character (a-z, A-Z, _ and any 8-bit char)
  • Parser::C_CTRL - control character (ASCII 127 and ASCII < 32 except whitespace)
  • Parser::C_SPECIAL - !"#$%&'()*+,-./:;<=>?@[\\]^\`{|}~
#CharacterType
NULLnoneC_NONE
00x00C_CTRL
10x01C_CTRL
20x02C_CTRL
30x03C_CTRL
40x04C_CTRL
50x05C_CTRL
60x06C_CTRL
70x07C_CTRL
80x08C_CTRL
9\tC_WS
10\nC_WS
11\vC_WS
12\fC_WS
13\rC_WS
140x0eC_CTRL
150x0fC_CTRL
160x10C_CTRL
170x11C_CTRL
180x12C_CTRL
190x13C_CTRL
200x14C_CTRL
210x15C_CTRL
220x16C_CTRL
230x17C_CTRL
240x18C_CTRL
250x19C_CTRL
260x1aC_CTRL
270x1bC_CTRL
280x1cC_CTRL
290x1dC_CTRL
300x1eC_CTRL
310x1fC_CTRL
320x20C_WS
33!C_SPECIAL
34"C_SPECIAL
35#C_SPECIAL
36$C_SPECIAL
37%C_SPECIAL
38&C_SPECIAL
39'C_SPECIAL
40(C_SPECIAL
41)C_SPECIAL
42*C_SPECIAL
43+C_SPECIAL
44,C_SPECIAL
45-C_SPECIAL
46.C_SPECIAL
47/C_SPECIAL
480C_NUM
491C_NUM
502C_NUM
513C_NUM
524C_NUM
535C_NUM
546C_NUM
557C_NUM
568C_NUM
579C_NUM
58:C_SPECIAL
59;C_SPECIAL
60<C_SPECIAL
61=C_SPECIAL
62>C_SPECIAL
63?C_SPECIAL
64@C_SPECIAL
65AC_STR
66BC_STR
67CC_STR
68DC_STR
69EC_STR
70FC_STR
71GC_STR
72HC_STR
73IC_STR
74JC_STR
75KC_STR
76LC_STR
77MC_STR
78NC_STR
79OC_STR
80PC_STR
81QC_STR
82RC_STR
83SC_STR
84TC_STR
85UC_STR
86VC_STR
87WC_STR
88XC_STR
89YC_STR
90ZC_STR
91[C_SPECIAL
92\C_SPECIAL
93]C_SPECIAL
94^C_SPECIAL
95_C_STR
96`C_SPECIAL
97aC_STR
98bC_STR
99cC_STR
100dC_STR
101eC_STR
102fC_STR
103gC_STR
104hC_STR
105iC_STR
106jC_STR
107kC_STR
108lC_STR
109mC_STR
110nC_STR
111oC_STR
112pC_STR
113qC_STR
114rC_STR
115sC_STR
116tC_STR
117uC_STR
118vC_STR
119wC_STR
120xC_STR
121yC_STR
122zC_STR
123{C_SPECIAL
124|C_SPECIAL
125}C_SPECIAL
126~C_SPECIAL
1270x7fC_CTRL
1280x80C_STR
1290x81C_STR
1300x82C_STR
1310x83C_STR
1320x84C_STR
1330x85C_STR
1340x86C_STR
1350x87C_STR
1360x88C_STR
1370x89C_STR
1380x8aC_STR
1390x8bC_STR
1400x8cC_STR
1410x8dC_STR
1420x8eC_STR
1430x8fC_STR
1440x90C_STR
1450x91C_STR
1460x92C_STR
1470x93C_STR
1480x94C_STR
1490x95C_STR
1500x96C_STR
1510x97C_STR
1520x98C_STR
1530x99C_STR
1540x9aC_STR
1550x9bC_STR
1560x9cC_STR
1570x9dC_STR
1580x9eC_STR
1590x9fC_STR
1600xa0C_STR
1610xa1C_STR
1620xa2C_STR
1630xa3C_STR
1640xa4C_STR
1650xa5C_STR
1660xa6C_STR
1670xa7C_STR
1680xa8C_STR
1690xa9C_STR
1700xaaC_STR
1710xabC_STR
1720xacC_STR
1730xadC_STR
1740xaeC_STR
1750xafC_STR
1760xb0C_STR
1770xb1C_STR
1780xb2C_STR
1790xb3C_STR
1800xb4C_STR
1810xb5C_STR
1820xb6C_STR
1830xb7C_STR
1840xb8C_STR
1850xb9C_STR
1860xbaC_STR
1870xbbC_STR
1880xbcC_STR
1890xbdC_STR
1900xbeC_STR
1910xbfC_STR
1920xc0C_STR
1930xc1C_STR
1940xc2C_STR
1950xc3C_STR
1960xc4C_STR
1970xc5C_STR
1980xc6C_STR
1990xc7C_STR
2000xc8C_STR
2010xc9C_STR
2020xcaC_STR
2030xcbC_STR
2040xccC_STR
2050xcdC_STR
2060xceC_STR
2070xcfC_STR
2080xd0C_STR
2090xd1C_STR
2100xd2C_STR
2110xd3C_STR
2120xd4C_STR
2130xd5C_STR
2140xd6C_STR
2150xd7C_STR
2160xd8C_STR
2170xd9C_STR
2180xdaC_STR
2190xdbC_STR
2200xdcC_STR
2210xddC_STR
2220xdeC_STR
2230xdfC_STR
2240xe0C_STR
2250xe1C_STR
2260xe2C_STR
2270xe3C_STR
2280xe4C_STR
2290xe5C_STR
2300xe6C_STR
2310xe7C_STR
2320xe8C_STR
2330xe9C_STR
2340xeaC_STR
2350xebC_STR
2360xecC_STR
2370xedC_STR
2380xeeC_STR
2390xefC_STR
2400xf0C_STR
2410xf1C_STR
2420xf2C_STR
2430xf3C_STR
2440xf4C_STR
2450xf5C_STR
2460xf6C_STR
2470xf7C_STR
2480xf8C_STR
2490xf9C_STR
2500xfaC_STR
2510xfbC_STR
2520xfcC_STR
2530xfdC_STR
2540xfeC_STR
2550xffC_STR

Character types can be customized by extending the base Parser class.

The following example changes "-" and "." from CHAR_SPECIAL to CHAR_STR and inherits everything else.

<?phpclass CustomParser extends Parser
{
constCHAR_TYPE_MAP = [
'-' => self::C_STR,
'.' => self::C_STR,
] + parent::CHAR_TYPE_MAP; // inherit everything else
}
// usage example$parser = newCustomParser('foo-bar.baz');
var_dump($parser->eatType(CustomParser::C_STR));

Output:

string(11) "foo-bar.baz"

About

Character-by-character string parsing library

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Used by

Contributors

Languages