123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187(* 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=Lexing.lexbufletof_filefile:t=letic=open_infileinletlexbuf=Lexing.from_channelicin{lexbufwithlex_curr_p={lexbuf.lex_curr_pwithpos_fname=file}}letof_channelci:t=Lexing.from_channelciletof_lexbuflexbuf:t=lexbufendexceptionParsing_errorofParse_info.tletparse_auxthe_parserlexbuf=letinit=the_parserlexbuf.Lexing.lex_start_pinletresetlexbuf=lexbuf.Lexing.lex_curr_p<-lexbuf.Lexing.lex_start_p;lexbuf.Lexing.lex_curr_pos<-lexbuf.Lexing.lex_start_posinletfolprev(tok:Js_token.t)=matchprevwith|[]->true|p::_->(Js_token.infop).Parse_info.line<>(Js_token.infotok).Parse_info.lineinletrecloop_errorprevcheckpoint=letmoduleI=Js_parser.MenhirInterpreterinmatchcheckpointwith|I.InputNeeded_env->letcheckpoint=I.offercheckpoint(Js_token.EOFParse_info.zero,lexbuf.Lexing.lex_curr_p,lexbuf.Lexing.lex_curr_p)inloop_errorprevcheckpoint|I.Shifting_|I.AboutToReduce_->loop_errorprev(I.resumecheckpoint)|I.Accepted_->assertfalse|I.Rejected->`Errorprev|I.HandlingError_->loop_errorprev(I.resumecheckpoint)inletrecloopprevcomments(last_checkpoint,checkpoint)=letmoduleI=Js_parser.MenhirInterpreterinmatchcheckpointwith|I.InputNeeded_env->letinputneeded=checkpointinlettoken,comments=matchprevwith|(Js_token.EOF_asprev)::_->prev,comments|_->letrecread_onecommentslexbuf=matchJs_lexer.mainlexbufwith|(TCommentLineDirective_|TComment_)ast->read_one(t::comments)lexbuf|t->t,commentsinlett,comments=read_onecommentslexbufinlett=matchprev,twith(* 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_)ast))->t|(T_RETURN_|T_CONTINUE_|T_BREAK_|T_THROW_)::_,twhenfolprevt->resetlexbuf;T_VIRTUAL_SEMICOLONParse_info.zero(* The practical effect of these restricted productions is as follows:
* When a ++ or -- token is encountered where the parser would treat it
* as a postfix operator, and at least one LineTerminator occurred between
* the preceding token and the ++ or -- token, then a semicolon is automatically
* inserted before the ++ or -- token. *)|_,(T_DECRcpiastok)whennot(folprevtok)->Js_token.T_DECR_NBcpi|_,(T_INCRcpiastok)whennot(folprevtok)->Js_token.T_INCR_NBcpi|_,((T_DIV_|T_DIV_ASSIGN_)astok)->ifI.acceptablecheckpointtoklexbuf.Lexing.lex_start_pthentokelse(resetlexbuf;Js_lexer.main_regexplexbuf)|_,t->tint,commentsinletlast_checkpoint=prev,comments,inputneededinletcheckpoint=I.offercheckpoint(token,lexbuf.Lexing.lex_start_p,lexbuf.Lexing.lex_curr_p)inloop(token::prev)comments(last_checkpoint,checkpoint)|I.Shifting_|I.AboutToReduce_->loopprevcomments(last_checkpoint,I.resumecheckpoint)|I.Acceptedv->`Ok(v,prev,comments)|I.Rejected->`Errorprev|I.HandlingError_->((* 7.9.1 - 1 *)(* When, as the program is parsed from left to right, a token (called the offending token)
is encountered that is not allowed by any production of the grammar, then a semicolon
is automatically inserted before the offending token if one or more of the following
conditions is true:
- The offending token is }.
- The offending token is separated from the previous
token by at least one LineTerminator. *)(* 7.9.1 - 2 *)(* When, as the program is parsed from left to right, the end of the input stream of tokens *)(* is encountered and the parser is unable to parse the input token stream as a single *)(* complete ECMAScript Program, then a semicolon is automatically inserted at the end *)letinsert_virtual_semmit=matchprevwith|[]|T_VIRTUAL_SEMICOLON_::_->false|T_RCURLY_::_->true|EOF_::_->true|offending::before::_whenfol[before]offending->true|_->falseinmatchinsert_virtual_semmitwith|false->loop_errorprev(I.resumecheckpoint)|true->leterror_checkpoint=checkpointinleterror_prev=previnletprev,comments,checkpoint=last_checkpointinifI.acceptablecheckpoint(Js_token.T_VIRTUAL_SEMICOLONParse_info.zero)lexbuf.Lexing.lex_curr_pthen(resetlexbuf;lett=Js_token.T_VIRTUAL_SEMICOLONParse_info.zeroinletcheckpoint=I.offercheckpoint(t,lexbuf.Lexing.lex_curr_p,lexbuf.Lexing.lex_curr_p)inloop(t::prev)comments(last_checkpoint,checkpoint))elseloop_errorerror_prev(I.resumeerror_checkpoint))inmatchloop[][](([],[],init),init)with|`Okx->x|`Errortok->lettok=matchtokwith|[]->Js_token.EOFParse_info.zero|x::_->xinletpi=Js_token.infotokinraise(Parsing_errorpi)letparse'lex=letp,t_rev,comment_rev=parse_auxJs_parser.Incremental.programlexinp,List.revt_rev,List.revcomment_revletparselex=letp,_,_=parse_auxJs_parser.Incremental.programlexinpletparse_exprlex=letexpr,_,_=parse_auxJs_parser.Incremental.standalone_expressionlexinexpr