Better parsing error reporting
Publish PHP Package / docker (push) Successful in 6s
Details
Publish PHP Package / docker (push) Successful in 6s
Details
This commit is contained in:
parent
dd1c8ad1ba
commit
4d080bacd8
51
jzon.inc.php
51
jzon.inc.php
|
@ -6,29 +6,38 @@ if(!defined('JZON_VERSION'))
|
||||||
define('JZON_EXT_VERSION', phpversion('jzon'));
|
define('JZON_EXT_VERSION', phpversion('jzon'));
|
||||||
}
|
}
|
||||||
|
|
||||||
function jzon_show_position($p, $in, $context_chars)
|
function jzon_show_position(int $p, string $in, int $context_lines = 5) : string
|
||||||
{
|
{
|
||||||
$pre = str_replace("\n", '', jzon_get_past_input($p, $in, $context_chars));
|
$out = array();
|
||||||
$c = str_repeat('-', max(0, strlen($pre) - 1));
|
$lines = explode("\n", $in);
|
||||||
|
//let's find out the maximum leading zeros for line numbers
|
||||||
|
$fmt_num = (int)round(log10(count($lines)));
|
||||||
|
foreach($lines as $line_idx => $line)
|
||||||
|
{
|
||||||
|
//adding line numbers and handling tabs
|
||||||
|
$out[] = sprintf('%0'.$fmt_num.'d', $line_idx) . ' ' . str_replace("\t", " ", $line);
|
||||||
|
$left = $p - (strlen($line) + 1/*taking into account \n*/);
|
||||||
|
//var_dump($left, $p, $line, $fmt_num);
|
||||||
|
if($left < 0)
|
||||||
|
{
|
||||||
|
$arrow = str_repeat('-', $fmt_num) . '-'; //line numbers
|
||||||
|
for($i=0;$i<$p;++$i)
|
||||||
|
$arrow .= ($line[$i] === "\t" ? '----' : '-');
|
||||||
|
$arrow .= '^';
|
||||||
|
|
||||||
return $pre . str_replace("\n", '', jzon_get_upcoming_input($p, $in, $context_chars)) . "\n" . $c . "^";
|
$out[] = $arrow;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
$p = $left;
|
||||||
function jzon_get_past_input($c, $in, $context_chars)
|
|
||||||
{
|
|
||||||
$past = substr($in, 0, $c+1);
|
|
||||||
return (strlen($past) > $context_chars ? '...' : '') . substr($past, -$context_chars);
|
|
||||||
}
|
}
|
||||||
|
if(count($out) > $context_lines)
|
||||||
function jzon_get_upcoming_input($c, $in, $context_chars)
|
$out = array_slice($out, -$context_lines);
|
||||||
{
|
return implode("\n", $out);
|
||||||
$next = substr($in, $c+1);
|
|
||||||
return substr($next, 0, $context_chars) . (strlen($next) > $context_chars ? '...' : '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class jzonParser
|
class jzonParser
|
||||||
{
|
{
|
||||||
const ERR_CONTEXT_CHARS = 200;
|
const ERR_CONTEXT_LINES = 5;
|
||||||
|
|
||||||
private $in;
|
private $in;
|
||||||
private $len;
|
private $len;
|
||||||
|
@ -86,9 +95,9 @@ class jzonParser
|
||||||
private function _error($error)
|
private function _error($error)
|
||||||
{
|
{
|
||||||
if($this->c < $this->len)
|
if($this->c < $this->len)
|
||||||
throw new Exception("Parse error: $error\n" . jzon_show_position($this->c, $this->in, self::ERR_CONTEXT_CHARS));
|
throw new Exception("Parse error: $error\n" . jzon_show_position($this->c, $this->in, self::ERR_CONTEXT_LINES));
|
||||||
else
|
else
|
||||||
throw new Exception("Parse error: $error\n" . jzon_show_position($this->len-1, $this->in, self::ERR_CONTEXT_CHARS));
|
throw new Exception("Parse error: $error\n" . jzon_show_position($this->len-1, $this->in, self::ERR_CONTEXT_LINES));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function skip_whitespace()
|
private function skip_whitespace()
|
||||||
|
@ -337,13 +346,13 @@ class jzonParser
|
||||||
else
|
else
|
||||||
$this->_error("'null' expected");
|
$this->_error("'null' expected");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function jzon_parse($str)
|
function jzon_parse($str, ?int &$parser = null) : array
|
||||||
{
|
{
|
||||||
//NOTE: using super fast built-in implementation and making a gracefull fallback to a slower and
|
//NOTE: using super fast built-in implementation and making a gracefull fallback to a slower and
|
||||||
// more relaxed implementation
|
// more relaxed implementation
|
||||||
|
$parser = 1;
|
||||||
$res = json_decode($str, true);
|
$res = json_decode($str, true);
|
||||||
if(is_array($res))
|
if(is_array($res))
|
||||||
return $res;
|
return $res;
|
||||||
|
@ -351,13 +360,15 @@ function jzon_parse($str)
|
||||||
//NOTE: only allowing extension implementation if versions match
|
//NOTE: only allowing extension implementation if versions match
|
||||||
if(defined('JZON_EXT_VERSION') && JZON_EXT_VERSION === JZON_VERSION)
|
if(defined('JZON_EXT_VERSION') && JZON_EXT_VERSION === JZON_VERSION)
|
||||||
{
|
{
|
||||||
|
$parser = 2;
|
||||||
list($ok, $err, $err_pos, $res) = jzon_parse_c($str);
|
list($ok, $err, $err_pos, $res) = jzon_parse_c($str);
|
||||||
if(!$ok)
|
if(!$ok)
|
||||||
throw new Exception($err . "\n" . jzon_show_position($err_pos, $str, jzonParser::ERR_CONTEXT_CHARS));
|
throw new Exception($err . "\n" . jzon_show_position($err_pos, $str, jzonParser::ERR_CONTEXT_LINES));
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
$parser = 3;
|
||||||
$p = new jzonParser($str);
|
$p = new jzonParser($str);
|
||||||
$res = $p->parse();
|
$res = $p->parse();
|
||||||
return $res;
|
return $res;
|
||||||
|
|
Loading…
Reference in New Issue