- Added missing copyright to meneame
[haanga.git] / lib / Haanga / Compiler / Lexer.lex
blob60de698d37221f871ee8bf56213e2549ba605dbe
1 <?php
2 /*
3   +---------------------------------------------------------------------------------+
4   | Copyright (c) 2010 César Rodas and Menéame Comunicacions S.L.                   |
5   +---------------------------------------------------------------------------------+
6   | Redistribution and use in source and binary forms, with or without              |
7   | modification, are permitted provided that the following conditions are met:     |
8   | 1. Redistributions of source code must retain the above copyright               |
9   |    notice, this list of conditions and the following disclaimer.                |
10   |                                                                                 |
11   | 2. Redistributions in binary form must reproduce the above copyright            |
12   |    notice, this list of conditions and the following disclaimer in the          |
13   |    documentation and/or other materials provided with the distribution.         |
14   |                                                                                 |
15   | 3. All advertising materials mentioning features or use of this software        |
16   |    must display the following acknowledgement:                                  |
17   |    This product includes software developed by César D. Rodas.                  |
18   |                                                                                 |
19   | 4. Neither the name of the César D. Rodas nor the                               |
20   |    names of its contributors may be used to endorse or promote products         |
21   |    derived from this software without specific prior written permission.        |
22   |                                                                                 |
23   | THIS SOFTWARE IS PROVIDED BY CÉSAR D. RODAS ''AS IS'' AND ANY                   |
24   | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED       |
25   | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE          |
26   | DISCLAIMED. IN NO EVENT SHALL CÉSAR D. RODAS BE LIABLE FOR ANY                  |
27   | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES      |
28   | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;    |
29   | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND     |
30   | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT      |
31   | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS   |
32   | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE                     |
33   +---------------------------------------------------------------------------------+
34   | Authors: César Rodas <crodas@php.net>                                           |
35   +---------------------------------------------------------------------------------+
38 class HG_Parser Extends Haanga_Compiler_Parser
40     /* subclass to made easier references to constants */
43 class Haanga_Compiler_Lexer
45     private $data;
46     private $N;
47     public $token;
48     public $value;
49     private $line;
50     private $state = 1;
52     function __construct($data, $compiler)
53     {
54         $this->data     = $data;
55         $this->compiler = $compiler;
56         $this->N        = 0;
57         $this->line     = 1;
58     }
60     static function init($template, $compiler)
61     {
62         $lexer  = new Haanga_Compiler_Lexer($template, $compiler);
63         $parser = new Haanga_Compiler_Parser($lexer);
65         $parser->compiler = $compiler;
67         try {
68             for($i=0; ; $i++) {
69                 if  (!$lexer->yylex()) {
70                     break;
71                 }
72                 $parser->doParse($lexer->token, $lexer->value);
73             }
74         } catch (Exception $e) {
75             throw new Haanga_Compiler_Exception($e->getMessage(). ' on line '.$lexer->getLine());
76         }
77         $parser->doParse(0, 0);
78         return (array)$parser->body;
79     }
81     function getLine()
82     {
83         return $this->line;
84     }
86     public $custom_tags=array();
88     function is_custom_tag()
89     {
90         static $tag=NULL;
91         if (!$tag) {
92             $tag = Haanga_Extension::getInstance('Tag');
93         }
94         $value = $tag->isValid($this->value);
95         $this->token = $value ? $value : HG_Parser::T_ALPHA;
96     }
98 /*!lex2php
99 %input          $this->data
100 %counter        $this->N
101 %token          $this->token
102 %value          $this->value
103 %line           $this->line
104 alpha           = /([a-zA-Z_][a-zA-Z_0-9]*)/
105 number          = /[0-9]/
106 numerals        = /([0-9])+/
107 whitespace      = /[ \r\t\n]+/
108 html            = /([^{]+(.[^%{#])?)+/
109 comment         = /([^\#]+\#\})+/
110 custom_tag_end  = /end([a-zA-Z][a-zA-Z0-9]*)/
111 token_end       = /[^a-zA-Z0-9_\.]/
112 single_string   = /[^'\\]+/
113 double_string   = /[^"\\]+/
115 /*!lex2php
116 %statename IN_HTML
117 "{%" {
118     $this->token = HG_Parser::T_OPEN_TAG;
119     $this->yypushstate(self::IN_CODE);
122 "{#" {
123     $this->token = HG_Parser::T_COMMENT_OPEN;
124     $this->yypushstate(self::IN_COMMENT);
128 "{{" {
129     $this->token = HG_Parser::T_PRINT_OPEN;
130     $this->yypushstate(self::IN_PRINT);
133 html {
134     $this->token = HG_Parser::T_HTML;
138 /*!lex2php
139 %statename IN_CODE
140 "%}" {
141     $this->token = HG_Parser::T_CLOSE_TAG;
142     $this->yypopstate();
145 "->" {
146     $this->token = HG_Parser::T_OBJ;
150 "." {
151     $this->token = HG_Parser::T_DOT;
154 "buffer" token_end {
155     $this->token = HG_Parser::T_BUFFER;
159 "for" token_end {
160     $this->token = HG_Parser::T_FOR;
163 "empty" token_end {
164     $this->token = HG_Parser::T_EMPTY;
167 "load" token_end {
168     $this->token = HG_Parser::T_LOAD;
171 "block" token_end {
172     $this->token = HG_Parser::T_BLOCK;
175 "&&" { 
176     $this->token = HG_Parser::T_AND;
179 "AND" token_end {
180     $this->token = HG_Parser::T_AND;
183 "||" {
184     $this->token = HG_Parser::T_OR;
187 "OR" token_end {
188     $this->token = HG_Parser::T_OR;
191 "==" {
192     $this->token = HG_Parser::T_EQ;
195 "!=" {
196     $this->token = HG_Parser::T_NE;
199 ">=" {
200     $this->token = HG_Parser::T_GE;
203 "not" token_end {
204     $this->token = HG_Parser::T_NOT;
206     
207 "!" token_end {
208     $this->token = HG_Parser::T_NOT;
210     
212 "[" {
213     $this->token = HG_Parser::T_BRACKETS_OPEN;
216 "]" {
217     $this->token = HG_Parser::T_BRACKETS_CLOSE;
220 ">" {
221     $this->token = HG_Parser::T_GT;
224 "<" {
225     $this->token = HG_Parser::T_LT;
227 "=<" {
228     $this->token = HG_Parser::T_LE;
231 "|" {
232     $this->token = HG_Parser::T_PIPE;
235 ":" {
236     $this->token = HG_Parser::T_COLON;
239 "filter" token_end {
240     $this->token = HG_Parser::T_FILTER;
243 "regroup" token_end {
244     $this->token = HG_Parser::T_REGROUP;
247 "endfilter" token_end {
248     $this->token = HG_Parser::T_END_FILTER;
251 "autoescape" token_end {
252     $this->token = HG_Parser::T_AUTOESCAPE;
255 "spacefull" token_end {
256     $this->token = HG_Parser::T_SPACEFULL;
260 "endautoescape" token_end {
261     $this->token = HG_Parser::T_END_AUTOESCAPE;
265 "endblock" token_end {
266     $this->token = HG_Parser::T_END_BLOCK;
269 "ifchanged" token_end {
270     $this->token = HG_Parser::T_IFCHANGED;
273 "ifequal" token_end {
274     $this->token = HG_Parser::T_IFEQUAL;
277 "endifequal" token_end {
278     $this->token = HG_Parser::T_END_IFEQUAL;
281 "ifnotequal" token_end {
282     $this->token = HG_Parser::T_IFNOTEQUAL;
285 "endifnotequal" token_end {
286     $this->token = HG_Parser::T_END_IFNOTEQUAL;
290 "else" token_end {
291     $this->token = HG_Parser::T_ELSE;
294 "endifchanged" token_end {
295     $this->token = HG_Parser::T_ENDIFCHANGED;
299 "in" token_end {
300     $this->token = HG_Parser::T_IN;
303 "endfor" token_end {
304     $this->token = HG_Parser::T_CLOSEFOR;
307 "with" token_end {
308     $this->token = HG_Parser::T_WITH;
311 "endwith" token_end {
312     $this->token = HG_Parser::T_ENDWITH;
315 "as" {
316     $this->token = HG_Parser::T_AS;
319 "on" {
320     $this->token = HG_Parser::T_ON;
323 "off" {
324     $this->token = HG_Parser::T_OFF;
327 "by" {
328     $this->token = HG_Parser::T_BY;
331 "if" token_end {
332     $this->token = HG_Parser::T_IF;
335 "else" token_end {
336     $this->token = HG_Parser::T_ELSE;
339 "endif" token_end {
340     $this->token = HG_Parser::T_ENDIF;
343 "_("  {
344     $this->token = HG_Parser::T_INTL;
348 "(" {
349     $this->token = HG_Parser::T_LPARENT;
352 ")" {
353     $this->token = HG_Parser::T_RPARENT;
356 "%" {
357     $this->token = HG_Parser::T_MOD;
360 "," {
361     $this->token = HG_Parser::T_COMMA;
364 "+" {
365     $this->token = HG_Parser::T_PLUS;
367 "-" {
368     $this->token = HG_Parser::T_MINUS;
370 "*" {
371     $this->token = HG_Parser::T_TIMES;
374 "/" {
375     $this->token = HG_Parser::T_DIV;
378 "'" {
379     $this->token = HG_Parser::T_STRING_SINGLE_INIT;
380     $this->yypushstate(self::IN_STRING_SINGLE);
383 "\"" {
384     $this->token = HG_Parser::T_STRING_DOUBLE_INIT;
385     $this->yypushstate(self::IN_STRING_DOUBLE);
388 custom_tag_end {
389     $this->token = HG_Parser::T_CUSTOM_END;
392 "extends" token_end {
393     $this->token = HG_Parser::T_EXTENDS;
396 "include" token_end {
397     $this->token = HG_Parser::T_INCLUDE;
400 numerals {
401     $this->token = HG_Parser::T_NUMERIC;
404 numerals "."  numerals {
405     $this->token = HG_Parser::T_NUMERIC;
408 alpha  {
409     $this->is_custom_tag();
412 whitespace {
413     return FALSE;
417 /*!lex2php
418 %statename IN_PRINT
419 "}}" {
420     $this->token = HG_Parser::T_PRINT_CLOSE;
421     $this->yypopstate();
424 "|" {
425     $this->token = HG_Parser::T_PIPE;
428 ":" {
429     $this->token = HG_Parser::T_COLON;
432 "->" {
433     $this->token = HG_Parser::T_OBJ;
437 "." {
438     $this->token = HG_Parser::T_DOT;
441 "[" {
442     $this->token = HG_Parser::T_BRACKETS_OPEN;
445 "]" {
446     $this->token = HG_Parser::T_BRACKETS_CLOSE;
449 numerals {
450     $this->token = HG_Parser::T_NUMERIC;
453 numerals "."  numerals {
454     $this->token = HG_Parser::T_NUMERIC;
457 "'" {
458     $this->token = HG_Parser::T_STRING_SINGLE_INIT;
459     $this->yypushstate(self::IN_STRING_SINGLE);
462 "\"" {
463     $this->token = HG_Parser::T_STRING_DOUBLE_INIT;
464     $this->yypushstate(self::IN_STRING_DOUBLE);
467 alpha {
468     $this->token = HG_Parser::T_ALPHA;
471 whitespace {
472     return FALSE;
476 /*!lex2php
477 %statename IN_STRING_DOUBLE
479 "\\" "\""  {
480     $this->token = HG_Parser::T_STRING_CONTENT;
481     $this->value = "\"";
482     $this->N    += 1;
485 "\'"  {
486     $this->token = HG_Parser::T_STRING_CONTENT;
487     $this->value = "'";
488     $this->N    += 1;
492 "\"" {
493     $this->token = HG_Parser::T_STRING_DOUBLE_END;
494     $this->yypopstate();
497 double_string {
498     $this->token = HG_Parser::T_STRING_CONTENT;
503 /*!lex2php
504 %statename IN_STRING_SINGLE
505 "\'"  {
506     $this->token = HG_Parser::T_STRING_CONTENT;
507     $this->value = "'";
508     $this->N    += 1;
511 "\\" "\""  {
512     $this->token = HG_Parser::T_STRING_CONTENT;
513     $this->value = "\"";
514     $this->N    += 1;
518 "'" {
519     $this->token = HG_Parser::T_STRING_SINGLE_END;
520     $this->yypopstate();
523 single_string {
524     $this->token = HG_Parser::T_STRING_CONTENT;
529 /*!lex2php
530 %statename IN_COMMENT
531 comment {
532     $this->token = HG_Parser::T_COMMENT;
533     $this->yypopstate();