123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133(* Js_of_ocaml compiler
* Copyright (C) 2013 Hugo Heuzard
*)(* Yoann Padioleau
*
* Copyright (C) 2010 Facebook
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation, with the
* special exception on linking described in file license.txt.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the file
* license.txt for more details.
*)open!StdlibmoduleLexer=structtypet=Js_token.tlistletrecuntil_non_commentacc=function|[]->acc,None|x::xs->ifJs_token.is_commentxthenuntil_non_comment(x::acc)xselseacc,Some(x,xs)letadjust_tokens?(keep_comment=true)l=matchuntil_non_comment[]lwith|acc,Nonewhenkeep_comment->List.revacc|_,None->[]|past,Some(first,rest)->letopenJs_tokeninletfprevxacc=matchprev,xwith(* restricted productions *)(* 7.9.1 - 3 *)(* When, as the program is parsed from left to right, a token is encountered *)(* that is allowed by some production of the grammar, but the production *)(* is a restricted production and the token would be the first token for a *)(* terminal or nonterminal immediately following the annotation [no LineTerminator here] *)(* within the restricted production (and therefore such a token is called a restricted token), *)(* and the restricted token is separated from the previous token by at least *)(* one LineTerminator, then a semicolon is automatically inserted before the *)(* restricted token. *)|((T_RETURN_|T_CONTINUE_|T_BREAK_|T_THROW_),(T_SEMICOLON_|T_VIRTUAL_SEMICOLON_))->x::acc|(T_RETURN_|T_CONTINUE_|T_BREAK_|T_THROW_),_->letx'=Js_token.infoxinletprev'=Js_token.infoprevinifprev'.Parse_info.line<>x'.Parse_info.linethenx::Js_token.T_VIRTUAL_SEMICOLONx'::accelsex::acc|_,_->x::accinletrecauxprevacc=function|[]->List.revacc|e::l->letnprev,nacc=ifJs_token.is_commentethenifkeep_commentthenprev,e::accelseprev,accelsee,fpreveaccinauxnprevnacclinletpast=ifkeep_commentthenpastelse[]inauxfirst(first::past)restletlexer_aux?(rm_comment=true)lexbuf=letreclooplexbufprevacc=lett=Js_lexer.mainprevlexbufinmatchtwith|Js_token.EOF_->List.revacc|_->letprev=ifJs_token.is_commenttthenprevelseSometinlooplexbufprev(t::acc)inlettoks=looplexbufNone[]in(* hack: adjust tokens *)adjust_tokens~keep_comment:(notrm_comment)toksletof_file?rm_commentfile:t=letic=open_infileinletlexbuf=Lexing.from_channelicinletlexbuf={lexbufwithlex_curr_p={lexbuf.lex_curr_pwithpos_fname=file}}inletlexer=lexer_aux?rm_commentlexbufinclose_inic;lexerletof_channel?rm_commentci:t=letlexbuf=Lexing.from_channelciinlexer_aux?rm_commentlexbufletof_lexbuf?rm_commentlexbuf:t=lexer_aux?rm_commentlexbufletfold~f~initl=List.fold_left~f~initlletof_listl=adjust_tokenslendexceptionParsing_errorofParse_info.tletparse_auxthe_parsertoks=letstate=ref(Js_token.TUnknown("",Parse_info.zero)::toks)inletlexer_fun_lb=match!statewith|[]->assertfalse|[last]->letinfo=Js_token.infolastinJs_token.EOFinfo|_prev::(curr::_asrest)->state:=rest;currinletlexbuf=Lexing.from_string""intrythe_parserlexer_funlexbufwithJs_parser.Error|Parsing.Parse_error->letpi=match!statewith|[]->assertfalse|top::_->Js_token.infotopinraise(Parsing_errorpi)letparselex=parse_auxJs_parser.programlexletparse_exprlex=parse_auxJs_parser.standalone_expressionlex