4fe6be7d73d37c1badf64f82c044dac7a93e5ae0
[atutor.git] / mods / phpdoc2 / PhpDocumentor / phpDocumentor / TutorialHighlightParser.inc
1 <?php\r
2 /**\r
3  * Source Code Highlighting\r
4  *\r
5  * The classes in this file are responsible for the dynamic @example, and\r
6  * <programlisting role="tutorial"> tags output.  Using the\r
7  * WordParser, the phpDocumentor_TutorialHighlightParser\r
8  * retrieves PHP tokens one by one from the array generated by\r
9  * {@link WordParser} source retrieval functions\r
10  * and then highlights them individually.\r
11  *\r
12  * It accomplishes this highlighting through the assistance of methods in\r
13  * the output Converter passed to its parse() method, and then returns the\r
14  * fully highlighted source as a string\r
15  * \r
16  * phpDocumentor :: automatic documentation generator\r
17  * \r
18  * PHP versions 4 and 5\r
19  *\r
20  * Copyright (c) 2003-2007 Gregory Beaver\r
21  * \r
22  * LICENSE:\r
23  * \r
24  * This library is free software; you can redistribute it\r
25  * and/or modify it under the terms of the GNU Lesser General\r
26  * Public License as published by the Free Software Foundation;\r
27  * either version 2.1 of the License, or (at your option) any\r
28  * later version.\r
29  * \r
30  * This library is distributed in the hope that it will be useful,\r
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
33  * Lesser General Public License for more details.\r
34  * \r
35  * You should have received a copy of the GNU Lesser General Public\r
36  * License along with this library; if not, write to the Free Software\r
37  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
38  *\r
39  * @category   ToolsAndUtilities\r
40  * @package    phpDocumentor\r
41  * @subpackage Parsers\r
42  * @author     Gregory Beaver <cellog@php.net>\r
43  * @copyright  2003-2007 Gregory Beaver\r
44  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL\r
45  * @version    CVS: $Id: TutorialHighlightParser.inc,v 1.7 2007/11/14 01:57:04 ashnazg Exp $\r
46  * @tutorial   tags.example.pkg, tags.filesource.pkg\r
47  * @link       http://www.phpdoc.org\r
48  * @link       http://pear.php.net/PhpDocumentor\r
49  * @since      1.3.0\r
50  * @todo       CS cleanup - change package to PhpDocumentor\r
51  * @todo       CS cleanup - PHPCS needs to ignore CVS Id length\r
52  */\r
53 \r
54 /**\r
55  * Highlights source code using {@link parse()}\r
56  *\r
57  * @category   ToolsAndUtilities\r
58  * @package    phpDocumentor\r
59  * @subpackage Parsers\r
60  * @author     Gregory Beaver <cellog@php.net>\r
61  * @copyright  2003-2007 Gregory Beaver\r
62  * @license    http://www.opensource.org/licenses/lgpl-license.php LGPL\r
63  * @version    Release: 1.4.1\r
64  * @link       http://www.phpdoc.org\r
65  * @link       http://pear.php.net/PhpDocumentor\r
66  * @todo       CS cleanup - change package to PhpDocumentor\r
67  * @todo       CS cleanup - change classname to PhpDocumentor_*\r
68  */\r
69 class phpDocumentor_TutorialHighlightParser extends Parser\r
70 {\r
71     /**#@+ @access private */\r
72     /**\r
73      * Highlighted source is built up in this string\r
74      * @var string\r
75      */\r
76     var $_output;\r
77     /**\r
78      * contents of the current source code line as it is parsed\r
79      * @var string\r
80      */\r
81     var $_line;\r
82     /**\r
83      * Used to retrieve highlighted tokens\r
84      * @var Converter a descendant of Converter\r
85      */\r
86     var $_converter;\r
87     /**\r
88      * Path to file being highlighted, if this is from a @filesource tag\r
89      * @var false|string full path\r
90      */\r
91     var $_filesourcepath;\r
92     /**\r
93      * @var array\r
94      */\r
95     var $eventHandlers = array(\r
96         TUTORIAL_EVENT_NOEVENTS    => 'defaultHandler',\r
97         TUTORIAL_EVENT_ITAG        => 'defaultHandler',\r
98         TUTORIAL_EVENT_ATTRIBUTE   => 'attrHandler',\r
99         TUTORIAL_EVENT_OPENTAG     => 'defaultHandler',\r
100         TUTORIAL_EVENT_CLOSETAG    => 'defaultHandler',\r
101         TUTORIAL_EVENT_ENTITY      => 'defaultHandler',\r
102         TUTORIAL_EVENT_COMMENT     => 'defaultHandler',\r
103         TUTORIAL_EVENT_SINGLEQUOTE => 'defaultHandler',\r
104         TUTORIAL_EVENT_DOUBLEQUOTE => 'defaultHandler',\r
105     );\r
106     /**#@-*/\r
107     \r
108     /**\r
109      * advances output to a new line\r
110      *\r
111      * @return void\r
112      * @uses Converter::SourceLine() encloses {@link $_line} in a\r
113      *                               converter-specific format\r
114      */\r
115     function newLineNum()\r
116     {\r
117         $this->_line   .= $this->_converter->flushHighlightCache();\r
118         $this->_output .= $this->_converter->SourceLine($this->_pv_curline + 1, \r
119             $this->_line, $this->_path);\r
120         $this->_line    = '';\r
121     }\r
122     \r
123     /**\r
124      * Start the parsing at a certain line number\r
125      *\r
126      * @param int $num the line number\r
127      *\r
128      * @return void\r
129      */\r
130     function setLineNum($num)\r
131     {\r
132         $this->_wp->linenum = $num;\r
133     }\r
134     \r
135     /**\r
136      * Parse a new file\r
137      *\r
138      * The parse() method is a do...while() loop that retrieves tokens one by\r
139      * one from the {@link $_event_stack}, and uses the token event array set up\r
140      * by the class constructor to call event handlers.\r
141      *\r
142      * The event handlers each process the tokens passed to them, and use the\r
143      * {@link _addoutput()} method to append the processed tokens to the\r
144      * {@link $_line} variable.  The word parser calls {@link newLineNum()}\r
145      * every time a line is reached.\r
146      *\r
147      * In addition, the event handlers use special linking functions\r
148      * {@link _link()} and its cousins (_classlink(), etc.) to create in-code\r
149      * hyperlinks to the documentation for source code elements that are in the\r
150      * source code.\r
151      *\r
152      * @param string        $parse_data     blah\r
153      * @param Converter     &$converter     blah\r
154      * @param false|string  $filesourcepath full path to file with @filesource tag,\r
155      *                                      if this is a @filesource parse\r
156      * @param false|integer $linenum        starting line number from\r
157      *                                      {@}source linenum}\r
158      *\r
159      * @staticvar integer used for recursion limiting if a handler for\r
160      *                    an event is not found\r
161      * @return    bool\r
162      * @uses setupStates() initialize parser state variables\r
163      * @uses configWordParser() pass $parse_data to prepare retrieval of tokens\r
164      * @todo CS cleanup - unable to get function signature below 85char wide\r
165      */\r
166     function parse($parse_data, &$converter, $filesourcepath = false, $linenum = false)\r
167     {\r
168         static $endrecur  = 0;\r
169         $parse_data       = \r
170             str_replace(array("\r\n", "\t"), array("\n", '    '), $parse_data);\r
171         $this->_converter = &$converter;\r
172         $converter->startHighlight();\r
173         $this->_path = $filesourcepath;\r
174         $this->setupStates($parse_data);\r
175 \r
176         $this->configWordParser(TUTORIAL_EVENT_NOEVENTS);\r
177         if ($linenum !== false) {\r
178             $this->setLineNum($linenum);\r
179         }\r
180         // initialize variables so E_ALL error_reporting doesn't complain\r
181         $pevent = 0;\r
182         $word   = 0;\r
183 \r
184         do {\r
185             $lpevent = $pevent;\r
186             $pevent  = $this->_event_stack->getEvent();\r
187             if ($lpevent != $pevent) {\r
188                 $this->_last_pevent = $lpevent;\r
189                 $this->configWordParser($pevent);\r
190             }\r
191             $this->_wp->setWhitespace(true);\r
192 \r
193             $dbg_linenum         = $this->_wp->linenum;\r
194             $dbg_pos             = $this->_wp->getPos();\r
195             $this->_pv_last_word = $word;\r
196             $this->_pv_curline   = $this->_wp->linenum;\r
197             $word                = $this->_wp->getWord();\r
198 \r
199             if (PHPDOCUMENTOR_DEBUG == true) {\r
200                 echo "LAST: ";\r
201                 echo "|" . $this->_pv_last_word;\r
202                 echo "|\n";\r
203                 echo "PEVENT: " . $this->getParserEventName($pevent) . "\n";\r
204                 echo "LASTPEVENT: " . \r
205                     $this->getParserEventName($this->_last_pevent) . "\n";\r
206                 //DEBUG echo "LINE: " . $this->_line . "\n";\r
207                 //DEBUG echo "OUTPUT: " . $this->_output . "\n";\r
208                 echo $dbg_linenum.'-'.$dbg_pos . ": ";\r
209                 echo '|'.htmlspecialchars($word);\r
210                 echo "|\n";\r
211                 echo "-------------------\n\n\n";\r
212                 flush();\r
213             }\r
214             if (isset($this->eventHandlers[$pevent])) {\r
215                 $handle = $this->eventHandlers[$pevent];\r
216                 $this->$handle($word, $pevent);\r
217             } else {\r
218                 debug('WARNING: possible error, no handler for event number '\r
219                     . $pevent);\r
220                 if ($endrecur++ == 25) {\r
221                     die("FATAL ERROR, recursion limit reached");\r
222                 }\r
223             }\r
224         } while (!($word === false));\r
225         if (strlen($this->_line)) {\r
226             $this->newLineNum();\r
227         }\r
228         return $this->_output;\r
229     }\r
230     \r
231     /**#@+\r
232      * Event Handlers\r
233      *\r
234      * All Event Handlers use {@link checkEventPush()} and\r
235      * {@link checkEventPop()} to set up the event stack and parser state.\r
236      *\r
237      * @param string|array $word   token value\r
238      * @param integer      $pevent parser event from {@link Parser.inc}\r
239      *\r
240      * @return void\r
241      * @access private\r
242      */\r
243     /**\r
244      * Most tokens only need highlighting, and this method handles them\r
245      *\r
246      * @todo CS cleanup - PHPCS needs to recognize docblock template tags\r
247      */\r
248     function defaultHandler($word, $pevent)\r
249     {\r
250         if ($word == "\n") {\r
251             $this->newLineNum();\r
252             return;\r
253         }\r
254         if ($this->checkEventPush($word, $pevent)) {\r
255             $this->_wp->backupPos($word);\r
256             return;\r
257         }\r
258         $this->_addoutput($word);\r
259         $this->checkEventPop($word, $pevent);\r
260     }\r
261 \r
262     /**\r
263      * Most tokens only need highlighting, and this method handles them\r
264      *\r
265      * @todo CS cleanup - PHPCS needs to recognize docblock template tags\r
266      */\r
267     function attrHandler($word, $pevent)\r
268     {\r
269         if ($word == "\n") {\r
270             $this->newLineNum();\r
271             return;\r
272         }\r
273         if ($e = $this->checkEventPush($word, $pevent)) {\r
274             if ($e == TUTORIAL_EVENT_SINGLEQUOTE \r
275                 || $e == TUTORIAL_EVENT_DOUBLEQUOTE\r
276             ) {\r
277                 $this->_addoutput($word);\r
278             }\r
279             return;\r
280         }\r
281         if ($this->checkEventPop($word, $pevent)) {\r
282             $this->_wp->backupPos($word);\r
283             return;\r
284         }\r
285         $this->_addoutput($word);\r
286     }\r
287     /**#@-*/\r
288     \r
289     /**#@+\r
290      * Output Methods\r
291      * @access private\r
292      */\r
293     /**\r
294      * This method adds output to {@link $_line}\r
295      *\r
296      * If a string with variables like "$test this" is present, then special\r
297      * handling is used to allow processing of the variable in context.\r
298      *\r
299      * @param string $word         the output to add\r
300      * @param bool   $preformatted whether or not its preformatted\r
301      *\r
302      * @return void\r
303      * @see _flush_save()\r
304      */\r
305     function _addoutput($word, $preformatted = false)\r
306     {\r
307         $type = array(\r
308             TUTORIAL_EVENT_ATTRIBUTE   => 'attribute',\r
309             TUTORIAL_EVENT_SINGLEQUOTE => 'attributevalue',\r
310             TUTORIAL_EVENT_DOUBLEQUOTE => 'attributevalue',\r
311             TUTORIAL_EVENT_CLOSETAG    => 'closetag',\r
312             TUTORIAL_EVENT_ENTITY      => 'entity',\r
313             TUTORIAL_EVENT_ITAG        => 'itag',\r
314             TUTORIAL_EVENT_OPENTAG     => 'opentag',\r
315             TUTORIAL_EVENT_COMMENT     => 'comment',\r
316         );\r
317 \r
318         $a = $this->_event_stack->getEvent();\r
319         if (in_array($a, array_keys($type))) {\r
320             $this->_line .= \r
321                 $this->_converter->highlightTutorialSource($type[$a], $word);\r
322         } else {\r
323             $this->_line .= $this->_converter->flushHighlightCache();\r
324             $this->_line .= $this->_converter->postProcess($word);\r
325         }\r
326     }\r
327     /**#@-*/\r
328 \r
329     /**\r
330      * Tell the parser's WordParser {@link $wp} to set up tokens to parse words by.\r
331      *\r
332      * Tokens are word separators.  In English, a space or punctuation are\r
333      * examples of tokens.  In PHP, a token can be a ;, a parenthesis, or \r
334      * even the word "function"\r
335      *\r
336      * @param integer $e an event number\r
337      *\r
338      * @return void\r
339      * @see WordParser\r
340      */\r
341     function configWordParser($e)\r
342     {\r
343         $this->_wp->setSeperator($this->tokens[($e + 100)]);\r
344     }\r
345 \r
346     /**#@+\r
347      * @param string|array $word   token value\r
348      * @param integer      $pevent parser event from {@link Parser.inc}\r
349      *\r
350      * @return mixed returns false, or the event number\r
351      */\r
352     /**\r
353      * This function checks whether parameter $word is a token \r
354      * for pushing a new event onto the Event Stack.\r
355      *\r
356      * @todo CS cleanup - PHPCS needs to recognize docblock template tags\r
357      */\r
358     function checkEventPush($word, $pevent)\r
359     {\r
360         $e = false;\r
361         if (isset($this->pushEvent[$pevent])) {\r
362             if (isset($this->pushEvent[$pevent][strtolower($word)])) {\r
363                 $e = $this->pushEvent[$pevent][strtolower($word)];\r
364             }\r
365         }\r
366         if ($e) {\r
367             $this->_event_stack->pushEvent($e);\r
368             return $e;\r
369         } else {\r
370             return false;\r
371         }\r
372     }\r
373 \r
374     /**\r
375      * This function checks whether parameter $word is a token \r
376      * for popping the current event off of the Event Stack.\r
377      *\r
378      * @todo CS cleanup - PHPCS needs to recognize docblock template tags\r
379      */\r
380     function checkEventPop($word, $pevent)\r
381     {\r
382         if (!isset($this->popEvent[$pevent])) {\r
383             return false;\r
384         }\r
385         if (in_array(strtolower($word), $this->popEvent[$pevent])) {\r
386             return $this->_event_stack->popEvent();\r
387         } else {\r
388             return false;\r
389         }\r
390     }\r
391     /**#@-*/\r
392 \r
393     /**\r
394      * Initialize all parser state variables\r
395      *\r
396      * @param bool|string $parsedata true if we are highlighting an inline {@}source}\r
397      *                               tag's output, or the name of class we are going \r
398      *                               to start from\r
399      *\r
400      * @return void\r
401      * @uses $_wp sets to a new {@link phpDocumentor_HighlightWordParser}\r
402      */\r
403     function setupStates($parsedata)\r
404     {\r
405         $this->_output = '';\r
406         $this->_line   = '';\r
407 \r
408         unset($this->_wp);\r
409         $this->_wp = new WordParser;\r
410         $this->_wp->setup($parsedata);\r
411 \r
412         $this->_event_stack = new EventStack;\r
413         $this->_event_stack->popEvent();\r
414         $this->_event_stack->pushEvent(TUTORIAL_EVENT_NOEVENTS);\r
415 \r
416         $this->_pv_linenum   = null;\r
417         $this->_pv_next_word = false;\r
418     }\r
419 \r
420     /**\r
421      * Initialize the {@link $tokenpushEvent, $wordpushEvent} arrays\r
422      */\r
423     function phpDocumentor_TutorialHighlightParser()\r
424     {\r
425         $this->allowableInlineTags                = \r
426             $GLOBALS['_phpDocumentor_inline_tutorial_tags_allowed']\r
427         ;\r
428         $this->inlineTagHandlers                  = \r
429             array('*' => 'handleDefaultInlineTag')\r
430         ;\r
431         $this->tokens[STATE_TUTORIAL_NOEVENTS]    = \r
432             array("\n",'{@', '<!--', '</', '<', '&');\r
433         $this->tokens[STATE_TUTORIAL_ITAG]        = array("\n","}");\r
434         $this->tokens[STATE_TUTORIAL_OPENTAG]     = array("\n","\t"," ", '>', '/>');\r
435         $this->tokens[STATE_TUTORIAL_CLOSETAG]    = array("\n",'>');\r
436         $this->tokens[STATE_TUTORIAL_COMMENT]     = array("\n",'-->');\r
437         $this->tokens[STATE_TUTORIAL_ENTITY]      = array("\n",';');\r
438         $this->tokens[STATE_TUTORIAL_ATTRIBUTE]   = array("\n",'"',"'",'>','/>');\r
439         $this->tokens[STATE_TUTORIAL_DOUBLEQUOTE] = array("\n",'"','&','{@');\r
440         $this->tokens[STATE_TUTORIAL_SINGLEQUOTE] = array("\n","'",'&','{@');\r
441         /**************************************************************/\r
442 \r
443         $this->pushEvent[TUTORIAL_EVENT_NOEVENTS] = array(\r
444             "{@"   => TUTORIAL_EVENT_ITAG,\r
445             '<'    => TUTORIAL_EVENT_OPENTAG,\r
446             '</'   => TUTORIAL_EVENT_CLOSETAG,\r
447             '&'    => TUTORIAL_EVENT_ENTITY,\r
448             '<!--' => TUTORIAL_EVENT_COMMENT,\r
449         );\r
450         /**************************************************************/\r
451 \r
452         $this->pushEvent[TUTORIAL_EVENT_OPENTAG] = array(\r
453             " "  => TUTORIAL_EVENT_ATTRIBUTE,\r
454             "\n" => TUTORIAL_EVENT_ATTRIBUTE,\r
455         );\r
456         /**************************************************************/\r
457 \r
458         $this->pushEvent[TUTORIAL_EVENT_ATTRIBUTE] = array(\r
459             "'" => TUTORIAL_EVENT_SINGLEQUOTE,\r
460             '"' => TUTORIAL_EVENT_DOUBLEQUOTE,\r
461         );\r
462         /**************************************************************/\r
463 \r
464         $this->pushEvent[TUTORIAL_EVENT_SINGLEQUOTE] = array(\r
465             '&'  => TUTORIAL_EVENT_ENTITY,\r
466             '{@' => TUTORIAL_EVENT_ITAG,\r
467         );\r
468         /**************************************************************/\r
469 \r
470         $this->pushEvent[TUTORIAL_EVENT_DOUBLEQUOTE] = array(\r
471             '&'  => TUTORIAL_EVENT_ENTITY,\r
472             '{@' => TUTORIAL_EVENT_ITAG,\r
473         );\r
474         /**************************************************************/\r
475 \r
476         $this->popEvent[TUTORIAL_EVENT_ENTITY] = array(';');\r
477         /**************************************************************/\r
478 \r
479         $this->popEvent[TUTORIAL_EVENT_SINGLEQUOTE] = array("'");\r
480         /**************************************************************/\r
481 \r
482         $this->popEvent[TUTORIAL_EVENT_DOUBLEQUOTE] = array('"');\r
483         /**************************************************************/\r
484 \r
485         $this->popEvent[TUTORIAL_EVENT_OPENTAG] = array('>', '/>');\r
486         /**************************************************************/\r
487 \r
488         $this->popEvent[TUTORIAL_EVENT_CLOSETAG] = array('>');\r
489         /**************************************************************/\r
490 \r
491         $this->popEvent[TUTORIAL_EVENT_COMMENT] = array('-->');\r
492         /**************************************************************/\r
493 \r
494         $this->popEvent[TUTORIAL_EVENT_ATTRIBUTE] = array('>','/>');\r
495         /**************************************************************/\r
496 \r
497         $this->popEvent[TUTORIAL_EVENT_ITAG] = array('}');\r
498         /**************************************************************/\r
499     }\r
500 \r
501     /**\r
502      * searches for a parser event name based on its number\r
503      *\r
504      * @param int $value the event number\r
505      *\r
506      * @return string|int the event name, or the original value\r
507      */\r
508     function getParserEventName ($value)\r
509     {    \r
510         $lookup = array(\r
511             TUTORIAL_EVENT_NOEVENTS    => "TUTORIAL_EVENT_NOEVENTS",\r
512             TUTORIAL_EVENT_ITAG        => "TUTORIAL_EVENT_ITAG",\r
513             TUTORIAL_EVENT_OPENTAG     => "TUTORIAL_EVENT_OPENTAG",\r
514             TUTORIAL_EVENT_ATTRIBUTE   => "TUTORIAL_EVENT_ATTRIBUTE",\r
515             TUTORIAL_EVENT_CLOSETAG    => "TUTORIAL_EVENT_CLOSETAG",\r
516             TUTORIAL_EVENT_ENTITY      => "TUTORIAL_EVENT_ENTITY",\r
517             TUTORIAL_EVENT_COMMENT     => "TUTORIAL_EVENT_COMMENT",\r
518             TUTORIAL_EVENT_SINGLEQUOTE => "TUTORIAL_EVENT_SINGLEQUOTE",\r
519             TUTORIAL_EVENT_DOUBLEQUOTE => "TUTORIAL_EVENT_DOUBLEQUOTE",\r
520         );\r
521         if (isset($lookup[$value])) {\r
522             return $lookup[$value];\r
523         } else {\r
524             return $value;\r
525         }\r
526     }\r
527 }\r
528 \r
529 \r
530 /**\r
531  * starting state\r
532  */\r
533 define("TUTORIAL_EVENT_NOEVENTS", 1);\r
534 \r
535 /**\r
536  * currently in starting state\r
537  */\r
538 define("STATE_TUTORIAL_NOEVENTS", 101);\r
539 \r
540 /**\r
541  * used when an {@}inline tag} is found\r
542  */\r
543 define("TUTORIAL_EVENT_ITAG", 2);\r
544 \r
545 /**\r
546  * currently parsing an {@}inline tag}\r
547  */\r
548 define("STATE_TUTORIAL_ITAG", 102);\r
549 \r
550 /**\r
551  * used when an open <tag> is found\r
552  */\r
553 define("TUTORIAL_EVENT_OPENTAG", 3);\r
554 \r
555 /**\r
556  * currently parsing an open <tag>\r
557  */\r
558 define("STATE_TUTORIAL_OPENTAG", 103);\r
559 \r
560 /**\r
561  * used when a <tag attr="attribute"> is found\r
562  */\r
563 define("TUTORIAL_EVENT_ATTRIBUTE", 4);\r
564 \r
565 /**\r
566  * currently parsing an open <tag>\r
567  */\r
568 define("STATE_TUTORIAL_ATTRIBUTE", 104);\r
569 \r
570 /**\r
571  * used when a close </tag> is found\r
572  */\r
573 define("TUTORIAL_EVENT_CLOSETAG", 5);\r
574 \r
575 /**\r
576  * currently parsing a close </tag>\r
577  */\r
578 define("STATE_TUTORIAL_CLOSETAG", 105);\r
579 \r
580 /**\r
581  * used when an &entity; is found\r
582  */\r
583 define("TUTORIAL_EVENT_ENTITY", 6);\r
584 \r
585 /**\r
586  * currently parsing an &entity;\r
587  */\r
588 define("STATE_TUTORIAL_ENTITY", 106);\r
589 \r
590 /**\r
591  * used when a <!-- comment --> is found\r
592  */\r
593 define("TUTORIAL_EVENT_COMMENT", 7);\r
594 \r
595 /**\r
596  * currently parsing a <!-- comment -->\r
597  */\r
598 define("STATE_TUTORIAL_COMMENT", 107);\r
599 \r
600 /**\r
601  * used when a <!-- comment --> is found\r
602  */\r
603 define("TUTORIAL_EVENT_SINGLEQUOTE", 8);\r
604 \r
605 /**\r
606  * currently parsing a <!-- comment -->\r
607  */\r
608 define("STATE_TUTORIAL_SINGLEQUOTE", 108);\r
609 \r
610 /**\r
611  * used when a <!-- comment --> is found\r
612  */\r
613 define("TUTORIAL_EVENT_DOUBLEQUOTE", 9);\r
614 \r
615 /**\r
616  * currently parsing a <!-- comment -->\r
617  */\r
618 define("STATE_TUTORIAL_DOUBLEQUOTE", 109);\r
619 \r
620 ?>\r