From 920ee2d8597d01a8e56714ec38cc1ab28c127e27 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Sat, 26 Oct 2013 01:15:22 +0400 Subject: [PATCH 01/13] Third argument of console. Path to template.php (optional) --- ports/php/php.js | 2 +- ports/php/readme | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ports/php/php.js b/ports/php/php.js index 5e9f84254..f7675b8e2 100644 --- a/ports/php/php.js +++ b/ports/php/php.js @@ -112,7 +112,7 @@ exec("jison " + process.argv[2], function (error) { console.log(option); - var parserRaw = fs.readFileSync(__dirname + "/template.php", "utf8"); + var parserRaw = fs.readFileSync(process.argv[3] ? process.argv[3] : (__dirname + "/template.php"), "utf8"); function parserInject() { var result = '\n'; diff --git a/ports/php/readme b/ports/php/readme index 4f7c84d34..3c49d17f5 100644 --- a/ports/php/readme +++ b/ports/php/readme @@ -4,7 +4,7 @@ Description: A jison wrapper that first processes a jison file and then injects DIRECTIONS: 1. After you've downloaded jison & node.js, navigate in command line interface to the folder that contains the ".jison" file that you want to process -2. Process the ".jison" file like this "nodejs /location_of_jison/ports/php/php.js my_jison_file.jison" +2. Process the ".jison" file like this "nodejs /location_of_jison/ports/php/php.js my_jison_file.jison path_to_template.php" CONFIGURATION: Configuration takes advantage of the commenting in javascript so as not to conflict with. From 9129e848ee181437930350c473f9dd1b6c9b6612 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Sat, 26 Oct 2013 01:20:46 +0400 Subject: [PATCH 02/13] Template.php modernisation. --- ports/php/template.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ports/php/template.php b/ports/php/template.php index 436b679f4..43429942e 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -481,6 +481,15 @@ function __clone() { $clone->text = $this->text; return $clone; } + + public function value() { + if ($this->text instanceof ParserValue) return $this->text->value(); + return $this->text; + } + + public function __toString() { + return (string) $this->value(); + } } class LexerConditions From 6b91c585a6541b3372a5296aa5cf1f0b47b15e0c Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Sat, 26 Oct 2013 01:38:49 +0400 Subject: [PATCH 03/13] Fix error when syntax error message didn't show --- ports/php/template.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ports/php/template.php b/ports/php/template.php index 43429942e..cb6583f9a 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -386,9 +386,7 @@ function next() } if (empty($token) == false) { - return $this->symbols[ - $token - ]; + if (isset($this->symbols[$token])) return $this->symbols[$token]; } else { return null; } From 486a8cce90d69b898a438f81f228706260d88955 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Sat, 26 Oct 2013 01:40:48 +0400 Subject: [PATCH 04/13] Fix README --- ports/php/readme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/php/readme b/ports/php/readme index 3c49d17f5..3d4f8cb3e 100644 --- a/ports/php/readme +++ b/ports/php/readme @@ -4,7 +4,7 @@ Description: A jison wrapper that first processes a jison file and then injects DIRECTIONS: 1. After you've downloaded jison & node.js, navigate in command line interface to the folder that contains the ".jison" file that you want to process -2. Process the ".jison" file like this "nodejs /location_of_jison/ports/php/php.js my_jison_file.jison path_to_template.php" +2. Process the ".jison" file like this "nodejs /location_of_jison/ports/php/php.js my_jison_file.jison [path_to_template.php]" CONFIGURATION: Configuration takes advantage of the commenting in javascript so as not to conflict with. From e23601a52e70c8afe50be4e7fe5f010705308a5d Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Sat, 26 Oct 2013 23:10:26 +0400 Subject: [PATCH 05/13] Escape some symbols. For example " --- ports/php/php.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ports/php/php.js b/ports/php/php.js index f7675b8e2..1ff93cbd1 100644 --- a/ports/php/php.js +++ b/ports/php/php.js @@ -60,6 +60,11 @@ exec("jison " + process.argv[2], function (error) { return str; } + function escape(str) { + return str + .replace("\"","\\\""); + } + function jsPerformActionToPhp(str) { str = jsFnBody(str); str = str.replace("var $0 = $$.length - 1;", ''); @@ -144,9 +149,9 @@ exec("jison " + process.argv[2], function (error) { for (var i in this.symbolsByIndex) { var symbol = this.symbolsByIndex[i]; - result += '\t\t\t$symbol' + symbol.index + ' = new ParserSymbol("' + symbol.name + '", ' + symbol.index + ');\n'; + result += '\t\t\t$symbol' + symbol.index + ' = new ParserSymbol("' + escape(symbol.name) + '", ' + symbol.index + ');\n'; this.symbols.push('\t\t\t$this->symbols[' + symbol.index + '] = $symbol' + symbol.index + ''); - this.symbols.push('\t\t\t$this->symbols["' + symbol.name + '"] = $symbol' + symbol.index + ''); + this.symbols.push('\t\t\t$this->symbols["' + escape(symbol.name) + '"] = $symbol' + symbol.index + ''); } From 18c37b3de332c824fcdf0ab65978b878a0ddf29f Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Sun, 27 Oct 2013 23:21:48 +0400 Subject: [PATCH 06/13] ParserValue->value() support at generated php code --- ports/php/php.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/php/php.js b/ports/php/php.js index 1ff93cbd1..28f4ba29f 100644 --- a/ports/php/php.js +++ b/ports/php/php.js @@ -70,7 +70,7 @@ exec("jison " + process.argv[2], function (error) { str = str.replace("var $0 = $$.length - 1;", ''); str = str.replace("var YYSTATE=YY_START", ''); str = str.replace(new RegExp('[$]0', 'g'), '$o'); - str = str.replace(new RegExp('[$][$]', 'g'), '$s'); + str = str.replace(new RegExp('[$][$](\\[(.+?)\\])', 'g'), '$$s$1->value()'); str = str.replace(new RegExp('default[:][;]', 'g'), ''); str = str.replace(new RegExp('this[.][$]', 'g'), '$thisS'); str = str.replace(new RegExp('this[-][>]', 'g'), '$this->'); From 1bb7ec00dfa9a55bc35517d22c6bf8847cac6537 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Mon, 28 Oct 2013 00:36:33 +0400 Subject: [PATCH 07/13] Add example --- ports/php/example/Makefile | 6 + ports/php/example/example | 1 + ports/php/example/filter.jison | 280 +++++++++++++++++++++++++++++++++ ports/php/example/test.php | 7 + 4 files changed, 294 insertions(+) create mode 100644 ports/php/example/Makefile create mode 100644 ports/php/example/example create mode 100644 ports/php/example/filter.jison create mode 100644 ports/php/example/test.php diff --git a/ports/php/example/Makefile b/ports/php/example/Makefile new file mode 100644 index 000000000..c84983799 --- /dev/null +++ b/ports/php/example/Makefile @@ -0,0 +1,6 @@ +test: compile + node filter.js example + php test.php + +compile: + node ../php.js filter.jison diff --git a/ports/php/example/example b/ports/php/example/example new file mode 100644 index 000000000..e2c7265c2 --- /dev/null +++ b/ports/php/example/example @@ -0,0 +1 @@ +'Hello world' LIKE ['helo','123','3453'] \ No newline at end of file diff --git a/ports/php/example/filter.jison b/ports/php/example/filter.jison new file mode 100644 index 000000000..94f68a652 --- /dev/null +++ b/ports/php/example/filter.jison @@ -0,0 +1,280 @@ + +/* description: Parses end executes mathematical expressions with strings. */ + +/* lexical grammar */ +%lex +%% + +\s+ /* skip whitespace */ +[0-9]+("."[0-9]+)?\b return 'NUMBER'; +"*" return '*'; +"/" return '/'; +"-" return '-'; +"+" return '+'; +"^" return '^'; +"!" return '!'; +"%" return '%'; +"(" return '('; +")" return ')'; +"[" return '['; +"]" return ']'; +"," return ','; +"PI" return 'PI'; +"E" return 'E'; +"SUM" return 'SUM'; +"LIKE" return 'LIKE'; +\"([^"]*)\" %{ + //js + yytext = yytext.substr(1,yyleng-2); + return 'STRING'; + /*php + $yytext = substr($yytext, 1, strlen($yytext) - 2); + return 'STRING'; + */ + %} +\'([^']*)\' %{ + //js + yytext = yytext.substr(1,yyleng-2); + return 'STRING'; + /*php + $yytext = substr($yytext, 1, strlen($yytext) - 2); + return 'STRING'; + */ + %} +'AND' return 'AND'; +'OR' return 'OR'; +'NOT' return 'NOT'; +'>' return '>'; +'<' return '<'; +'=' return '='; +'<>' return '<>'; +'>=' return '>='; +'=>' return '>='; +'<=' return '=<'; +'=<' return '=<'; +'true' return 'true'; +'false' return 'false'; +<> return 'EOF'; +. return 'INVALID'; + +/lex + +/* operator associations and precedence */ + +%right ',' +%left 'OR', +%left 'AND' +%left 'NOT' +%left '>','<','=<','>=', '<>','=' +%left '+' '-' +%left '*' '/' +%left '^' +%right '!' +%right '%' +%left UMINUS + +%start expressions + +%% /* language grammar */ +expressions + : e EOF + { + //js + typeof console !== 'undefined' ? console.log($1) : print($1); + return $1; + /*php + return $1; + */ + } + ; + +sub_list + : sub_list ',' e + { + //js + var A = $1; + A.push($3); + $$ = A; + /*php + $a = $1; + array_push($a, $3); + $$ = $a; + */ + } + | e + { + //js + $$ = [ $1 ]; + //php $$ = array($1); + } + ; + +list + : '[' sub_list ']' + { + $$ = $2; + } + ; + +e + : e '+' e + { + $$ = ( $1 + $3 ); + } + | e '-' e + { + $$ = ($1 - $3); + } + | e '*' e + { + $$ = ( $1*$3 ); + } + + | e '/' e + { + $$ = ( $1 /$3 ); + } + | e '^' e + { + //js + $$ = Math.pow($1, $3); + //php $$ = pow( $1, $3); + } + | e '!' + { + //js + $$ = (function fact (n) { return n==0 ? 1 : fact(n-1) * n })($1); + /*php + $f = function($n) use (&$f) { return ($n<1) ? 1 : ($f($n-1) * $n); }; + $$ = $f((int) $1); + */ + } + | e '%' + { + $$ = $1/100; + } + | '-' e %prec UMINUS + { + $$ = -$2; + } + | '(' e ')' + { + //js + $$ = $2; + //php $$ = $2; + } + | NUMBER + { + //js + $$ = Number(yytext); + //php $$ = $1; + } + | STRING + { + //js + $$ = yytext; + //php $$ = $1; + } + | E + { + //js + $$ = Math.E; + //php $$ = exp(1); + } + | PI + { + //js + $$ = Math.PI; + //php $$ = 3.141592653589793; + } + | 'SUM' list + { + //js + var sum = 0; + $2.forEach(function(item) { sum+= Number(item); }); + $$ = sum; + /*php + $sum = 0; + foreach($2 as $value) { + $sum += $value; + } + $$ = $sum; + */ + } + | e 'LIKE' list + { + //js + var flag = false; + var escape = function(text) { + return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + } + $3.forEach(function(item) { + var regexp = new RegExp(escape(item).replace('%', '(.*)'),'gi'); + flag = flag || regexp.test($1); + }); + $$ = flag; + /*php + // TODO: Синхронизировать метод с JS + $flag = false; + $template = $1; + foreach($3 as $item) { + $flag = $flag || (mb_stripos($template, $item,0, 'utf-8') !== false); + if ($flag) break; + } + $$ = $flag; + */ + } + | e 'AND' e + { + //js + $$ = ($1!=false) && ($3!=false); + //php $$ = ($1 !== false) && ($3 !== false); + } + | e 'OR' e + { + //js + $$ = ($1!=false) || ($3!=false); + /*php + $$ = ($1 !== false) || ($3 !== false); + */ + } + | 'NOT' e + { + //js + $$ = !($2!=false) ; + //php $$ = ! ($2 !== false) ; + } + | 'true' + { + $$ = true; + } + | 'false' + { + $$ = false; + } + | e '>' e + { + $$ = ( $1 > $3 ); + } + | e '<' e + { + $$ = ( $1 < $3 ); + } + | e '>=' e + { + $$ = ( $1 >= $3 ); + } + | e '=<' e + { + $$ = ( $1 <= $3 ); + } + | e '=' e + { + $$ = ( $1 == $3 ); + } + | e '<>' e + { + $$ = ( $1 != $3 ); + } + ; + diff --git a/ports/php/example/test.php b/ports/php/example/test.php new file mode 100644 index 000000000..6625cd57c --- /dev/null +++ b/ports/php/example/test.php @@ -0,0 +1,7 @@ +parse($text)); +echo "\n"; \ No newline at end of file From b62f9e30bbe2beafbff25619c0efe7998f0e1e98 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Mon, 28 Oct 2013 01:08:53 +0400 Subject: [PATCH 08/13] Delete escape. --- ports/php/php.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/ports/php/php.js b/ports/php/php.js index 28f4ba29f..b80f5e0d8 100644 --- a/ports/php/php.js +++ b/ports/php/php.js @@ -60,11 +60,6 @@ exec("jison " + process.argv[2], function (error) { return str; } - function escape(str) { - return str - .replace("\"","\\\""); - } - function jsPerformActionToPhp(str) { str = jsFnBody(str); str = str.replace("var $0 = $$.length - 1;", ''); @@ -149,9 +144,9 @@ exec("jison " + process.argv[2], function (error) { for (var i in this.symbolsByIndex) { var symbol = this.symbolsByIndex[i]; - result += '\t\t\t$symbol' + symbol.index + ' = new ParserSymbol("' + escape(symbol.name) + '", ' + symbol.index + ');\n'; + result += '\t\t\t$symbol' + symbol.index + ' = new ParserSymbol("' + symbol.name + '", ' + symbol.index + ');\n'; this.symbols.push('\t\t\t$this->symbols[' + symbol.index + '] = $symbol' + symbol.index + ''); - this.symbols.push('\t\t\t$this->symbols["' + escape(symbol.name) + '"] = $symbol' + symbol.index + ''); + this.symbols.push('\t\t\t$this->symbols["' + symbol.name + '"] = $symbol' + symbol.index + ''); } From 92fe2957cdf58031dcd21bd18cb51b99f12ff4d1 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Mon, 28 Oct 2013 11:27:21 +0400 Subject: [PATCH 09/13] Fix bug when symbol = '0' at the end of string generate error --- ports/php/template.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ports/php/template.php b/ports/php/template.php index cb6583f9a..c244b7590 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -328,7 +328,7 @@ function next() return $this->eof; } - if (empty($this->input)) { + if ($this->input == '' || $this->input === false) { $this->done = true; } @@ -380,8 +380,7 @@ function next() $nextCondition = $this->conditionStack[$this->conditionStackCount - 1]; $token = $this->lexerPerformAction($ruleIndex, $nextCondition); - - if ($this->done == true && empty($this->input) == false) { + if ($this->done == true && $this->input != '' && $this->input !== false) { $this->done = false; } @@ -392,7 +391,7 @@ function next() } } - if (empty($this->input)) { + if ($this->input == '' || $this->input === false) { return $this->eof; } else { $this->lexerError("Lexical error on line " . ($this->yy->lineNo + 1) . ". Unrecognized text.\n" . $this->showPosition(), new LexerError("", -1, $this->yy->lineNo)); From e71e2a4ae7acd24563c822069fbd997832391236 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Mon, 28 Oct 2013 22:05:15 +0400 Subject: [PATCH 10/13] UTF-8 regexp support. --- ports/php/php.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ports/php/php.js b/ports/php/php.js index b80f5e0d8..c9d10d8d6 100644 --- a/ports/php/php.js +++ b/ports/php/php.js @@ -221,7 +221,7 @@ exec("jison " + process.argv[2], function (error) { this.conditions = []; for (var i in rules) { - this.rules.push('\t\t\t\t\t' + i + '=>"/' + rules[i].substring(1, rules[i].length - 1).replace(/"/g, '\\"') + '/"'); + this.rules.push('\t\t\t\t\t' + i + '=>"' + rules[i].replace(/"/g, '\\"') + 'u"'); } result += '\t\t\t$this->rules = array(\n\t\t\t\t\n' + this.rules.join(',\n') + '\n\t\t\t\t);\n\n'; From 8aa35ea44cc6bd7015bee09e31fa33db3a3c59b3 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Mon, 28 Oct 2013 23:37:04 +0400 Subject: [PATCH 11/13] Public to protect property --- ports/php/template.php | 52 +++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/ports/php/template.php b/ports/php/template.php index c244b7590..4b6adb88f 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -6,17 +6,17 @@ /**/class Parser/**/ { - public $symbols = array(); - public $terminals = array(); - public $productions = array(); - public $table = array(); - public $defaultActions = array(); - public $version = '0.3.12'; - public $debug = false; - public $none = 0; - public $shift = 1; - public $reduce = 2; - public $accept = 3; + protected $symbols = array(); + protected $terminals = array(); + protected $productions = array(); + protected $table = array(); + protected $defaultActions = array(); + protected $version = '0.3.12'; + protected $debug = false; + protected $none = 0; + protected $shift = 1; + protected $reduce = 2; + protected $accept = 3; function trace() { @@ -200,21 +200,21 @@ function parse($input) /* Jison generated lexer */ - public $eof; - public $yy = null; - public $match = ""; - public $matched = ""; - public $conditionStack = array(); - public $conditionStackCount = 0; - public $rules = array(); - public $conditions = array(); - public $done = false; - public $less; - public $more; - public $input; - public $offset; - public $ranges; - public $flex = false; + protected $eof; + protected $yy = null; + protected $match = ""; + protected $matched = ""; + protected $conditionStack = array(); + protected $conditionStackCount = 0; + protected $rules = array(); + protected $conditions = array(); + protected $done = false; + protected $less; + protected $more; + protected $input; + protected $offset; + protected $ranges; + protected $flex = false; function setInput($input) { From a3949b4f56663e0b33b5b35a7646eb5fff4763ed Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Mon, 28 Oct 2013 23:45:30 +0400 Subject: [PATCH 12/13] ParserError and LexerError exceptions. --- ports/php/template.php | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/ports/php/template.php b/ports/php/template.php index 4b6adb88f..91f362cf9 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -48,14 +48,14 @@ function parserLex() return $this->symbols["end"]; } - function parseError($str = "", ParserError $hash = null) + function parseError(ParserError $error) { - throw new Exception($str); + throw $error; } - function lexerError($str = "", LexerError $hash = null) + function lexerError(LexerError $error) { - throw new Exception($str); + throw $error; } function parse($input) @@ -112,7 +112,7 @@ function parse($input) $errStr = "Parse error on line " . ($this->yy->lineNo + 1) . ":\n" . $this->showPosition() . "\nExpecting " . implode(", ", $expected) . ", got '" . (isset($this->terminals[$symbol->index]) ? $this->terminals[$symbol->index]->name : 'NOTHING') . "'"; - $this->parseError($errStr, new ParserError($this->match, $state, $symbol, $this->yy->lineNo, $this->yy->loc, $expected)); + $this->parseError(new ParserError($errStr,$this->match, $state, $symbol, $this->yy->lineNo, $this->yy->loc, $expected)); } } @@ -394,7 +394,7 @@ function next() if ($this->input == '' || $this->input === false) { return $this->eof; } else { - $this->lexerError("Lexical error on line " . ($this->yy->lineNo + 1) . ". Unrecognized text.\n" . $this->showPosition(), new LexerError("", -1, $this->yy->lineNo)); + $this->lexerError(new LexerError("Lexical error on line " . ($this->yy->lineNo + 1) . ". Unrecognized text.\n" . $this->showPosition(), "", -1, $this->yy->lineNo)); return null; } } @@ -558,7 +558,7 @@ public function addAction($a) } } -class ParserError +class ParserError extends \Exception { public $text; public $state; @@ -567,8 +567,9 @@ class ParserError public $loc; public $expected; - function __construct($text, $state, $symbol, $lineNo, $loc, $expected) + function __construct($msg,$text, $state, $symbol, $lineNo, $loc, $expected) { + parent::__construct($msg); $this->text = $text; $this->state = $state; $this->symbol = $symbol; @@ -578,14 +579,15 @@ function __construct($text, $state, $symbol, $lineNo, $loc, $expected) } } -class LexerError +class LexerError extends \Exception { public $text; public $token; public $lineNo; - public function __construct($text, $token, $lineNo) + public function __construct($msg, $text, $token, $lineNo) { + parent::__construct($msg); $this->text = $text; $this->token = $token; $this->lineNo = $lineNo; From a8db3420d0f9be6370538ada6c910d53db6cfc06 Mon Sep 17 00:00:00 2001 From: Loguntsov Sergey Date: Wed, 30 Oct 2013 20:37:32 +0400 Subject: [PATCH 13/13] Support UTF8 when generate error messages. Catching special RunTimeError exception. This exception can generates by user code. --- ports/php/template.php | 65 ++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/ports/php/template.php b/ports/php/template.php index 91f362cf9..6ce35930d 100644 --- a/ports/php/template.php +++ b/ports/php/template.php @@ -48,16 +48,18 @@ function parserLex() return $this->symbols["end"]; } - function parseError(ParserError $error) - { + protected function parseError(ParserError $error) { throw $error; } - function lexerError(LexerError $error) - { + protected function lexerError(LexerError $error) { throw $error; } + protected function runTimeError(RunTimeError $error) { + throw $error; + } + function parse($input) { if (empty($this->table)) { @@ -150,10 +152,20 @@ function parse($input) if (isset($this->ranges)) { //TODO: add ranges } - - $r = $this->parserPerformAction($_yy->text, $yy, $action->state->index, $vstack, $vstackCount - 1); - - if (isset($r)) { + try { + $r = $this->parserPerformAction($_yy->text, $yy, $action->state->index, $vstack, $vstackCount - 1); + } + catch (RunTimeError $error) { + $newError = new RunTimeError($error->getMessage(). "\n". $this->showPosition()); + $newError->text = $this->match; + $newError->state = $state; + $newError->symbol = $symbol; + $newError->lineNo = $this->yy->lineNo; + $newError->loc = $this->yy->loc; + throw $newError; + } + + if (isset($r)) { return $r; } @@ -295,31 +307,31 @@ function more() $this->more = true; } - function pastInput() + function pastInput($len) { - $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match)); - return (strlen($past) > 20 ? '...' : '') . preg_replace("/\n/", "", substr($past, -20)); + $past = mb_substr($this->matched, 0, mb_strlen($this->matched,'utf8') - mb_strlen($this->match,'utf8'),'utf8'); + return (mb_strlen($past,'utf8') > $len ? '...' : '') . str_replace("\n", "", mb_substr($past, -$len, NULL, 'utf8')); } - function upcomingInput() + function upcomingInput($len) { $next = $this->match; - if (strlen($next) < 20) { - $next .= substr($this->input, 0, 20 - strlen($next)); + if (mb_strlen($next,'utf8') < $len) { + $next .= mb_substr($this->input, 0, $len - mb_strlen($next,'utf8')); } - return preg_replace("/\n/", "", substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '')); + return str_replace("\n", "", mb_substr($next, 0, $len,'utf8') . (mb_strlen($next,'utf8') > $len ? '...' : '')); } - function showPosition() + function showPosition($len = 20) { - $pre = $this->pastInput(); + $pre = $this->pastInput($len); $c = ''; - for($i = 0, $preLength = strlen($pre); $i < $preLength; $i++) { + for($i = 0, $preLength = mb_strlen($pre, 'utf8'); $i < $preLength; $i++) { $c .= '-'; } - return $pre . $this->upcomingInput() . "\n" . $c . "^"; + return $pre . $this->upcomingInput($len) . "\n" . $c . "^"; } function next() @@ -558,7 +570,18 @@ public function addAction($a) } } -class ParserError extends \Exception +class JisonError extends \Exception { +} + +class RunTimeError extends JisonError { + public $text; + public $state; + public $symbol; + public $lineNo; + public $loc; +} + +class ParserError extends JisonError { public $text; public $state; @@ -579,7 +602,7 @@ function __construct($msg,$text, $state, $symbol, $lineNo, $loc, $expected) } } -class LexerError extends \Exception +class LexerError extends JisonError { public $text; public $token;