Skip to content
Open
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "3.4-dev"
"dev-master": "3.5-dev"
}
}
}
4 changes: 2 additions & 2 deletions src/Neon/Decoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public function parseToNode(string $input): Node
{
$lexer = new Lexer;
$parser = new Parser;
$tokens = $lexer->tokenize($input);
return $parser->parse($tokens);
$stream = $lexer->tokenize($input);
return $parser->parse($stream);
}
}
9 changes: 9 additions & 0 deletions src/Neon/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,13 @@
*/
class Exception extends \Exception
{
public ?Position /*readonly*/ $position = null;


public function __construct(string $message, ?Position $position = null, ?\Throwable $previous = null)
{
$message .= $position ? ' ' . $position : '';
$this->position = $position;
parent::__construct($message, 0, $previous);
}
}
32 changes: 26 additions & 6 deletions src/Neon/Lexer.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,25 +56,45 @@ public function tokenize(string $input): TokenStream
}

$types = array_keys(self::Patterns);
$offset = 0;
$position = new Position;

$tokens = [];
foreach ($matches as $match) {
$type = $types[count($match) - 2];
$tokens[] = new Token($match[0], $type === Token::Char ? $match[0] : $type);
$offset += strlen($match[0]);
$tokens[] = new Token($type === Token::Char ? $match[0] : $type, $match[0], $position);
$position = $this->advance($position, $match[0]);
}

$tokens[] = new Token(Token::End, '', $position);

$stream = new TokenStream($tokens);
if ($offset !== strlen($input)) {
$s = str_replace("\n", '\n', substr($input, $offset, 40));
$stream->error("Unexpected '$s'", count($tokens));
if ($position->offset !== strlen($input)) {
$s = str_replace("\n", '\n', substr($input, $position->offset, 40));
throw new Exception("Unexpected '$s'", $position);
}

return $stream;
}


private function advance(Position $position, string $str): Position
{
if ($lines = substr_count($str, "\n")) {
return new Position(
$position->line + $lines,
strlen($str) - strrpos($str, "\n"),
$position->offset + strlen($str),
);
} else {
return new Position(
$position->line,
$position->column + strlen($str),
$position->offset + strlen($str),
);
}
}


public static function requiresDelimiters(string $s): bool
{
return preg_match('~[\x00-\x1F]|^[+-.]?\d|^(true|false|yes|no|on|off|null)$~Di', $s)
Expand Down
4 changes: 2 additions & 2 deletions src/Neon/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ abstract class Node implements \IteratorAggregate
{
public ?int $startTokenPos = null;
public ?int $endTokenPos = null;
public ?int $startLine = null;
public ?int $endLine = null;
public ?Position $start = null;
public ?Position $end = null;


abstract public function toValue(): mixed;
Expand Down
9 changes: 9 additions & 0 deletions src/Neon/Node/LiteralNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,13 @@ public function toString(): string
throw new \LogicException;
}
}


public function setMemberFlag(): void
{
if(is_string($this->value) && str_starts_with($this->value, '::')){
$this->value .= '()';
}
}

}
8 changes: 4 additions & 4 deletions src/Neon/Node/StringNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function toValue(): string
}


public static function parse(string $s): string
public static function parse(string $s, Nette\Neon\Position $position): string
{
if (preg_match('#^...\n++([\t ]*+)#', $s, $m)) { // multiline
$res = substr($s, 3, -3);
Expand All @@ -52,14 +52,14 @@ public static function parse(string $s): string

return preg_replace_callback(
'#\\\\(?:ud[89ab][0-9a-f]{2}\\\\ud[c-f][0-9a-f]{2}|u[0-9a-f]{4}|.)#i',
function (array $m): string {
function (array $m) use ($position): string {
$sq = $m[0];
if (isset(self::EscapeSequences[$sq[1]])) {
return self::EscapeSequences[$sq[1]];
} elseif ($sq[1] === 'u' && strlen($sq) >= 6) {
return json_decode('"' . $sq . '"') ?? throw new Nette\Neon\Exception("Invalid UTF-8 sequence $sq");
return json_decode('"' . $sq . '"') ?? throw new Nette\Neon\Exception("Invalid UTF-8 sequence $sq", $position);
} else {
throw new Nette\Neon\Exception("Invalid escaping sequence $sq");
throw new Nette\Neon\Exception("Invalid escaping sequence $sq", $position);
}
},
$res,
Expand Down
Loading