json.php 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. <?php
  2. class LuminousJSONScanner extends LuminousScanner {
  3. private $stack = array();
  4. public function init() {
  5. $this->add_identifier_mapping('KEYWORD', array('true', 'false', 'null'));
  6. }
  7. public function state() {
  8. if (!empty($this->stack)) return $this->stack[count($this->stack)-1][0];
  9. else return null;
  10. }
  11. private function expecting($x=null) {
  12. if ($x !== null) {
  13. if (!empty($this->stack)) $this->stack[count($this->stack)-1][1] = $x;
  14. }
  15. if (!empty($this->stack)) return $this->stack[count($this->stack)-1][1];
  16. else return null;
  17. }
  18. function main() {
  19. while (!$this->eos()) {
  20. $tok = null;
  21. $c = $this->peek();
  22. list($state, $expecting) = array($this->state(), $this->expecting());
  23. $this->skip_whitespace();
  24. if ($this->eos()) break;
  25. if ($this->scan(LuminousTokenPresets::$NUM_REAL) !== null) {
  26. $tok = 'NUMERIC';
  27. }
  28. elseif($this->scan('/[a-zA-Z]\w*/')) {
  29. $tok = 'IDENT';
  30. }
  31. elseif($this->scan(LuminousTokenPresets::$DOUBLE_STR)) {
  32. $tok = ($state === 'obj' && $expecting === 'key')? 'TYPE' : 'STRING';
  33. }
  34. elseif($this->scan('/\[/')) {
  35. $this->stack[] = array('array', null);
  36. $tok = 'OPERATOR';
  37. }
  38. elseif($this->scan('/\]/')) {
  39. if ($state === 'array') {
  40. array_pop($this->stack);
  41. $tok = 'OPERATOR';
  42. }
  43. }
  44. elseif($this->scan('/\{/')) {
  45. $this->stack[] = array('obj', 'key');
  46. $tok = 'OPERATOR';
  47. }
  48. elseif($state === 'obj' && $this->scan('/\}/')) {
  49. array_pop($this->stack);
  50. $tok = 'OPERATOR';
  51. }
  52. elseif($state === 'obj' && $this->scan('/:/')) {
  53. $this->expecting('value');
  54. $tok = 'OPERATOR';
  55. }
  56. elseif($this->scan('/,/')) {
  57. if ($state === 'obj') {
  58. $this->expecting('key');
  59. $tok = 'OPERATOR';
  60. }
  61. elseif($state === 'array') $tok = 'OPERATOR';
  62. }
  63. else $this->scan('/./');
  64. $this->record($this->match(), $tok);
  65. }
  66. }
  67. public static function guess_language($src, $info) {
  68. // JSON is fairly hard to guess
  69. $p = 0;
  70. $src_ = trim($src);
  71. if (!empty($src_)) {
  72. $char = $src_[0];
  73. $char2 = $src_[strlen($src_)-1];
  74. $str = '"(?>[^"\\\\]+|\\\\.)"';
  75. // looks like an object or array
  76. if ( ($char === '[' && $char2 === ']')
  77. || ($char === '{' && $char2 === '}'))
  78. {
  79. $p += 0.05;
  80. }
  81. elseif(preg_match("/^(?:$str|(\d+(\.\d+)?([eE]\d+)?)|true|false|null)$/",
  82. $src_))
  83. {
  84. // just a string or number or value
  85. $p += 0.1;
  86. }
  87. }
  88. return $p;
  89. }
  90. }