BBCodeLexer

The bbPress BBCodeLexer class.

Defined (1)

The class is defined in the following location(s).

/includes/admin/parser.php  
  1. class BBCodeLexer { 
  2. var $token; 
  3. var $text; 
  4. var $tag; 
  5. var $state; 
  6. var $input; 
  7. var $ptr; 
  8. var $unget; 
  9. var $verbatim; 
  10. var $debug; 
  11. var $tagmarker; 
  12. var $end_tagmarker; 
  13. var $pat_main; 
  14. var $pat_comment; 
  15. var $pat_comment2; 
  16. var $pat_wiki; 
  17. function BBCodeLexer($string, $tagmarker = '[') { 
  18. $regex_beginmarkers = Array( '[' => '\[', '<' => '<', '{' => '\{', '(' => '\(' ); 
  19. $regex_endmarkers = Array( '[' => '\]', '<' => '>', '{' => '\}', '(' => '\)' ); 
  20. $endmarkers = Array( '[' => ']', '<' => '>', '{' => '}', '(' => ')' ); 
  21. if (!isset($regex_endmarkers[$tagmarker])) $tagmarker = '['; 
  22. $e = $regex_endmarkers[$tagmarker]; 
  23. $b = $regex_beginmarkers[$tagmarker]; 
  24. $this->tagmarker = $tagmarker; 
  25. $this->end_tagmarker = $endmarkers[$tagmarker]; 
  26. $this->pat_main = "/( " 
  27. . "{$b}" 
  28. . "(?! -- | ' | !-- | {$b}{$b} )" 
  29. . "(?: [^\\n\\r{$b}{$e}] | \\\" [^\\\"\\n\\r]* \\\" | \\' [^\\'\\n\\r]* \\' )*" 
  30. . "{$e}" 
  31. . "| {$b}{$b} (?: [^{$e}\\r\\n] | {$e}[^{$e}\\r\\n] )* {$e}{$e}" 
  32. . "| {$b} (?: -- | ' ) (?: [^{$e}\\n\\r]* ) {$e}" 
  33. . "| {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e}" 
  34. . "| -----+" 
  35. . "| \\x0D\\x0A | \\x0A\\x0D | \\x0D | \\x0A" 
  36. . "| [\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+(?=[\\x0D\\x0A{$b}]|-----|$)" 
  37. . "| (?<=[\\x0D\\x0A{$e}]|-----|^)[\\x00-\\x09\\x0B-\\x0C\\x0E-\\x20]+" 
  38. . " )/Dx"; 
  39. $this->input = preg_split($this->pat_main, $string, -1, PREG_SPLIT_DELIM_CAPTURE); 
  40. $this->pat_comment = "/^ {$b} (?: -- | ' ) /Dx"; 
  41. $this->pat_comment2 = "/^ {$b}!-- (?: [^-] | -[^-] | --[^{$e}] )* --{$e} $/Dx"; 
  42. $this->pat_wiki = "/^ {$b}{$b} ([^\\|]*) (?:\\|(.*))? {$e}{$e} $/Dx"; 
  43. $this->ptr = 0; 
  44. $this->unget = false; 
  45. $this->state = BBCODE_LEXSTATE_TEXT; 
  46. $this->verbatim = false; 
  47. $this->token = BBCODE_EOI; 
  48. $this->tag = false; 
  49. $this->text = ""; 
  50. function GuessTextLength() { 
  51. $length = 0; 
  52. $ptr = 0; 
  53. $state = BBCODE_LEXSTATE_TEXT; 
  54. while ($ptr < count($this->input)) { 
  55. $text = $this->input[$ptr++]; 
  56. if ($state == BBCODE_LEXSTATE_TEXT) { 
  57. $state = BBCODE_LEXSTATE_TAG; 
  58. $length += strlen($text); 
  59. else { 
  60. switch (ord(substr($this->text, 0, 1))) { 
  61. case 10: 
  62. case 13: 
  63. $state = BBCODE_LEXSTATE_TEXT; 
  64. $length++; 
  65. break; 
  66. default: 
  67. $state = BBCODE_LEXSTATE_TEXT; 
  68. $length += strlen($text); 
  69. break; 
  70. case 40: 
  71. case 60: 
  72. case 91: 
  73. case 123: 
  74. $state = BBCODE_LEXSTATE_TEXT; 
  75. break; 
  76. return $length; 
  77. function NextToken() { 
  78. if ($this->unget) { 
  79. $this->unget = false; 
  80. return $this->token; 
  81. while (true) { 
  82. if ($this->ptr >= count($this->input)) { 
  83. $this->text = ""; 
  84. $this->tag = false; 
  85. return $this->token = BBCODE_EOI; 
  86. $this->text = preg_replace("/[\\x00-\\x08\\x0B-\\x0C\\x0E-\\x1F]/", "",  
  87. $this->input[$this->ptr++]); 
  88. if ($this->verbatim) { 
  89. $this->tag = false; 
  90. if ($this->state == BBCODE_LEXSTATE_TEXT) { 
  91. $this->state = BBCODE_LEXSTATE_TAG; 
  92. $token_type = BBCODE_TEXT; 
  93. else { 
  94. $this->state = BBCODE_LEXSTATE_TEXT; 
  95. switch (ord(substr($this->text, 0, 1))) { 
  96. case 10: 
  97. case 13: 
  98. $token_type = BBCODE_NL; 
  99. break; 
  100. default: 
  101. $token_type = BBCODE_WS; 
  102. break; 
  103. case 45: 
  104. case 40: 
  105. case 60: 
  106. case 91: 
  107. case 123: 
  108. $token_type = BBCODE_TEXT; 
  109. break; 
  110. if (strlen($this->text) > 0) 
  111. return $this->token = $token_type; 
  112. else if ($this->state == BBCODE_LEXSTATE_TEXT) { 
  113. $this->state = BBCODE_LEXSTATE_TAG; 
  114. $this->tag = false; 
  115. if (strlen($this->text) > 0) 
  116. return $this->token = BBCODE_TEXT; 
  117. else { 
  118. switch (ord(substr($this->text, 0, 1))) { 
  119. case 10: 
  120. case 13: 
  121. $this->tag = false; 
  122. $this->state = BBCODE_LEXSTATE_TEXT; 
  123. return $this->token = BBCODE_NL; 
  124. case 45: 
  125. if (preg_match("/^-----/", $this->text)) { 
  126. $this->tag = Array('_name' => 'rule', '_endtag' => false, '_default' => ''); 
  127. $this->state = BBCODE_LEXSTATE_TEXT; 
  128. return $this->token = BBCODE_TAG; 
  129. else { 
  130. $this->tag = false; 
  131. $this->state = BBCODE_LEXSTATE_TEXT; 
  132. if (strlen($this->text) > 0) 
  133. return $this->token = BBCODE_TEXT; 
  134. continue; 
  135. default: 
  136. $this->tag = false; 
  137. $this->state = BBCODE_LEXSTATE_TEXT; 
  138. return $this->token = BBCODE_WS; 
  139. case 40: 
  140. case 60: 
  141. case 91: 
  142. case 123: 
  143. if (preg_match($this->pat_comment, $this->text)) { 
  144. $this->state = BBCODE_LEXSTATE_TEXT; 
  145. continue; 
  146. if (preg_match($this->pat_comment2, $this->text)) { 
  147. $this->state = BBCODE_LEXSTATE_TEXT; 
  148. continue; 
  149. if (preg_match($this->pat_wiki, $this->text, $matches)) { 
  150. $this->tag = Array('_name' => 'wiki', '_endtag' => false,  
  151. '_default' => @$matches[1], 'title' => @$matches[2]); 
  152. $this->state = BBCODE_LEXSTATE_TEXT; 
  153. return $this->token = BBCODE_TAG; 
  154. $this->tag = $this->Internal_DecodeTag($this->text); 
  155. $this->state = BBCODE_LEXSTATE_TEXT; 
  156. return $this->token = ($this->tag['_end'] ? BBCODE_ENDTAG : BBCODE_TAG); 
  157. function UngetToken() { 
  158. if ($this->token !== BBCODE_EOI) 
  159. $this->unget = true; 
  160. function PeekToken() { 
  161. $result = $this->NextToken(); 
  162. if ($this->token !== BBCODE_EOI) 
  163. $this->unget = true; 
  164. return $result; 
  165. function SaveState() { 
  166. return Array( 
  167. 'token' => $this->token,  
  168. 'text' => $this->text,  
  169. 'tag' => $this->tag,  
  170. 'state' => $this->state,  
  171. 'input' => $this->input,  
  172. 'ptr' => $this->ptr,  
  173. 'unget' => $this->unget,  
  174. 'verbatim' => $this->verbatim 
  175. ); 
  176. function RestoreState($state) { 
  177. if (!is_array($state)) return; 
  178. $this->token = @$state['token']; 
  179. $this->text = @$state['text']; 
  180. $this->tag = @$state['tag']; 
  181. $this->state = @$state['state']; 
  182. $this->input = @$state['input']; 
  183. $this->ptr = @$state['ptr']; 
  184. $this->unget = @$state['unget']; 
  185. $this->verbatim = @$state['verbatim']; 
  186. function Internal_StripQuotes($string) { 
  187. if (preg_match("/^\\\"(.*)\\\"$/", $string, $matches)) 
  188. return $matches[1]; 
  189. else if (preg_match("/^\\'(.*)\\'$/", $string, $matches)) 
  190. return $matches[1]; 
  191. else return $string; 
  192. function Internal_ClassifyPiece($ptr, $pieces) { 
  193. if ($ptr >= count($pieces)) return -1; 
  194. $piece = $pieces[$ptr]; 
  195. if ($piece == '=') return '='; 
  196. else if (preg_match("/^[\\'\\\"]/", $piece)) return '"'; 
  197. else if (preg_match("/^[\\x00-\\x20]+$/", $piece)) return ' '; 
  198. else return 'A'; 
  199. function Internal_DecodeTag($tag) { 
  200. $result = Array('_tag' => $tag, '_endtag' => '', '_name' => '',  
  201. '_hasend' => false, '_end' => false, '_default' => false); 
  202. $tag = substr($tag, 1, strlen($tag)-2); 
  203. $ch = ord(substr($tag, 0, 1)); 
  204. if ($ch >= 0 && $ch <= 32) return $result; 
  205. $pieces = preg_split("/(\\\"[^\\\"]+\\\"|\\'[^\\']+\\'|=|[\\x00-\\x20]+)/",  
  206. $tag, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY); 
  207. $ptr = 0; 
  208. if (count($pieces) < 1) return $result; 
  209. if (@substr($pieces[$ptr], 0, 1) == '/') { 
  210. $result['_name'] = strtolower(substr($pieces[$ptr++], 1)); 
  211. $result['_end'] = true; 
  212. else { 
  213. $result['_name'] = strtolower($pieces[$ptr++]); 
  214. $result['_end'] = false; 
  215. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') 
  216. $ptr++; 
  217. $params = Array(); 
  218. if ($type != '=') { 
  219. $result['_default'] = false; 
  220. $params[] = Array('key' => '', 'value' => ''); 
  221. else { 
  222. $ptr++; 
  223. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') 
  224. $ptr++; 
  225. if ($type == "\"") 
  226. $value = $this->Internal_StripQuotes($pieces[$ptr++]); 
  227. else { 
  228. $after_space = false; 
  229. $start = $ptr; 
  230. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1) { 
  231. if ($type == ' ') $after_space = true; 
  232. if ($type == '=' && $after_space) break; 
  233. $ptr++; 
  234. if ($type == -1) $ptr--; 
  235. if ($type == '=') { 
  236. $ptr--; 
  237. while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) == ' ') 
  238. $ptr--; 
  239. while ($ptr > $start && $this->Internal_ClassifyPiece($ptr, $pieces) != ' ') 
  240. $ptr--; 
  241. $value = ""; 
  242. for (; $start <= $ptr; $start++) { 
  243. if ($this->Internal_ClassifyPiece($start, $pieces) == ' ') 
  244. $value .= " "; 
  245. else $value .= $this->Internal_StripQuotes($pieces[$start]); 
  246. $value = trim($value); 
  247. $ptr++; 
  248. $result['_default'] = $value; 
  249. $params[] = Array('key' => '', 'value' => $value); 
  250. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1) { 
  251. while ($type == ' ') { 
  252. $ptr++; 
  253. $type = $this->Internal_ClassifyPiece($ptr, $pieces); 
  254. if ($type == 'A' || $type == '"') 
  255. $key = strtolower($this->Internal_StripQuotes(@$pieces[$ptr++])); 
  256. else if ($type == '=') { 
  257. $ptr++; 
  258. continue; 
  259. else if ($type == -1) break; 
  260. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') 
  261. $ptr++; 
  262. if ($type != '=') 
  263. $value = $this->Internal_StripQuotes($key); 
  264. else { 
  265. $ptr++; 
  266. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) == ' ') 
  267. $ptr++; 
  268. if ($type == '"') { 
  269. $value = $this->Internal_StripQuotes($pieces[$ptr++]); 
  270. else if ($type != -1) { 
  271. $value = $pieces[$ptr++]; 
  272. while (($type = $this->Internal_ClassifyPiece($ptr, $pieces)) != -1 
  273. && $type != ' ') 
  274. $value .= $pieces[$ptr++]; 
  275. else $value = ""; 
  276. if (substr($key, 0, 1) != '_') 
  277. $result[$key] = $value; 
  278. $params[] = Array('key' => $key, 'value' => $value); 
  279. $result['_params'] = $params; 
  280. return $result;