
000001| {

000002|

000003| (**

000004| This program is free software; you can redistribute it and / or modify

000005| it under the terms of the GNU General Public License as published by

000006| the Free Software Foundation; version 3 of the License.

000007|

000008| This program is distributed in the hope that it will be useful,

000009| but WITHOUT ANY WARRANTY; without even the implied warranty of

000010| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

000011| GNU General Public License for more details.

000012|

000013| Jtemplate lexer

000014|

000015| @author Tony BenBrahim < tony.benbrahim at gmail.com >

000016|

000017| *)

000018|

000019| open RuntimeError

000020| open Parser

000021| open Ast

000022|

000023| (* from http://plus.kaist.ac.kr/~shoh/ocaml/ocamllex-ocamlyacc/ocamllex-tutorial.pdf , p.9 *)

000024| let incr_linenum lexbuf =

000025| let pos = lexbuf.Lexin(*[3024]*)g.lex_curr_p in

000026| lexbuf.Lexing.lex_curr(*[3024]*)_p <- { pos with

000027| Lexing.pos_lnum = pos.Lexing.pos_lnum + 1;

000028| Lexing.pos_bol = pos.Lexing.pos_cnum;

000029| }

000030|

000031| let syntax_exception msg lexbuf=

000033| lexbuf.Lexing.lex_curr_p.Lexing.pos_cnum - lexbuf.Lexing.lex_curr_p.Lexing.pos_bol))

000034|

000035| let map_id name=

000036| match name with

000037| "foreach" -> FOREACH

000038| | "in" ->(*[22]*) IN

000039| | "while" -> W(*[22]*)HILE

000040| | "function(*[14]*)" -> FUNCTION

000041| | "if" -(*[346]*)> IF

000042| | "else" -> EL(*[36]*)SE

000043| | "template"(*[14]*) -> TEMPLATE

000044| | "instr(*[4]*)uctions" ->INSTRUCTIONS

000045| | "c(*[2]*)ontinue" -> CONTINUE

000046| | "break(*[8]*)" -> BREAK

000047| | "return" (*[16]*)-> RETURN

000048| | "for" ->(*[440]*) FOR

000049| | "once" -> O(*[24]*)NCE

000059| | "case" -(*[14]*)> CASE

000060| | "default" (*[30]*)-> DEFAULT

000061| | "try" -(*[14]*)> TRY

000062| | "catch" -> (*[106]*)CATCH

000063| | "finally"(*[98]*) -> FINALLY

000064| | "throw"(*[8]*) -> THROW

000065| | _ -> ID((*[12]*)name)

000066| }

000067| (*[2742]*)

000068| let digit = ['0'-'9']

000069| let id = ['a'-'z' 'A'-'Z' '_' '$']['A'-'Z' 'a'-'z' '0'-'9' '_' '$' ]*

000070| let whitespace = ['\r' '\t' ' ']

000071| let text = '#'[^'\n']*

000072| let float = (( (['0'-'9']+'.'['0'-'9']*) | (['0'-'9']*'.'['0'-'9']+) ) ('e'['+' '-']?['0'-'9']+)? ) | (['0'-'9']+ ('e'['+' '-']?['0'-'9']+))

000073|

000074| rule main = parse

000075| | whitespace { main lexbuf }

000076| | text as token { TEXT(String.sub token 1 ((String.length token) - 1))}

000077| | digit+ as token { try INT( int_of_string token) with _ -> OUTOFRANGENUMBER }

000078| | float as token { try REAL(float_of_string token) with _ -> OUTOFRANGENUMBER }

000079| | id as token { (map_id token )}

000080| | '\'' { single_quote_string "" lexbuf }

000081| | '"' { double_quote_string "" lexbuf }

000082| | "//" [^'\n']* { main lexbuf}

000083| | "/*" {multiline_comment lexbuf}

000084| | '\n' { incr_linenum lexbuf;main lexbuf }

000085| | "&&" {AND}

000086| | "||" {OR}

000087| | "<" {COMPOP(LessThan)}

000088| | ">" {COMPOP(GreaterThan)}

000089| | "<=" {COMPOP(LessThanEqual)}

000090| | ">=" {COMPOP(GreaterThanEqual)}

000091| | "==" {COMPOP(Equal)}

000092| | "!=" {COMPOP(NotEqual)}

000093| | "..." {DOTDOTDOT}

000094| | "+=" {PLUSEQUALS}

000095| | "-=" {MINUSEQUALS}

000096| | "*=" {TIMESEQUALS}

000097| | "/=" {DIVEQUALS}

000098| | "%=" {MODEQUALS}

000099| | "++" {PLUSPLUS}

000100| | "--" {MINUSMINUS}

000101| | '=' {EQUALS}

000102| | '.' {DOT}

000103| | '{' {LBRACE}

000104| | '}' {RBRACE}

000105| | '(' {LPAREN}

000106| | ')' {RPAREN}

000107| | '[' {LBRACKET}

000108| | ']' {RBRACKET}

000109| | ',' {COMMA}

000110| | ';' {SEMICOLON}

000111| | ':' {COLON}

000112| | '!' {NOT}

000113| | '?' {QUESTION}

000114| | '+' {PLUS}

000115| | '-' {MINUS}

000116| | '*' {TIMES}

000117| | '/' {DIVIDE}

000118| | '%' {MODULO}

000119| | '@' {AT}

000120| | _ as c { syntax_exception ("Invalid character "^String.make 1 c) lexbuf}

000121| | eof { EOF }

000122| and single_quote_string s = parse

000123| | '\n' { incr_linenum lexbuf; single_quote_string (s ^ "\n") lexbuf }

000124| | '\'' { STRING(s) }

000125| | '\\' { single_quote_string (s ^ (escape_char lexbuf)) lexbuf }

000126| | [^ '\''] as c { single_quote_string (s ^ String.make 1 c) lexbuf }

000127| | eof { syntax_exception "Unterminated string constant" lexbuf }

000128| and double_quote_string s = parse

000129| | '\n' { incr_linenum lexbuf; double_quote_string (s ^ "\n") lexbuf }

000130| | '"' { STRING(s) }

000131| | '\\' { double_quote_string (s ^ (escape_char lexbuf)) lexbuf }

000132| | [^ '"'] as c { double_quote_string (s ^ String.make 1 c) lexbuf }

000133| | eof { syntax_exception "Unterminated string constant" lexbuf }

000134| and escape_char =parse

000135| | '\\' {"\\"}

000136| | 'n' {"\n"}

000137| | 'r' {"\r"}

000138| | '\'' {"'"}

000139| | '"' {"\""}

000140| | 't' {"\t"}

000141| | 'b' {"\b"}

000142| and multiline_comment = parse

000143| | '\n' { incr_linenum lexbuf; multiline_comment lexbuf }

000144| | "*/" { main lexbuf }

000145| | [^ '\n'] { multiline_comment lexbuf}

000146| | eof { syntax_exception "Unterminated multiline comment" lexbuf }