PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/xhp/scanner.l

http://github.com/facebook/xhp
LEX | 1103 lines | 980 code | 54 blank | 69 comment | 0 complexity | 8ee1248a303cedc14c964a835c5cc732 MD5 | raw file
Possible License(s): MIT, MPL-2.0-no-copyleft-exception
  1. /*
  2. +----------------------------------------------------------------------+
  3. | XHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
  6. | Copyright (c) 2009 - 2010 Facebook, Inc. (http://www.facebook.com) |
  7. +----------------------------------------------------------------------+
  8. | This source file is subject to version 2.00 of the Zend license, |
  9. | that is bundled with this package in the file LICENSE.ZEND, and is |
  10. | available through the world-wide-web at the following url: |
  11. | http://www.zend.com/license/2_00.txt. |
  12. | If you did not receive a copy of the Zend license and are unable to |
  13. | obtain it through the world-wide-web, please send a note to |
  14. | license@zend.com so we can mail you a copy immediately. |
  15. +----------------------------------------------------------------------+
  16. */
  17. %{
  18. #include "xhp.hpp"
  19. #include <string.h>
  20. // A PHP file is made of multiple languages, each with its own lexing rules.
  21. // The starting mode or state is the HTML state, then comes the PHP state,
  22. // and with XHP there is even an XHP state. Certain tokens indicate a
  23. // transition from one state to another and the macros below are used to
  24. // manage this state.
  25. #define push_state(s) xhp_new_push_state(s, yyg)
  26. #define pop_state() xhp_new_pop_state(yyg)
  27. #define set_state(s) xhp_set_state(s, yyg)
  28. // This is used to help contextual lexing. For instance 'attribute' is
  29. // considered a XHP keyword after a '{' of a class definition,
  30. // but a regular identifier in other contexts.
  31. #define last_token() yyextra->last_token
  32. #define YY_USER_ACTION \
  33. if (yyextra->terminated) \
  34. return 0; \
  35. if (!yyg->yy_more_len) \
  36. yyextra->first_lineno = yyextra->lineno;
  37. #define tok(t) \
  38. if (yyextra->has_doc_block) { \
  39. *yylval = yyextra->doc_block + code_rope(yytext, yyextra->first_lineno, yyextra->lineno - yyextra->first_lineno); \
  40. yyextra->has_doc_block = false; \
  41. } else { \
  42. *yylval = code_rope(yytext, yyextra->first_lineno, yyextra->lineno - yyextra->first_lineno); \
  43. } \
  44. return yy_token(t, yyg)
  45. #ifdef DEBUG
  46. static void yy_log_token(int tok);
  47. #define tokt(t) *yylval = t; push_state(XHP_AFTER_ENT); yy_log_token(T_XHP_TEXT); return yyextra->last_token = T_XHP_TEXT;
  48. #else
  49. #define tokt(t) *yylval = t; push_state(XHP_AFTER_ENT); return yyextra->last_token = T_XHP_TEXT;
  50. #endif
  51. #define YY_USER_INIT \
  52. if (yyextra->insert_token) { \
  53. yyg->yy_init = 0; \
  54. int ft = yyextra->insert_token; \
  55. yyextra->insert_token = 0; \
  56. return yy_token(ft, yyg); \
  57. }
  58. using namespace std;
  59. const char* yytokname(int tok);
  60. static int yy_token(int tok, struct yyguts_t* yyg);
  61. static void yy_scan_newlines(const char* text, struct yyguts_t* yyg);
  62. static bool utf8ize(uint32_t v, char* buf /* [5] */) {
  63. if (v <= 0x7f) { // 0xxxxxxx
  64. buf[0] = v;
  65. buf[1] = 0;
  66. } else if (v <= 0x7ff) { // 110yyyxx 10xxxxxx
  67. buf[0] = 0xc0 | (v >> 6);
  68. buf[1] = 0x80 | (v & 0x3f);
  69. buf[2] = 0;
  70. } else if (v <= 0xffff) { // 1110yyyy 10yyyyxx 10xxxxxx
  71. buf[0] = 0xe0 | (v >> 12);
  72. buf[1] = 0x80 | ((v >> 6) & 0x3f);
  73. buf[2] = 0x80 | (v & 0x3f);
  74. buf[3] = 0;
  75. } else if (v <= 0x1fffff) { // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
  76. buf[0] = 0xf0 | (v >> 18);
  77. buf[1] = 0x80 | ((v >> 12) & 0x3f);
  78. buf[2] = 0x80 | ((v >> 6) & 0x3f);
  79. buf[3] = 0x80 | (v & 0x3f);
  80. buf[4] = 0;
  81. } else {
  82. return false;
  83. }
  84. return true;
  85. }
  86. %}
  87. %option prefix="xhp"
  88. %option reentrant
  89. /* PHP allows IF or if */
  90. %option case-insensitive
  91. %option noyywrap nodefault
  92. %option stack
  93. %option bison-bridge
  94. %option 8bit
  95. /* I think an interactive scanner is required because of the bison state
  96. * pushing we do. I'm putting an explicit interactive declaration here in case
  97. * someone tries adding -CF or whatever to the make flags. */
  98. %option interactive
  99. /* The different lexing states. Note that the transitions are done either
  100. * in the lex actions, or in a generic manner in yy_token(). */
  101. %s PHP
  102. %s PHP_COMMENT
  103. %s PHP_EOL_COMMENT
  104. %s PHP_DOC_COMMENT
  105. %s PHP_HEREDOC_START
  106. %s PHP_HEREDOC_NSTART
  107. %s PHP_HEREDOC_NEWLINE
  108. %s PHP_HEREDOC_DATA
  109. %s PHP_NO_RESERVED_WORDS
  110. %s PHP_NO_RESERVED_WORDS_PERSIST
  111. %s XHP_LABEL
  112. %s XHP_LABEL_WHITESPACE
  113. %s XHP_ATTRS
  114. %s XHP_ATTR_VAL
  115. %s XHP_AFTER_ENT
  116. %s XHP_CHILD
  117. %s XHP_CHILD_START
  118. %s XHP_INVALID_ENTITY
  119. %s XHP_ATTR_TYPE_DECL
  120. %s XHP_CHILDREN_DECL
  121. LNUM [0-9]+
  122. DNUM ([0-9]*"."[0-9]+)|([0-9]+"."[0-9]*)
  123. EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM})
  124. HNUM "0x"[0-9a-fA-F]+
  125. LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
  126. BYTE (.|\n)
  127. WHITESPACE [ \n\r\t]+
  128. TABS_AND_SPACES [ \t]*
  129. NEWLINE ("\r\n"|"\n"|"\r")
  130. %%
  131. <XHP_ATTR_TYPE_DECL>{
  132. "bool" tok(T_XHP_BOOLEAN);
  133. "int" tok(T_XHP_NUMBER);
  134. "float" tok(T_XHP_FLOAT);
  135. "var" tok(T_VAR);
  136. "array" tok(T_XHP_ARRAY);
  137. "string" tok(T_XHP_STRING);
  138. "enum" tok(T_XHP_ENUM);
  139. @required tok(T_XHP_REQUIRED);
  140. "(" tok('(');
  141. ":" tok(T_XHP_COLON);
  142. }
  143. /* Open / close PHP + inline HTML */
  144. <INITIAL>{
  145. "<?php"([ \t]|{NEWLINE}) {
  146. yy_scan_newlines(yytext + 5, yyg);
  147. // the state transition will be done in yy_token()
  148. tok(T_OPEN_TAG);
  149. }
  150. "<?" {
  151. if (yyextra->short_tags) {
  152. tok(T_OPEN_TAG);
  153. } else {
  154. tok(T_INLINE_HTML);
  155. }
  156. }
  157. "<?=" {
  158. if (yyextra->short_tags) {
  159. tok(T_OPEN_TAG_WITH_ECHO);
  160. } else {
  161. tok(T_INLINE_HTML);
  162. }
  163. }
  164. "<%" {
  165. if (yyextra->asp_tags) {
  166. tok(T_OPEN_TAG);
  167. } else {
  168. tok(T_INLINE_HTML);
  169. }
  170. }
  171. "<%=" {
  172. if (yyextra->asp_tags) {
  173. tok(T_OPEN_TAG_WITH_ECHO);
  174. } else {
  175. tok(T_INLINE_HTML);
  176. }
  177. }
  178. "<"|[^<]* {
  179. yy_scan_newlines(yytext, yyg);
  180. tok(T_INLINE_HTML);
  181. }
  182. }
  183. <PHP,PHP_NO_RESERVED_WORDS,PHP_NO_RESERVED_WORDS_PERSIST>{
  184. ("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {
  185. yy_scan_newlines(yytext + 2, yyg);
  186. tok(T_CLOSE_TAG);
  187. }
  188. "%>" {
  189. if (yyextra->asp_tags) {
  190. tok(T_CLOSE_TAG);
  191. } else {
  192. yyless(1);
  193. tok(yytext[0]);
  194. }
  195. }
  196. }
  197. /* Comments and whitespace */
  198. <PHP,PHP_NO_RESERVED_WORDS,PHP_NO_RESERVED_WORDS_PERSIST,XHP_CHILDREN_DECL,XHP_ATTR_TYPE_DECL>{
  199. "#"|"//" {
  200. push_state(PHP_EOL_COMMENT);
  201. yymore();
  202. }
  203. "/**"{WHITESPACE} {
  204. yy_scan_newlines(yytext + 3, yyg);
  205. push_state(PHP_DOC_COMMENT);
  206. yymore();
  207. }
  208. "/*" {
  209. push_state(PHP_COMMENT);
  210. yymore();
  211. }
  212. {WHITESPACE}+ yy_scan_newlines(yytext, yyg);
  213. }
  214. <PHP_EOL_COMMENT>{
  215. {NEWLINE} {
  216. ++yyextra->lineno;
  217. pop_state();
  218. }
  219. [^\r\n?]+ yymore();
  220. "?>" {
  221. yyless(yyleng - 2);
  222. pop_state();
  223. }
  224. . yymore();
  225. }
  226. <PHP_DOC_COMMENT,PHP_COMMENT>{
  227. {NEWLINE} {
  228. ++yyextra->lineno;
  229. yymore();
  230. }
  231. [^*\r\n]+|"*" yymore();
  232. }
  233. <PHP_DOC_COMMENT>"*/" {
  234. yyextra->doc_block = code_rope(yytext, yyextra->first_lineno, yyextra->lineno - yyextra->first_lineno);
  235. yyextra->has_doc_block = true;
  236. pop_state();
  237. }
  238. <PHP_COMMENT>"*/" pop_state();
  239. /* Reserved words */
  240. <PHP>{
  241. include tok(T_INCLUDE);
  242. include_once tok(T_INCLUDE_ONCE);
  243. eval tok(T_EVAL);
  244. require tok(T_REQUIRE);
  245. require_once tok(T_REQUIRE_ONCE);
  246. or tok(T_LOGICAL_OR);
  247. xor tok(T_LOGICAL_XOR);
  248. and tok(T_LOGICAL_AND);
  249. print tok(T_PRINT);
  250. instanceof tok(T_INSTANCEOF);
  251. new tok(T_NEW);
  252. clone tok(T_CLONE);
  253. exit tok(T_EXIT);
  254. if tok(T_IF);
  255. elseif tok(T_ELSEIF);
  256. else tok(T_ELSE);
  257. endif tok(T_ENDIF);
  258. echo tok(T_ECHO);
  259. do tok(T_DO);
  260. while tok(T_WHILE);
  261. endwhile tok(T_ENDWHILE);
  262. for tok(T_FOR);
  263. endfor tok(T_ENDFOR);
  264. foreach tok(T_FOREACH);
  265. endforeach tok(T_ENDFOREACH);
  266. declare tok(T_DECLARE);
  267. enddeclare tok(T_ENDDECLARE);
  268. as tok(T_AS);
  269. switch tok(T_SWITCH);
  270. endswitch tok(T_ENDSWITCH);
  271. case tok(T_CASE);
  272. default tok(T_DEFAULT);
  273. break tok(T_BREAK);
  274. continue tok(T_CONTINUE);
  275. goto tok(T_GOTO);
  276. function tok(T_FUNCTION);
  277. const tok(T_CONST);
  278. return tok(T_RETURN);
  279. try tok(T_TRY);
  280. catch tok(T_CATCH);
  281. throw tok(T_THROW);
  282. use tok(T_USE);
  283. global tok(T_GLOBAL);
  284. static tok(T_STATIC);
  285. abstract tok(T_ABSTRACT);
  286. final tok(T_FINAL);
  287. private tok(T_PRIVATE);
  288. protected tok(T_PROTECTED);
  289. public tok(T_PUBLIC);
  290. var tok(T_VAR);
  291. unset tok(T_UNSET);
  292. isset tok(T_ISSET);
  293. empty tok(T_EMPTY);
  294. __halt_compiler tok(T_HALT_COMPILER);
  295. class tok(T_CLASS);
  296. interface tok(T_INTERFACE);
  297. extends tok(T_EXTENDS);
  298. implements tok(T_IMPLEMENTS);
  299. list tok(T_LIST);
  300. array tok(T_ARRAY);
  301. __class__ tok(T_CLASS_C);
  302. __method__ tok(T_METHOD_C);
  303. __function__ tok(T_FUNC_C);
  304. __line__ tok(T_LINE);
  305. __file__ tok(T_FILE);
  306. namespace tok(T_NAMESPACE);
  307. __namespace__ tok(T_NS_C);
  308. __dir__ tok(T_DIR);
  309. attribute {
  310. // expecting_xhp_class_statements is set in some actions in the grammar.
  311. // This means the lexer and parser are interdependent.
  312. if ((last_token() == '{' || last_token() == '}' || last_token() == ';') &&
  313. (yyextra->expecting_xhp_class_statements)) {
  314. tok(T_XHP_ATTRIBUTE);
  315. } else {
  316. tok(T_STRING);
  317. }
  318. }
  319. category {
  320. if ((last_token() == '{' || last_token() == '}' || last_token() == ';') &&
  321. (yyextra->expecting_xhp_class_statements)) {
  322. tok(T_XHP_CATEGORY);
  323. } else {
  324. tok(T_STRING);
  325. }
  326. }
  327. children {
  328. if ((last_token() == '{' || last_token() == '}' || last_token() == ';') &&
  329. (yyextra->expecting_xhp_class_statements)) {
  330. tok(T_XHP_CHILDREN);
  331. } else {
  332. tok(T_STRING);
  333. }
  334. }
  335. }
  336. /* Operators */
  337. <PHP,PHP_NO_RESERVED_WORDS,PHP_NO_RESERVED_WORDS_PERSIST,XHP_ATTR_TYPE_DECL>{
  338. "+=" tok(T_PLUS_EQUAL);
  339. "-=" tok(T_MINUS_EQUAL);
  340. "*=" tok(T_MUL_EQUAL);
  341. "/=" tok(T_DIV_EQUAL);
  342. ".=" tok(T_CONCAT_EQUAL);
  343. "%=" tok(T_MOD_EQUAL);
  344. "&=" tok(T_AND_EQUAL);
  345. "|=" tok(T_OR_EQUAL);
  346. "^=" tok(T_XOR_EQUAL);
  347. "<<=" tok(T_SL_EQUAL);
  348. ">>=" tok(T_SR_EQUAL);
  349. "||" tok(T_BOOLEAN_OR);
  350. "&&" tok(T_BOOLEAN_AND);
  351. "==" tok(T_IS_EQUAL);
  352. "!="|"<>" tok(T_IS_NOT_EQUAL);
  353. "===" tok(T_IS_IDENTICAL);
  354. "!==" tok(T_IS_NOT_IDENTICAL);
  355. "<=" tok(T_IS_SMALLER_OR_EQUAL);
  356. ">=" tok(T_IS_GREATER_OR_EQUAL);
  357. "<<" tok(T_SL);
  358. ">>" tok(T_SR);
  359. "++" tok(T_INC);
  360. "--" tok(T_DEC);
  361. "->" tok(T_OBJECT_OPERATOR);
  362. "=>" tok(T_DOUBLE_ARROW);
  363. "::" tok(T_PAAMAYIM_NEKUDOTAYIM);
  364. "\\" tok(T_NS_SEPARATOR);
  365. ":" {
  366. // A colon can either mean the start (or component) of an XHP class,
  367. // a ternary expression (as in 1?false:null), the colon of a 'case',
  368. // or finally the start of a block in the old PHP syntax. The following
  369. // disambiguate between the XHP case, which requires a special token,
  370. // and the other cases.
  371. switch (yyextra->last_token) {
  372. // In a ternary expression, the colon must follow a full-fledged
  373. // expression so seeing for instance a binary operator means
  374. // it must be an XHP class.
  375. case ',': case '=': case '|': case '^': case '&': case '<': case '>':
  376. case '+': case '-': case '%': case '!': case '~': case '[': case '(':
  377. case '{': case '.':
  378. case T_LOGICAL_OR: case T_LOGICAL_XOR: case T_LOGICAL_AND:
  379. case T_PLUS_EQUAL: case T_MINUS_EQUAL: case T_MUL_EQUAL:
  380. case T_DIV_EQUAL: case T_CONCAT_EQUAL: case T_MOD_EQUAL:
  381. case T_AND_EQUAL: case T_OR_EQUAL: case T_XOR_EQUAL:
  382. case T_SL_EQUAL: case T_SR_EQUAL: case T_BOOLEAN_OR:
  383. case T_BOOLEAN_AND: case T_IS_EQUAL: case T_IS_NOT_EQUAL:
  384. case T_IS_IDENTICAL: case T_IS_NOT_IDENTICAL: case T_IS_SMALLER_OR_EQUAL:
  385. case T_IS_GREATER_OR_EQUAL:
  386. // An XHP class can also occur after certain keywords. Not sure
  387. // we got them all covered though.
  388. case T_ECHO: case T_RETURN:
  389. case T_EXTENDS: case T_INSTANCEOF: case T_DOUBLE_ARROW:
  390. case T_XHP_ATTRIBUTE:
  391. tok(T_XHP_COLON);
  392. break;
  393. default:
  394. tok(':');
  395. break;
  396. }
  397. }
  398. }
  399. /* Casts */
  400. <PHP,PHP_NO_RESERVED_WORDS,PHP_NO_RESERVED_WORDS_PERSIST>{
  401. "("{TABS_AND_SPACES}(int|integer){TABS_AND_SPACES}")" tok(T_INT_CAST);
  402. "("{TABS_AND_SPACES}(real|double|float){TABS_AND_SPACES}")" tok(T_DOUBLE_CAST);
  403. "("{TABS_AND_SPACES}string{TABS_AND_SPACES}")" tok(T_STRING_CAST);
  404. "("{TABS_AND_SPACES}unicode{TABS_AND_SPACES}")" tok(T_UNICODE_CAST);
  405. "("{TABS_AND_SPACES}binary{TABS_AND_SPACES}")" tok(T_BINARY_CAST);
  406. "("{TABS_AND_SPACES}array{TABS_AND_SPACES}")" tok(T_ARRAY_CAST);
  407. "("{TABS_AND_SPACES}object{TABS_AND_SPACES}")" tok(T_OBJECT_CAST);
  408. "("{TABS_AND_SPACES}(bool|boolean){TABS_AND_SPACES}")" tok(T_BOOL_CAST);
  409. "("{TABS_AND_SPACES}unset{TABS_AND_SPACES}")" tok(T_UNSET_CAST);
  410. }
  411. /* Scalars (parsing these doesn't really matter since we just pass them through literally) */
  412. <PHP,PHP_NO_RESERVED_WORDS,PHP_NO_RESERVED_WORDS_PERSIST,XHP_ATTR_TYPE_DECL>{
  413. {LNUM}|{HNUM} tok(T_LNUMBER);
  414. {DNUM}|{EXPONENT_DNUM} tok(T_DNUMBER);
  415. {LABEL} tok(T_STRING);
  416. "$"{LABEL} tok(T_VARIABLE);
  417. b?'(\\.|\\\n|[^\\']+)*'|b?\"(\\.|\\\n|[^\\\"]+)*\" {
  418. yy_scan_newlines(yytext, yyg);
  419. tok(T_CONSTANT_ENCAPSED_STRING);
  420. }
  421. `[^`]*` {
  422. yy_scan_newlines(yytext, yyg);
  423. tok(T_BACKTICKS_EXPR);
  424. }
  425. }
  426. /* (HERE|NOW)DOC's */
  427. <PHP,PHP_NO_RESERVED_WORDS,PHP_NO_RESERVED_WORDS_PERSIST>b?"<<<"{TABS_AND_SPACES} {
  428. push_state(PHP_HEREDOC_START);
  429. yyextra->heredoc_yyleng = yyleng;
  430. yymore();
  431. }
  432. <PHP_HEREDOC_START>{
  433. "'"{LABEL}"'"|\"{LABEL}\" {
  434. // Create a new string for the heredoc label. Since we're using yymore above
  435. // yytext will actually start at the "<<<" and not the label. Use of
  436. // heredoc_yyleng jumps past that. Then we add 1 to get past the " or '. The
  437. // match is similar to calculate length.
  438. yyextra->heredoc_label = string(yytext + yyextra->heredoc_yyleng + 1, yyleng - yyextra->heredoc_yyleng - 2);
  439. set_state(PHP_HEREDOC_NSTART);
  440. yyextra->heredoc_yyleng = yyleng;
  441. yymore();
  442. }
  443. {LABEL} {
  444. yyextra->heredoc_label = string(yytext + yyextra->heredoc_yyleng);
  445. set_state(PHP_HEREDOC_NSTART);
  446. yyextra->heredoc_yyleng = yyleng;
  447. yymore();
  448. }
  449. }
  450. <PHP_HEREDOC_NSTART>{NEWLINE} {
  451. ++yyextra->lineno;
  452. yyextra->heredoc_data = yytext + yyleng;
  453. set_state(PHP_HEREDOC_DATA);
  454. yymore();
  455. }
  456. <PHP_HEREDOC_DATA>{
  457. [^\r\n]*{NEWLINE} {
  458. ++yyextra->lineno;
  459. set_state(PHP_HEREDOC_NEWLINE);
  460. yyextra->heredoc_yyleng = yyleng;
  461. yymore();
  462. }
  463. }
  464. <PHP_HEREDOC_NEWLINE>{
  465. {LABEL};?{NEWLINE} {
  466. if (strncmp(yyextra->heredoc_label.c_str(), yytext + yyextra->heredoc_yyleng, yyextra->heredoc_label.size()) == 0) {
  467. switch (yytext[yyextra->heredoc_yyleng + yyextra->heredoc_label.size()]) {
  468. case ';': case '\n': case '\r':
  469. yyless(yyleng - (yyleng - yyextra->heredoc_yyleng - yyextra->heredoc_label.size()));
  470. pop_state();
  471. tok(T_HEREDOC);
  472. }
  473. }
  474. ++yyextra->lineno;
  475. yyextra->heredoc_yyleng = yyleng;
  476. yymore();
  477. }
  478. [^\r\n]+ {
  479. set_state(PHP_HEREDOC_DATA);
  480. yyextra->heredoc_yyleng = yyleng;
  481. yymore();
  482. }
  483. {NEWLINE} {
  484. ++yyextra->lineno;
  485. yyextra->heredoc_yyleng = yyleng;
  486. yymore();
  487. }
  488. }
  489. /* XHP */
  490. <XHP_LABEL_WHITESPACE>{
  491. {WHITESPACE}+ yy_scan_newlines(yytext, yyg);
  492. }
  493. <XHP_LABEL,XHP_LABEL_WHITESPACE>{
  494. ":" tok(T_XHP_COLON);
  495. "-" tok(T_XHP_HYPHEN);
  496. "::" {
  497. pop_state();
  498. // Hack: Please don't expect this to work: $foo = <a href={Thing::if} />;
  499. // PHP will let you use reserved words for member variables and methods, but
  500. // they are verboten in XHP classes now.
  501. //
  502. // We don't use tok() because that pushes PHP_NO_RESERVED_WORDS, which the
  503. // scanner expects to pop at some point, but XHP_LABEL (in parser.y) will pop
  504. // sooner and then you're left with an imbalanced tag stack and that's when
  505. // the fun stops.
  506. *yylval = code_rope(yytext, yyextra->first_lineno, yyextra->lineno - yyextra->first_lineno);
  507. #ifdef DEBUG
  508. yy_log_token(T_PAAMAYIM_NEKUDOTAYIM);
  509. #endif
  510. return T_PAAMAYIM_NEKUDOTAYIM;
  511. }
  512. "--" {
  513. pop_state();
  514. tok(T_DEC);
  515. }
  516. {WHITESPACE} {
  517. yy_scan_newlines(yytext, yyg);
  518. pop_state();
  519. tok(T_XHP_WHITESPACE);
  520. }
  521. {LABEL} tok(T_STRING);
  522. . {
  523. pop_state();
  524. tok(yytext[0]);
  525. }
  526. }
  527. <XHP_ATTRS>{
  528. "="|"/"|">" tok(yytext[0]);
  529. {WHITESPACE}+ yy_scan_newlines(yytext, yyg);
  530. {LABEL} tok(T_STRING);
  531. }
  532. <XHP_ATTR_VAL>{
  533. [^&'\\"]+ tok(T_XHP_TEXT);
  534. \" {
  535. pop_state();
  536. tok('"');
  537. }
  538. }
  539. <XHP_CHILD_START>{
  540. {WHITESPACE}+ {
  541. /* ignore whitespace at the start */
  542. yy_scan_newlines(yytext, yyg);
  543. unput(' ');
  544. set_state(XHP_CHILD);
  545. }
  546. . {
  547. yyless(0);
  548. set_state(XHP_CHILD);
  549. }
  550. }
  551. /* Below we use tokt() (and not tok) which internally transits to
  552. * the XHP_AFTER_ENT state. */
  553. <XHP_CHILD,XHP_AFTER_ENT,XHP_ATTR_VAL>{
  554. /* xml entities */
  555. (?-i:&quot;) tokt("\"");
  556. (?-i:&amp;) tokt("&");
  557. (?-i:&apos;) tokt("\\'");
  558. (?-i:&lt;) tokt("<")
  559. (?-i:&gt;) tokt(">");
  560. /* html entities */
  561. (?-i:&nbsp;) tokt("\u00A0");
  562. (?-i:&iexcl;) tokt("\u00A1");
  563. (?-i:&cent;) tokt("\u00A2");
  564. (?-i:&pound;) tokt("\u00A3");
  565. (?-i:&curren;) tokt("\u00A4");
  566. (?-i:&yen;) tokt("\u00A5");
  567. (?-i:&brvbar;) tokt("\u00A6");
  568. (?-i:&sect;) tokt("\u00A7");
  569. (?-i:&uml;) tokt("\u00A8");
  570. (?-i:&copy;) tokt("\u00A9");
  571. (?-i:&ordf;) tokt("\u00AA");
  572. (?-i:&laquo;) tokt("\u00AB");
  573. (?-i:&not;) tokt("\u00AC");
  574. (?-i:&shy;) tokt("\u00AD");
  575. (?-i:&reg;) tokt("\u00AE");
  576. (?-i:&macr;) tokt("\u00AF");
  577. (?-i:&deg;) tokt("\u00B0");
  578. (?-i:&plusmn;) tokt("\u00B1");
  579. (?-i:&sup2;) tokt("\u00B2");
  580. (?-i:&sup3;) tokt("\u00B3");
  581. (?-i:&acute;) tokt("\u00B4");
  582. (?-i:&micro;) tokt("\u00B5");
  583. (?-i:&para;) tokt("\u00B6");
  584. (?-i:&middot;) tokt("\u00B7");
  585. (?-i:&cedil;) tokt("\u00B8");
  586. (?-i:&sup1;) tokt("\u00B9");
  587. (?-i:&ordm;) tokt("\u00BA");
  588. (?-i:&raquo;) tokt("\u00BB");
  589. (?-i:&frac14;) tokt("\u00BC");
  590. (?-i:&frac12;) tokt("\u00BD");
  591. (?-i:&frac34;) tokt("\u00BE");
  592. (?-i:&iquest;) tokt("\u00BF");
  593. (?-i:&Agrave;) tokt("\u00C0");
  594. (?-i:&Aacute;) tokt("\u00C1");
  595. (?-i:&Acirc;) tokt("\u00C2");
  596. (?-i:&Atilde;) tokt("\u00C3");
  597. (?-i:&Auml;) tokt("\u00C4");
  598. (?-i:&Aring;) tokt("\u00C5");
  599. (?-i:&AElig;) tokt("\u00C6");
  600. (?-i:&Ccedil;) tokt("\u00C7");
  601. (?-i:&Egrave;) tokt("\u00C8");
  602. (?-i:&Eacute;) tokt("\u00C9");
  603. (?-i:&Ecirc;) tokt("\u00CA");
  604. (?-i:&Euml;) tokt("\u00CB");
  605. (?-i:&Igrave;) tokt("\u00CC");
  606. (?-i:&Iacute;) tokt("\u00CD");
  607. (?-i:&Icirc;) tokt("\u00CE");
  608. (?-i:&Iuml;) tokt("\u00CF");
  609. (?-i:&ETH;) tokt("\u00D0");
  610. (?-i:&Ntilde;) tokt("\u00D1");
  611. (?-i:&Ograve;) tokt("\u00D2");
  612. (?-i:&Oacute;) tokt("\u00D3");
  613. (?-i:&Ocirc;) tokt("\u00D4");
  614. (?-i:&Otilde;) tokt("\u00D5");
  615. (?-i:&Ouml;) tokt("\u00D6");
  616. (?-i:&times;) tokt("\u00D7");
  617. (?-i:&Oslash;) tokt("\u00D8");
  618. (?-i:&Ugrave;) tokt("\u00D9");
  619. (?-i:&Uacute;) tokt("\u00DA");
  620. (?-i:&Ucirc;) tokt("\u00DB");
  621. (?-i:&Uuml;) tokt("\u00DC");
  622. (?-i:&Yacute;) tokt("\u00DD");
  623. (?-i:&THORN;) tokt("\u00DE");
  624. (?-i:&szlig;) tokt("\u00DF");
  625. (?-i:&agrave;) tokt("\u00E0");
  626. (?-i:&aacute;) tokt("\u00E1");
  627. (?-i:&acirc;) tokt("\u00E2");
  628. (?-i:&atilde;) tokt("\u00E3");
  629. (?-i:&auml;) tokt("\u00E4");
  630. (?-i:&aring;) tokt("\u00E5");
  631. (?-i:&aelig;) tokt("\u00E6");
  632. (?-i:&ccedil;) tokt("\u00E7");
  633. (?-i:&egrave;) tokt("\u00E8");
  634. (?-i:&eacute;) tokt("\u00E9");
  635. (?-i:&ecirc;) tokt("\u00EA");
  636. (?-i:&euml;) tokt("\u00EB");
  637. (?-i:&igrave;) tokt("\u00EC");
  638. (?-i:&iacute;) tokt("\u00ED");
  639. (?-i:&icirc;) tokt("\u00EE");
  640. (?-i:&iuml;) tokt("\u00EF");
  641. (?-i:&eth;) tokt("\u00F0");
  642. (?-i:&ntilde;) tokt("\u00F1");
  643. (?-i:&ograve;) tokt("\u00F2");
  644. (?-i:&oacute;) tokt("\u00F3");
  645. (?-i:&ocirc;) tokt("\u00F4");
  646. (?-i:&otilde;) tokt("\u00F5");
  647. (?-i:&ouml;) tokt("\u00F6");
  648. (?-i:&divide;) tokt("\u00F7");
  649. (?-i:&oslash;) tokt("\u00F8");
  650. (?-i:&ugrave;) tokt("\u00F9");
  651. (?-i:&uacute;) tokt("\u00FA");
  652. (?-i:&ucirc;) tokt("\u00FB");
  653. (?-i:&uuml;) tokt("\u00FC");
  654. (?-i:&yacute;) tokt("\u00FD");
  655. (?-i:&thorn;) tokt("\u00FE");
  656. (?-i:&yuml;) tokt("\u00FF");
  657. (?-i:&OElig;) tokt("\u0152");
  658. (?-i:&oelig;) tokt("\u0153");
  659. (?-i:&Scaron;) tokt("\u0160");
  660. (?-i:&scaron;) tokt("\u0161");
  661. (?-i:&Yuml;) tokt("\u0178");
  662. (?-i:&fnof;) tokt("\u0192");
  663. (?-i:&circ;) tokt("\u02C6");
  664. (?-i:&tilde;) tokt("\u02DC");
  665. (?-i:&Alpha;) tokt("\u0391");
  666. (?-i:&Beta;) tokt("\u0392");
  667. (?-i:&Gamma;) tokt("\u0393");
  668. (?-i:&Delta;) tokt("\u0394");
  669. (?-i:&Epsilon;) tokt("\u0395");
  670. (?-i:&Zeta;) tokt("\u0396");
  671. (?-i:&Eta;) tokt("\u0397");
  672. (?-i:&Theta;) tokt("\u0398");
  673. (?-i:&Iota;) tokt("\u0399");
  674. (?-i:&Kappa;) tokt("\u039A");
  675. (?-i:&Lambda;) tokt("\u039B");
  676. (?-i:&Mu;) tokt("\u039C");
  677. (?-i:&Nu;) tokt("\u039D");
  678. (?-i:&Xi;) tokt("\u039E");
  679. (?-i:&Omicron;) tokt("\u039F");
  680. (?-i:&Pi;) tokt("\u03A0");
  681. (?-i:&Rho;) tokt("\u03A1");
  682. (?-i:&Sigma;) tokt("\u03A3");
  683. (?-i:&Tau;) tokt("\u03A4");
  684. (?-i:&Upsilon;) tokt("\u03A5");
  685. (?-i:&Phi;) tokt("\u03A6");
  686. (?-i:&Chi;) tokt("\u03A7");
  687. (?-i:&Psi;) tokt("\u03A8");
  688. (?-i:&Omega;) tokt("\u03A9");
  689. (?-i:&alpha;) tokt("\u03B1");
  690. (?-i:&beta;) tokt("\u03B2");
  691. (?-i:&gamma;) tokt("\u03B3");
  692. (?-i:&delta;) tokt("\u03B4");
  693. (?-i:&epsilon;) tokt("\u03B5");
  694. (?-i:&zeta;) tokt("\u03B6");
  695. (?-i:&eta;) tokt("\u03B7");
  696. (?-i:&theta;) tokt("\u03B8");
  697. (?-i:&iota;) tokt("\u03B9");
  698. (?-i:&kappa;) tokt("\u03BA");
  699. (?-i:&lambda;) tokt("\u03BB");
  700. (?-i:&mu;) tokt("\u03BC");
  701. (?-i:&nu;) tokt("\u03BD");
  702. (?-i:&xi;) tokt("\u03BE");
  703. (?-i:&omicron;) tokt("\u03BF");
  704. (?-i:&pi;) tokt("\u03C0");
  705. (?-i:&rho;) tokt("\u03C1");
  706. (?-i:&sigmaf;) tokt("\u03C2");
  707. (?-i:&sigma;) tokt("\u03C3");
  708. (?-i:&tau;) tokt("\u03C4");
  709. (?-i:&upsilon;) tokt("\u03C5");
  710. (?-i:&phi;) tokt("\u03C6");
  711. (?-i:&chi;) tokt("\u03C7");
  712. (?-i:&psi;) tokt("\u03C8");
  713. (?-i:&omega;) tokt("\u03C9");
  714. (?-i:&thetasym;) tokt("\u03D1");
  715. (?-i:&upsih;) tokt("\u03D2");
  716. (?-i:&piv;) tokt("\u03D6");
  717. (?-i:&ensp;) tokt("\u2002");
  718. (?-i:&emsp;) tokt("\u2003");
  719. (?-i:&thinsp;) tokt("\u2009");
  720. (?-i:&zwnj;) tokt("\u200C");
  721. (?-i:&zwj;) tokt("\u200D");
  722. (?-i:&lrm;) tokt("\u200E");
  723. (?-i:&rlm;) tokt("\u200F");
  724. (?-i:&ndash;) tokt("\u2013");
  725. (?-i:&mdash;) tokt("\u2014");
  726. (?-i:&lsquo;) tokt("\u2018");
  727. (?-i:&rsquo;) tokt("\u2019");
  728. (?-i:&sbquo;) tokt("\u201A");
  729. (?-i:&ldquo;) tokt("\u201C");
  730. (?-i:&rdquo;) tokt("\u201D");
  731. (?-i:&bdquo;) tokt("\u201E");
  732. (?-i:&dagger;) tokt("\u2020");
  733. (?-i:&Dagger;) tokt("\u2021");
  734. (?-i:&bull;) tokt("\u2022");
  735. (?-i:&hellip;) tokt("\u2026");
  736. (?-i:&permil;) tokt("\u2030");
  737. (?-i:&prime;) tokt("\u2032");
  738. (?-i:&Prime;) tokt("\u2033");
  739. (?-i:&lsaquo;) tokt("\u2039");
  740. (?-i:&rsaquo;) tokt("\u203A");
  741. (?-i:&oline;) tokt("\u203E");
  742. (?-i:&frasl;) tokt("\u2044");
  743. (?-i:&euro;) tokt("\u20AC");
  744. (?-i:&image;) tokt("\u2111");
  745. (?-i:&weierp;) tokt("\u2118");
  746. (?-i:&real;) tokt("\u211C");
  747. (?-i:&trade;) tokt("\u2122");
  748. (?-i:&alefsym;) tokt("\u2135");
  749. (?-i:&larr;) tokt("\u2190");
  750. (?-i:&uarr;) tokt("\u2191");
  751. (?-i:&rarr;) tokt("\u2192");
  752. (?-i:&darr;) tokt("\u2193");
  753. (?-i:&harr;) tokt("\u2194");
  754. (?-i:&crarr;) tokt("\u21B5");
  755. (?-i:&lArr;) tokt("\u21D0");
  756. (?-i:&uArr;) tokt("\u21D1");
  757. (?-i:&rArr;) tokt("\u21D2");
  758. (?-i:&dArr;) tokt("\u21D3");
  759. (?-i:&hArr;) tokt("\u21D4");
  760. (?-i:&forall;) tokt("\u2200");
  761. (?-i:&part;) tokt("\u2202");
  762. (?-i:&exist;) tokt("\u2203");
  763. (?-i:&empty;) tokt("\u2205");
  764. (?-i:&nabla;) tokt("\u2207");
  765. (?-i:&isin;) tokt("\u2208");
  766. (?-i:&notin;) tokt("\u2209");
  767. (?-i:&ni;) tokt("\u220B");
  768. (?-i:&prod;) tokt("\u220F");
  769. (?-i:&sum;) tokt("\u2211");
  770. (?-i:&minus;) tokt("\u2212");
  771. (?-i:&lowast;) tokt("\u2217");
  772. (?-i:&radic;) tokt("\u221A");
  773. (?-i:&prop;) tokt("\u221D");
  774. (?-i:&infin;) tokt("\u221E");
  775. (?-i:&ang;) tokt("\u2220");
  776. (?-i:&and;) tokt("\u2227");
  777. (?-i:&or;) tokt("\u2228");
  778. (?-i:&cap;) tokt("\u2229");
  779. (?-i:&cup;) tokt("\u222A");
  780. (?-i:&int;) tokt("\u222B");
  781. (?-i:&there4;) tokt("\u2234");
  782. (?-i:&sim;) tokt("\u223C");
  783. (?-i:&cong;) tokt("\u2245");
  784. (?-i:&asymp;) tokt("\u2248");
  785. (?-i:&ne;) tokt("\u2260");
  786. (?-i:&equiv;) tokt("\u2261");
  787. (?-i:&le;) tokt("\u2264");
  788. (?-i:&ge;) tokt("\u2265");
  789. (?-i:&sub;) tokt("\u2282");
  790. (?-i:&sup;) tokt("\u2283");
  791. (?-i:&nsub;) tokt("\u2284");
  792. (?-i:&sube;) tokt("\u2286");
  793. (?-i:&supe;) tokt("\u2287");
  794. (?-i:&oplus;) tokt("\u2295");
  795. (?-i:&otimes;) tokt("\u2297");
  796. (?-i:&perp;) tokt("\u22A5");
  797. (?-i:&sdot;) tokt("\u22C5");
  798. (?-i:&lceil;) tokt("\u2308");
  799. (?-i:&rceil;) tokt("\u2309");
  800. (?-i:&lfloor;) tokt("\u230A");
  801. (?-i:&rfloor;) tokt("\u230B");
  802. (?-i:&lang;) tokt("\u2329");
  803. (?-i:&rang;) tokt("\u232A");
  804. (?-i:&loz;) tokt("\u25CA");
  805. (?-i:&spades;) tokt("\u2660");
  806. (?-i:&clubs;) tokt("\u2663");
  807. (?-i:&hearts;) tokt("\u2665");
  808. (?-i:&diams;) tokt("\u2666");
  809. /* awesome entities */
  810. (?-i:&cloud;) tokt("\u2601");
  811. (?-i:&umbrella;) tokt("\u2602");
  812. (?-i:&snowman;) tokt("\u2603");
  813. (?-i:&snowflake;) tokt("\u2745");
  814. (?-i:&comet;) tokt("\u2604");
  815. (?-i:&thunderstorm;) tokt("\u2608");
  816. /* pseudo entities */
  817. ' tokt("\\'");
  818. "\\" tokt("\\\\");
  819. /* meta entities */
  820. (?-i:&#[0-9]+;) {
  821. char buf[5];
  822. utf8ize(atoi(yytext + 2), buf);
  823. tokt(buf);
  824. }
  825. (?-i:&#x)[A-F0-9]+; {
  826. char buf[5];
  827. char *_;
  828. utf8ize(strtol(yytext + 3, &_, 16), buf);
  829. tokt(buf);
  830. }
  831. /* not entities */
  832. & {
  833. yymore();
  834. BEGIN(XHP_INVALID_ENTITY);
  835. }
  836. }
  837. <XHP_INVALID_ENTITY>{
  838. {BYTE}{1,10} {
  839. for (char* ii = yytext; *ii; ++ii) {
  840. if (*ii == ';') {
  841. ii[1] = 0;
  842. break;
  843. }
  844. }
  845. if (!yyextra->terminated) {
  846. yyextra->error = string("Invalid entity: (") + yytext + ")";
  847. yyextra->terminated = true;
  848. }
  849. }
  850. }
  851. <XHP_AFTER_ENT>{
  852. [ \t\x0b\x0c\xa0\r\n]|\r\n {
  853. if (*yytext == '\r' || *yytext == '\n') {
  854. // Since we rewrite newlines into space we need to increment both line
  855. // counters. The first_lineno increment is quite a hack, and makes it so
  856. // that this ent is on the wrong line but it doesn't mess up the rest of
  857. // the file.
  858. ++yyextra->lineno;
  859. ++yyextra->first_lineno;
  860. }
  861. pop_state();
  862. yytext[0] = ' ';
  863. yytext[1] = 0;
  864. tok(T_XHP_TEXT);
  865. }
  866. . {
  867. pop_state();
  868. yyless(0);
  869. }
  870. }
  871. <XHP_CHILD>{
  872. [^&'<>\\{ \t\x0b\x0c\xa0\r\n]+{WHITESPACE}? {
  873. yy_scan_newlines(yytext, yyg);
  874. // Crunch white space at the end
  875. char* ii = yytext + yyleng - 1;
  876. while (*ii == ' ' || *ii == '\t' || *ii == '\n' || *ii == '\r') {
  877. --ii;
  878. }
  879. if (ii != yytext + yyleng - 1) {
  880. ii[1] = ' ';
  881. ii[2] = 0;
  882. }
  883. tok(T_XHP_TEXT);
  884. }
  885. {WHITESPACE}* {
  886. yy_scan_newlines(yytext, yyg);
  887. yytext[0] = ' ';
  888. yytext[1] = 0;
  889. tok(T_XHP_TEXT);
  890. }
  891. {WHITESPACE}*"{" {
  892. yy_scan_newlines(yytext, yyg);
  893. tok('{');
  894. }
  895. {WHITESPACE}*"<" {
  896. yy_scan_newlines(yytext, yyg);
  897. tok('<');
  898. }
  899. {WHITESPACE}*"</" {
  900. yy_scan_newlines(yytext, yyg);
  901. tok(T_XHP_LT_DIV);
  902. }
  903. {WHITESPACE}*"</>" {
  904. yy_scan_newlines(yytext, yyg);
  905. tok(T_XHP_LT_DIV_GT);
  906. }
  907. }
  908. <XHP_CHILDREN_DECL>{
  909. any tok(T_XHP_ANY);
  910. pcdata tok(T_XHP_PCDATA);
  911. empty tok(T_XHP_EMPTY);
  912. {LABEL} tok(T_STRING);
  913. ";" {
  914. pop_state();
  915. tok(';');
  916. }
  917. ":" {
  918. tok(T_XHP_COLON);
  919. }
  920. }
  921. /* Other */
  922. <*>{BYTE} {
  923. tok(yytext[0]);
  924. // fix unused function warnings
  925. yy_top_state(NULL);
  926. yyunput(0, 0, NULL);
  927. }
  928. %%
  929. #ifdef DEBUG
  930. static const char* yy_state_name(int state) {
  931. switch (state) {
  932. case INITIAL:
  933. return "INITIAL";
  934. case PHP:
  935. return "PHP";
  936. case PHP_COMMENT:
  937. return "PHP_COMMENT";
  938. case PHP_EOL_COMMENT:
  939. return "PHP_EOL_COMMENT";
  940. case PHP_DOC_COMMENT:
  941. return "PHP_DOC_COMMENT";
  942. case PHP_HEREDOC_START:
  943. return "PHP_HEREDOC_START";
  944. case PHP_HEREDOC_NSTART:
  945. return "PHP_HEREDOC_NSTART";
  946. case PHP_HEREDOC_NEWLINE:
  947. return "PHP_HEREDOC_NEWLINE";
  948. case PHP_HEREDOC_DATA:
  949. return "PHP_HEREDOC_DATA";
  950. case PHP_NO_RESERVED_WORDS:
  951. return "PHP_NO_RESERVED_WORDS";
  952. case PHP_NO_RESERVED_WORDS_PERSIST:
  953. return "PHP_NO_RESERVED_WORDS_PERSIST";
  954. case XHP_LABEL:
  955. return "XHP_LABEL";
  956. case XHP_LABEL_WHITESPACE:
  957. return "XHP_LABEL_WHITESPACE";
  958. case XHP_ATTRS:
  959. return "XHP_ATTRS";
  960. case XHP_ATTR_VAL:
  961. return "XHP_ATTR_VAL";
  962. case XHP_AFTER_ENT:
  963. return "XHP_AFTER_ENT";
  964. case XHP_CHILD:
  965. return "XHP_CHILD";
  966. case XHP_CHILD_START:
  967. return "XHP_CHILD_START";
  968. case XHP_INVALID_ENTITY:
  969. return "XHP_INVALID_ENTITY";
  970. case XHP_ATTR_TYPE_DECL:
  971. return "XHP_ATTR_TYPE_DECL";
  972. case XHP_CHILDREN_DECL:
  973. return "XHP_CHILDREN_DECL";
  974. default:
  975. return "???";
  976. }
  977. }
  978. static void yy_log_token(int tok) {
  979. const char* tokname = yytokname(tok);
  980. if (tokname) {
  981. fprintf(stderr, "--> %s\n", tokname);
  982. } else {
  983. fprintf(stderr, "--> '%c'\n", tok);
  984. }
  985. }
  986. #endif
  987. static int yy_token(int tok, yyguts_t* yyg) {
  988. if (YY_START == PHP_NO_RESERVED_WORDS) {
  989. pop_state();
  990. }
  991. switch (tok) {
  992. case T_OPEN_TAG:
  993. case T_OPEN_TAG_WITH_ECHO:
  994. case T_OPEN_TAG_FAKE:
  995. push_state(PHP);
  996. break;
  997. case T_CLOSE_TAG:
  998. pop_state();
  999. return ';';
  1000. // In PHP it's ok to use keywords such as 'if' as field names
  1001. // or function names.
  1002. case T_OBJECT_OPERATOR:
  1003. case T_PAAMAYIM_NEKUDOTAYIM:
  1004. case T_FUNCTION:
  1005. push_state(PHP_NO_RESERVED_WORDS);
  1006. break;
  1007. case '{':
  1008. // not used anymore
  1009. yyextra->curly_stack.push(tok);
  1010. break;
  1011. }
  1012. #ifdef DEBUG
  1013. yy_log_token(tok);
  1014. #endif
  1015. return yyextra->last_token = tok;
  1016. }
  1017. static inline void yy_scan_newlines(const char* text, struct yyguts_t* yyg) {
  1018. for (; *text; ++text) {
  1019. if (*text == '\r') {
  1020. if (text[1] == '\n') {
  1021. ++text;
  1022. }
  1023. ++yyextra->lineno;
  1024. } else if (*text == '\n') {
  1025. ++yyextra->lineno;
  1026. }
  1027. }
  1028. }
  1029. void xhp_new_push_state(int s, struct yyguts_t* yyg) {
  1030. #ifdef DEBUG
  1031. fprintf(stderr, "--> PUSH(%s -> %s)\n", yy_state_name(YY_START), yy_state_name(s));
  1032. #endif
  1033. yy_push_state(s, yyg);
  1034. }
  1035. void xhp_new_pop_state(struct yyguts_t* yyg) {
  1036. #ifdef DEBUG
  1037. int s = YY_START;
  1038. #endif
  1039. yy_pop_state(yyg);
  1040. #ifdef DEBUG
  1041. fprintf(stderr, "--> POP(%s -> %s)\n", yy_state_name(s), yy_state_name(YY_START));
  1042. #endif
  1043. }
  1044. void xhp_set_state(int s, struct yyguts_t* yyg) {
  1045. #ifdef DEBUG
  1046. fprintf(stderr, "--> SET(%s)\n", yy_state_name(s));
  1047. #endif
  1048. BEGIN(s);
  1049. }