fork download
  1. <?php
  2.  
  3. class Lexer {
  4. protected static $_terminals = array(
  5. '~^(\[)~' => "T_OPEN",
  6. '~^(\])~' => "T_CLOSE",
  7. '~^(".+?(?<!\\\\)")~' => "T_ITEM",
  8. '~^(,)(?!,)~' => "T_SEPARATOR",
  9. '~^(\d+)~' => "T_NUMBER",
  10. '~^(,)(?=,)~' => "T_EMPTY"
  11. );
  12.  
  13. public static function run($line) {
  14. $tokens = array();
  15. $offset = 0;
  16. while($offset < strlen($line)) {
  17. $result = static::_match($line, $offset);
  18. if($result === false) {
  19. throw new Exception("Unable to parse line " . ($line+1) . ".");
  20. }
  21. $tokens[] = $result;
  22. $offset += strlen($result['match']);
  23. }
  24. return static::_generate($tokens);
  25. }
  26.  
  27. protected static function _match($line, $offset) {
  28. $string = substr($line, $offset);
  29.  
  30. foreach(static::$_terminals as $pattern => $name) {
  31. if(preg_match($pattern, $string, $matches)) {
  32. return array(
  33. 'match' => $matches[1],
  34. 'token' => $name
  35. );
  36. }
  37. }
  38. return false;
  39. }
  40.  
  41. // a recursive function to actually build the structure
  42. protected static function _generate($arr=array(), $idx=0) {
  43. $output = array();
  44. $current = 0;
  45. for($i=$idx;$i<count($arr);$i++) {
  46. $type = $arr[$i]["token"];
  47. $element = $arr[$i]["match"];
  48. switch ($type) {
  49. case 'T_OPEN':
  50. list($out, $index) = static::_generate($arr, $i+1);
  51. $output[] = $out;
  52. $i = $index;
  53. break;
  54. case 'T_CLOSE':
  55. return array($output, $i);
  56. break;
  57. case 'T_ITEM':
  58. case 'T_NUMBER':
  59. $output[] = $element;
  60. break;
  61. case 'T_EMPTY':
  62. $output[] = "";
  63. break;
  64. }
  65. }
  66. return $output;
  67. }
  68. }
  69.  
  70. $input = '[[["Hello, \"how\" are you?","Good!",,,123]],,"ok"]';
  71. $items = Lexer::run($input);
  72. print_r($items);
  73.  
  74. ?>
Success #stdin #stdout 0.01s 82944KB
stdin
Standard input is empty
stdout
Array
(
    [0] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [0] => "Hello, \"how\" are you?"
                            [1] => "Good!"
                            [2] => 
                            [3] => 
                            [4] => 123
                        )

                )

            [1] => 
            [2] => "ok"
        )

)