LCOV - code coverage report
Current view: top level - as2js/lib - parser_statement.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 381 381 100.0 %
Date: 2014-08-10 Functions: 20 20 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* parser_statement.cpp -- written by Alexis WILKE for Made to Order Software Corp. (c) 2005-2014 */
       2             : 
       3             : /*
       4             : 
       5             : Copyright (c) 2005-2014 Made to Order Software Corp.
       6             : 
       7             : http://snapwebsites.org/project/as2js
       8             : 
       9             : Permission is hereby granted, free of charge, to any
      10             : person obtaining a copy of this software and
      11             : associated documentation files (the "Software"), to
      12             : deal in the Software without restriction, including
      13             : without limitation the rights to use, copy, modify,
      14             : merge, publish, distribute, sublicense, and/or sell
      15             : copies of the Software, and to permit persons to whom
      16             : the Software is furnished to do so, subject to the
      17             : following conditions:
      18             : 
      19             : The above copyright notice and this permission notice
      20             : shall be included in all copies or substantial
      21             : portions of the Software.
      22             : 
      23             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
      24             : ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
      25             : LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
      26             : FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
      27             : EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
      28             : LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
      29             : WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      30             : ARISING FROM, OUT OF OR IN CONNECTION WITH THE
      31             : SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      32             : SOFTWARE.
      33             : 
      34             : */
      35             : 
      36             : #include    "as2js/parser.h"
      37             : #include    "as2js/message.h"
      38             : 
      39             : 
      40             : namespace as2js
      41             : {
      42             : 
      43             : 
      44             : /**********************************************************************/
      45             : /**********************************************************************/
      46             : /***  PARSER BLOCK  ***************************************************/
      47             : /**********************************************************************/
      48             : /**********************************************************************/
      49             : 
      50      344106 : void Parser::block(Node::pointer_t& node)
      51             : {
      52             :     // handle the emptiness right here
      53      344106 :     if(f_node->get_type() != Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
      54             :     {
      55      344106 :         directive_list(node);
      56             :     }
      57             : 
      58      344106 :     if(f_node->get_type() != Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
      59             :     {
      60        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
      61        8193 :         msg << "'}' expected to close a block.";
      62             :     }
      63             :     else
      64             :     {
      65             :         // skip the '}'
      66      335913 :         get_token();
      67             :     }
      68      344106 : }
      69             : 
      70             : 
      71      311334 : void Parser::forced_block(Node::pointer_t& node, Node::pointer_t statement)
      72             : {
      73             :     // if user turned on the forced block flag (bit 1 in extended statements)
      74             :     // then we much have the '{' and '}' for all sorts of blocks
      75             :     // (while, for, do, with, if, else)
      76             :     // in a way this is very similar to the try/catch/finally which
      77             :     // intrinsicly require the curvly brackets
      78      311334 :     if(f_options
      79      311334 :     && (f_options->get_option(Options::option_t::OPTION_EXTENDED_STATEMENTS) & 2) != 0)
      80             :     {
      81             :         // in this case we force users to use '{' and '}' for all blocks
      82      155648 :         if(f_node->get_type() == Node::node_t::NODE_OPEN_CURVLY_BRACKET)
      83             :         {
      84       49152 :             get_token();
      85             : 
      86             :             // although the extra directive list may look useless, it may
      87             :             // be very important if the user declared variables (because
      88             :             // we support proper variable definition on a per block basis)
      89       49152 :             node = f_lexer->get_new_node(Node::node_t::NODE_DIRECTIVE_LIST);
      90       49152 :             Node::pointer_t block_node;
      91       49152 :             block(block_node);
      92       49152 :             node->append_child(block_node);
      93             :         }
      94             :         else
      95             :         {
      96             :             {
      97      106496 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
      98      106496 :                 msg << "'{' expected to open the '" << statement->get_type_name() << "' block.";
      99             :             }
     100             : 
     101             :             // still read one directive
     102      155648 :             directive(node);
     103             :         }
     104             :     }
     105             :     else
     106             :     {
     107      155686 :         directive(node);
     108             :     }
     109      311334 : }
     110             : 
     111             : 
     112             : /**********************************************************************/
     113             : /**********************************************************************/
     114             : /***  PARSER BREAK & CONTINUE  ****************************************/
     115             : /**********************************************************************/
     116             : /**********************************************************************/
     117             : 
     118             : /** \brief Read a break or continue statement.
     119             :  *
     120             :  * The statement is a break or continue optionally followed by a label
     121             :  * (an identifier) or the default keyword (a special label meaning
     122             :  * use the default behavior.)
     123             :  *
     124             :  * Then we expect a semi-colon.
     125             :  *
     126             :  * The label is saved in the break or continue statement as the string
     127             :  * of the break or continue node.
     128             :  *
     129             :  * \code
     130             :  *     // A break by itself or the default break
     131             :  *     break;
     132             :  *     break default;
     133             :  *    
     134             :  *     // A break with a label
     135             :  *     break label;
     136             :  * \endcode
     137             :  *
     138             :  * \param[out] node  The node to be created.
     139             :  * \param[in] type  The type of node (break or continue).
     140             :  */
     141       81930 : void Parser::break_continue(Node::pointer_t& node, Node::node_t type)
     142             : {
     143       81930 :     node = f_lexer->get_new_node(type);
     144             : 
     145       81930 :     if(f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
     146             :     {
     147       32772 :         node->set_string(f_node->get_string());
     148       32772 :         get_token();
     149             :     }
     150       49158 :     else if(f_node->get_type() == Node::node_t::NODE_DEFAULT)
     151             :     {
     152             :         // default is equivalent to no label
     153       16386 :         get_token();
     154             :     }
     155             : 
     156       81930 :     if(f_node->get_type() != Node::node_t::NODE_SEMICOLON)
     157             :     {
     158       16386 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_LABEL, f_lexer->get_input()->get_position());
     159       16386 :         msg << "'break' and 'continue' can be followed by one label only.";
     160             :     }
     161       81930 : }
     162             : 
     163             : 
     164             : /**********************************************************************/
     165             : /**********************************************************************/
     166             : /***  PARSER CASE  ****************************************************/
     167             : /**********************************************************************/
     168             : /**********************************************************************/
     169             : 
     170       65544 : void Parser::case_directive(Node::pointer_t& node)
     171             : {
     172       65544 :     node = f_lexer->get_new_node(Node::node_t::NODE_CASE);
     173       65544 :     Node::pointer_t expr;
     174       65544 :     expression(expr);
     175       65544 :     node->append_child(expr);
     176             : 
     177             :     // check for 'case <expr> ... <expr>:'
     178      131088 :     if(f_node->get_type() == Node::node_t::NODE_REST
     179       65544 :     || f_node->get_type() == Node::node_t::NODE_RANGE)
     180             :     {
     181        8193 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_STATEMENTS))
     182             :         {
     183        2049 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     184        2049 :             msg << "ranges in a 'case' statement are only accepted when extended statements are allowed (use extended_statements;).";
     185             :         }
     186        8193 :         get_token();
     187        8193 :         Node::pointer_t expr_to;
     188        8193 :         expression(expr_to);
     189        8193 :         node->append_child(expr_to);
     190             :     }
     191             : 
     192       65544 :     if(f_node->get_type() == Node::node_t::NODE_COLON)
     193             :     {
     194       57351 :         get_token();
     195             :     }
     196             :     else
     197             :     {
     198        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CASE_LABEL, f_lexer->get_input()->get_position());
     199        8193 :         msg << "case expression expected to be followed by ':'.";
     200       65544 :     }
     201       65544 : }
     202             : 
     203             : 
     204             : 
     205             : 
     206             : 
     207             : /**********************************************************************/
     208             : /**********************************************************************/
     209             : /***  PARSER CATCH  ***************************************************/
     210             : /**********************************************************************/
     211             : /**********************************************************************/
     212             : 
     213       81930 : void Parser::catch_directive(Node::pointer_t& node)
     214             : {
     215       81930 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     216             :     {
     217       73737 :         node = f_lexer->get_new_node(Node::node_t::NODE_CATCH);
     218       73737 :         get_token();
     219       73737 :         Node::pointer_t parameters;
     220             :         bool unused;
     221       73737 :         parameter_list(parameters, unused);
     222       73737 :         if(!parameters)
     223             :         {
     224             :             {
     225        8193 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_CATCH, f_lexer->get_input()->get_position());
     226        8193 :                 msg << "the 'catch' statement cannot be used with void as its list of parameters.";
     227             :             }
     228             : 
     229             :             // silently close the parenthesis if possible
     230        8193 :             if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     231             :             {
     232        8193 :                 get_token();
     233             :             }
     234       90123 :             return;
     235             :         }
     236       65544 :         node->append_child(parameters);
     237             :         // we want exactly ONE parameter
     238       65544 :         size_t const count(parameters->get_children_size());
     239       65544 :         if(count != 1)
     240             :         {
     241        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_CATCH, f_lexer->get_input()->get_position());
     242        8193 :             msg << "the 'catch' keyword expects exactly one parameter.";
     243             :         }
     244             :         else
     245             :         {
     246             :             // There is just one parameter, make sure there
     247             :             // is no initializer
     248       57351 :             bool has_type(false);
     249       57351 :             Node::pointer_t param(parameters->get_child(0));
     250       57351 :             size_t idx(param->get_children_size());
     251       73737 :             while(idx > 0)
     252             :             {
     253       24579 :                 --idx;
     254       24579 :                 if(param->get_child(idx)->get_type() == Node::node_t::NODE_SET)
     255             :                 {
     256        8193 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_CATCH, f_lexer->get_input()->get_position());
     257        8193 :                     msg << "'catch' parameters do not support initializers.";
     258        8193 :                     break;
     259             :                 }
     260       16386 :                 has_type = true;
     261             :             }
     262       57351 :             if(has_type)
     263             :             {
     264       16386 :                 node->set_flag(Node::flag_t::NODE_CATCH_FLAG_TYPED, true);
     265       57351 :             }
     266             :         }
     267       65544 :         if(f_node->get_type() == Node::node_t::NODE_IF)
     268             :         {
     269             :             // to support the Netscape extension of conditional catch()'s
     270       16386 :             Node::pointer_t if_node(f_node);
     271       16386 :             get_token();
     272       16386 :             Node::pointer_t expr;
     273       16386 :             expression(expr);
     274       16386 :             if_node->append_child(expr);
     275       32772 :             node->append_child(if_node);
     276             :         }
     277       65544 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     278             :         {
     279       57351 :             get_token();
     280       57351 :             if(f_node->get_type() == Node::node_t::NODE_OPEN_CURVLY_BRACKET)
     281             :             {
     282       49158 :                 get_token();
     283       49158 :                 Node::pointer_t one_block;
     284       49158 :                 block(one_block);
     285       49158 :                 node->append_child(one_block);
     286             :             }
     287             :             else
     288             :             {
     289        8193 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     290       57351 :                 msg << "'{' expected after the 'catch' parameter list.";
     291             :             }
     292             :         }
     293             :         else
     294             :         {
     295        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     296       73737 :             msg << "')' expected to end the 'catch' parameter list.";
     297       73737 :         }
     298             :     }
     299             :     else
     300             :     {
     301        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     302        8193 :         msg << "'(' expected after the 'catch' keyword.";
     303             :     }
     304             : }
     305             : 
     306             : 
     307             : 
     308             : 
     309             : /**********************************************************************/
     310             : /**********************************************************************/
     311             : /***  PARSER DEBBUGER  ************************************************/
     312             : /**********************************************************************/
     313             : /**********************************************************************/
     314             : 
     315        8193 : void Parser::debugger(Node::pointer_t& node)
     316             : {
     317        8193 :     node = f_lexer->get_new_node(Node::node_t::NODE_DEBUGGER);
     318        8193 : }
     319             : 
     320             : 
     321             : /**********************************************************************/
     322             : /**********************************************************************/
     323             : /***  PARSER DEFAULT  *************************************************/
     324             : /**********************************************************************/
     325             : /**********************************************************************/
     326             : 
     327             : // NOTE: if default wasn't a keyword, then it could be used as a
     328             : //       label like any user label!
     329             : //
     330             : //       The fact that it is a keyword allows us to forbid default with
     331             : //       the goto instruction without having to do any extra work.
     332             : //
     333       16386 : void Parser::default_directive(Node::pointer_t& node)
     334             : {
     335       16386 :     node = f_lexer->get_new_node(Node::node_t::NODE_DEFAULT);
     336             : 
     337             :     // default is just itself!
     338       16386 :     if(f_node->get_type() == Node::node_t::NODE_COLON)
     339             :     {
     340        8193 :         get_token();
     341             :     }
     342             :     else
     343             :     {
     344        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_DEFAULT_LABEL, f_lexer->get_input()->get_position());
     345        8193 :         msg << "default label expected to be followed by ':'.";
     346             :     }
     347       16386 : }
     348             : 
     349             : 
     350             : 
     351             : 
     352             : 
     353             : /**********************************************************************/
     354             : /**********************************************************************/
     355             : /***  PARSER DO  ******************************************************/
     356             : /**********************************************************************/
     357             : /**********************************************************************/
     358             : 
     359       40965 : void Parser::do_directive(Node::pointer_t& node)
     360             : {
     361       40965 :     node = f_lexer->get_new_node(Node::node_t::NODE_DO);
     362             : 
     363       40965 :     Node::pointer_t one_directive;
     364       40965 :     forced_block(one_directive, node);
     365       40965 :     node->append_child(one_directive);
     366             : 
     367       40965 :     if(f_node->get_type() == Node::node_t::NODE_WHILE)
     368             :     {
     369       32772 :         get_token();
     370       32772 :         if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     371             :         {
     372       24579 :             get_token();
     373       24579 :             Node::pointer_t expr;
     374       24579 :             expression(expr);
     375       24579 :             node->append_child(expr);
     376       24579 :             if(f_node->get_type() != Node::node_t::NODE_CLOSE_PARENTHESIS)
     377             :             {
     378        8193 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     379        8193 :                 msg << "')' expected to end the 'while' expression.";
     380             :             }
     381             :             else
     382             :             {
     383       16386 :                 get_token();
     384       24579 :             }
     385             :         }
     386             :         else
     387             :         {
     388        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     389       32772 :             msg << "'(' expected after the 'while' keyword.";
     390             :         }
     391             :     }
     392             :     else
     393             :     {
     394        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_DO, f_lexer->get_input()->get_position());
     395        8193 :         msg << "'while' expected after the block of a 'do' keyword.";
     396       40965 :     }
     397       40965 : }
     398             : 
     399             : 
     400             : 
     401             : /**********************************************************************/
     402             : /**********************************************************************/
     403             : /***  PARSER FOR  *****************************************************/
     404             : /**********************************************************************/
     405             : /**********************************************************************/
     406             : 
     407      114702 : void Parser::for_directive(Node::pointer_t& node)
     408             : {
     409             :     // for each(...)
     410      114702 :     bool const for_each(f_node->get_type() == Node::node_t::NODE_IDENTIFIER
     411      114702 :                      && f_node->get_string() == "each");
     412      114702 :     if(for_each)
     413             :     {
     414       16386 :         get_token(); // skip the 'each' "keyword"
     415             :     }
     416      114702 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     417             :     {
     418      106509 :         node = f_lexer->get_new_node(Node::node_t::NODE_FOR);
     419             : 
     420      106509 :         get_token(); // skip the '('
     421      106509 :         if(f_node->get_type() == Node::node_t::NODE_SEMICOLON)
     422             :         {
     423             :             // *** EMPTY ***
     424             :             // When we have ';' directly we have got an empty initializer!
     425        8193 :             Node::pointer_t empty(f_lexer->get_new_node(Node::node_t::NODE_EMPTY));
     426        8193 :             node->append_child(empty);
     427             :         }
     428      196632 :         else if(f_node->get_type() == Node::node_t::NODE_CONST
     429       98316 :              || f_node->get_type() == Node::node_t::NODE_VAR)
     430             :         {
     431             :             // *** VARIABLE ***
     432       32772 :             bool const constant(f_node->get_type() == Node::node_t::NODE_CONST);
     433       32772 :             if(constant)
     434             :             {
     435       16386 :                 node->set_flag(Node::flag_t::NODE_FOR_FLAG_CONST, true);
     436       16386 :                 get_token(); // skip the 'const'
     437       16386 :                 if(f_node->get_type() == Node::node_t::NODE_VAR)
     438             :                 {
     439             :                     // allow just 'const' or 'const var'
     440       16386 :                     get_token(); // skip the 'var'
     441             :                 }
     442             :             }
     443             :             else
     444             :             {
     445       16386 :                 get_token(); // skip the 'var'
     446             :             }
     447       32772 :             Node::pointer_t variables;
     448       32772 :             variable(variables, constant);
     449       32772 :             node->append_child(variables);
     450             : 
     451             :             // This can happen when we return from the
     452             :             // variable() function
     453       32772 :             if(f_node->get_type() == Node::node_t::NODE_IN)
     454             :             {
     455             :                 // *** IN ***
     456       16386 :                 get_token();
     457       16386 :                 Node::pointer_t expr;
     458       16386 :                 expression(expr);
     459             :                 // TODO: we probably want to test whether the expression we
     460             :                 //       just got includes a comma (NODE_LIST) and/or
     461             :                 //       another 'in' and generate a WARNING in that case
     462             :                 //       (although the compiler should err here if necessary)
     463       16386 :                 node->append_child(expr);
     464       16386 :                 node->set_flag(Node::flag_t::NODE_FOR_FLAG_IN, true);
     465       32772 :             }
     466             :         }
     467             :         else
     468             :         {
     469       65544 :             Node::pointer_t expr;
     470       65544 :             expression(expr);
     471             : 
     472             :             // Note: if there is more than one expression (Variable
     473             :             //       definition) then the expression() function returns
     474             :             //       a NODE_LIST, not a NODE_IN
     475             : 
     476       65544 :             if(expr->get_type() == Node::node_t::NODE_IN)
     477             :             {
     478             :                 // *** IN ***
     479             :                 // if the last expression uses 'in' then break it up in two
     480             :                 // (the compiler will check that the left hand side is valid
     481             :                 // for the 'in' keyword here)
     482        8193 :                 Node::pointer_t left(expr->get_child(0));
     483       16386 :                 Node::pointer_t right(expr->get_child(1));
     484        8193 :                 expr->delete_child(0);
     485        8193 :                 expr->delete_child(0);
     486        8193 :                 node->append_child(left);
     487        8193 :                 node->append_child(right);
     488       16386 :                 node->set_flag(Node::flag_t::NODE_FOR_FLAG_IN, true);
     489             :             }
     490             :             else
     491             :             {
     492       57351 :                 node->append_child(expr);
     493       65544 :             }
     494             :         }
     495             : 
     496             :         // if not marked as an IN for loop,
     497             :         // then get the 2nd and 3rd expressions
     498      106509 :         if(!node->get_flag(Node::flag_t::NODE_FOR_FLAG_IN))
     499             :         {
     500       81930 :             if(f_node->get_type() == Node::node_t::NODE_SEMICOLON)
     501             :             {
     502             :                 // *** SECOND EXPRESSION ***
     503       73737 :                 get_token();
     504       73737 :                 Node::pointer_t expr;
     505       73737 :                 if(f_node->get_type() == Node::node_t::NODE_SEMICOLON)
     506             :                 {
     507             :                     // empty expression
     508        8193 :                     expr = f_lexer->get_new_node(Node::node_t::NODE_EMPTY);
     509             :                 }
     510             :                 else
     511             :                 {
     512       65544 :                     expression(expr);
     513             :                 }
     514       73737 :                 node->append_child(expr);
     515       73737 :                 if(f_node->get_type() == Node::node_t::NODE_SEMICOLON)
     516             :                 {
     517             :                     // *** THIRD EXPRESSION ***
     518       65544 :                     get_token();
     519       65544 :                     Node::pointer_t thrid_expr;
     520       65544 :                     if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     521             :                     {
     522        8193 :                         thrid_expr = f_lexer->get_new_node(Node::node_t::NODE_EMPTY);
     523             :                     }
     524             :                     else
     525             :                     {
     526       57351 :                         expression(thrid_expr);
     527             :                     }
     528       65544 :                     node->append_child(thrid_expr);
     529             :                 }
     530             :                 else
     531             :                 {
     532        8193 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_SEMICOLON_EXPECTED, f_lexer->get_input()->get_position());
     533        8193 :                     msg << "';' expected between the last two 'for' expressions.";
     534       73737 :                 }
     535             :             }
     536             :             else
     537             :             {
     538        8193 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_SEMICOLON_EXPECTED, f_lexer->get_input()->get_position());
     539       81930 :                 msg << "';' or 'in' expected between the 'for' expressions.";
     540             :             }
     541             :         }
     542             : 
     543      106509 :         if(f_node->get_type() != Node::node_t::NODE_CLOSE_PARENTHESIS)
     544             :         {
     545        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     546        8193 :             msg << "')' expected to close the 'for' expressions.";
     547             :         }
     548             :         else
     549             :         {
     550       98316 :             get_token();
     551             :         }
     552             : 
     553      106509 :         if(for_each)
     554             :         {
     555       16386 :             if(node->get_children_size() == 2)
     556             :             {
     557        8193 :                 node->set_flag(Node::flag_t::NODE_FOR_FLAG_FOREACH, true);
     558             :             }
     559             :             else
     560             :             {
     561        8193 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     562       16386 :                 msg << "'for each()' only available with an enumeration for.";
     563             :             }
     564             :         }
     565             : 
     566             :         // *** DIRECTIVES ***
     567      106509 :         Node::pointer_t one_directive;
     568      106509 :         forced_block(one_directive, node);
     569      106509 :         node->append_child(one_directive);
     570             :     }
     571             :     else
     572             :     {
     573        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     574        8193 :         msg << "'(' expected following the 'for' keyword.";
     575             :     }
     576      114702 : }
     577             : 
     578             : 
     579             : 
     580             : 
     581             : 
     582             : /**********************************************************************/
     583             : /**********************************************************************/
     584             : /***  PARSER GOTO  ****************************************************/
     585             : /**********************************************************************/
     586             : /**********************************************************************/
     587             : 
     588             : // although JavaScript does not support a goto directive, we support it
     589             : // in the parser; however, the compiler is likely to reject it
     590       24579 : void Parser::goto_directive(Node::pointer_t& node)
     591             : {
     592       24579 :     if(f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
     593             :     {
     594       16386 :         node = f_lexer->get_new_node(Node::node_t::NODE_GOTO);
     595             : 
     596             :         // save the label
     597       16386 :         node->set_string(f_node->get_string());
     598             : 
     599             :         // skip the label
     600       16386 :         get_token();
     601             :     }
     602             :     else
     603             :     {
     604        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_GOTO, f_lexer->get_input()->get_position());
     605        8193 :         msg << "'goto' expects a label as parameter.";
     606             :     }
     607       24579 : }
     608             : 
     609             : 
     610             : 
     611             : 
     612             : /**********************************************************************/
     613             : /**********************************************************************/
     614             : /***  PARSER IF  ******************************************************/
     615             : /**********************************************************************/
     616             : /**********************************************************************/
     617             : 
     618       65544 : void Parser::if_directive(Node::pointer_t& node)
     619             : {
     620       65544 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     621             :     {
     622       57351 :         node = f_lexer->get_new_node(Node::node_t::NODE_IF);
     623       57351 :         get_token();
     624       57351 :         Node::pointer_t expr;
     625       57351 :         expression(expr);
     626       57351 :         node->append_child(expr);
     627       57351 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     628             :         {
     629       49158 :             get_token();
     630             :         }
     631             :         else
     632             :         {
     633        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     634        8193 :             msg << "')' expected to end the 'if' expression.";
     635             :         }
     636             : 
     637       57351 :         if(f_node->get_type() == Node::node_t::NODE_ELSE)
     638             :         {
     639        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_IMPROPER_STATEMENT, f_lexer->get_input()->get_position());
     640        8193 :             msg << "statements expected following the 'if' expression, 'else' found instead.";
     641             :         }
     642             :         else
     643             :         {
     644             :             // IF part
     645       49158 :             Node::pointer_t one_directive;
     646       49158 :             forced_block(one_directive, node);
     647       49158 :             node->append_child(one_directive);
     648             :         }
     649             : 
     650             :         // Note that this is the only place where ELSE is permitted!
     651       57351 :         if(f_node->get_type() == Node::node_t::NODE_ELSE)
     652             :         {
     653       24579 :             get_token();
     654             : 
     655             :             // ELSE part
     656             :             //
     657             :             // TODO: when calling the forced_block() we call with the 'if'
     658             :             //       node which means errors are presented as if the 'if'
     659             :             //       block was wrong and not the 'else'
     660       24579 :             Node::pointer_t else_directive;
     661       24579 :             forced_block(else_directive, node);
     662       24579 :             node->append_child(else_directive);
     663       57351 :         }
     664             :     }
     665             :     else
     666             :     {
     667        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     668        8193 :         msg << "'(' expected after the 'if' keyword.";
     669             :     }
     670       65544 : }
     671             : 
     672             : 
     673             : 
     674             : 
     675             : /**********************************************************************/
     676             : /**********************************************************************/
     677             : /***  PARSER RETURN  **************************************************/
     678             : /**********************************************************************/
     679             : /**********************************************************************/
     680             : 
     681             : 
     682             : 
     683      180246 : void Parser::return_directive(Node::pointer_t& node)
     684             : {
     685      180246 :     node = f_lexer->get_new_node(Node::node_t::NODE_RETURN);
     686      180246 :     if(f_node->get_type() != Node::node_t::NODE_SEMICOLON)
     687             :     {
     688      180246 :         Node::pointer_t expr;
     689      180246 :         expression(expr);
     690      180246 :         node->append_child(expr);
     691             :     }
     692      180246 : }
     693             : 
     694             : 
     695             : /**********************************************************************/
     696             : /**********************************************************************/
     697             : /***  PARSER TRY & FINALLY  *******************************************/
     698             : /**********************************************************************/
     699             : /**********************************************************************/
     700             : 
     701       24579 : void Parser::try_finally(Node::pointer_t& node, Node::node_t type)
     702             : {
     703       24579 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_CURVLY_BRACKET)
     704             :     {
     705        8193 :         get_token();
     706        8193 :         node = f_lexer->get_new_node(type);
     707        8193 :         Node::pointer_t one_block;
     708        8193 :         block(one_block);
     709        8193 :         node->append_child(one_block);
     710             :     }
     711             :     else
     712             :     {
     713       16386 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     714       16386 :         msg << "'{' expected after the '" << (type == Node::node_t::NODE_TRY ? "try" : "finally") << "' keyword.";
     715             :     }
     716       24579 : }
     717             : 
     718             : 
     719             : 
     720             : /**********************************************************************/
     721             : /**********************************************************************/
     722             : /***  PARSER SWITCH  **************************************************/
     723             : /**********************************************************************/
     724             : /**********************************************************************/
     725             : 
     726       90123 : void Parser::switch_directive(Node::pointer_t& node)
     727             : {
     728       90123 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     729             :     {
     730       81930 :         node = f_lexer->get_new_node(Node::node_t::NODE_SWITCH);
     731             : 
     732             :         // a default comparison is important to support ranges properly
     733             :         //node->set_switch_operator(Node::node_t::NODE_UNKNOWN); -- this is the default
     734             : 
     735       81930 :         get_token();
     736       81930 :         Node::pointer_t expr;
     737       81930 :         expression(expr);
     738       81930 :         node->append_child(expr);
     739       81930 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     740             :         {
     741       73737 :             get_token();
     742             :         }
     743             :         else
     744             :         {
     745        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     746        8193 :             msg << "')' expected to end the 'switch' expression.";
     747             :         }
     748       81930 :         if(f_node->get_type() == Node::node_t::NODE_WITH)
     749             :         {
     750       57351 :             if(!has_option_set(Options::option_t::OPTION_EXTENDED_STATEMENTS))
     751             :             {
     752       14343 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     753       14343 :                 msg << "a switch() statement can be followed by a 'with' only if extended statements were turned on (use extended_statements;).";
     754             :             }
     755       57351 :             get_token();
     756       57351 :             bool const has_open(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS);
     757       57351 :             if(has_open)
     758             :             {
     759       40965 :                 get_token();
     760             :             }
     761       57351 :             switch(f_node->get_type())
     762             :             {
     763             :             // equality
     764             :             case Node::node_t::NODE_STRICTLY_EQUAL:
     765             :             case Node::node_t::NODE_EQUAL:
     766             :             case Node::node_t::NODE_NOT_EQUAL:
     767             :             case Node::node_t::NODE_STRICTLY_NOT_EQUAL:
     768             :             // relational
     769             :             case Node::node_t::NODE_MATCH:
     770             :             case Node::node_t::NODE_IN:
     771             :             case Node::node_t::NODE_IS:
     772             :             case Node::node_t::NODE_AS:
     773             :             case Node::node_t::NODE_INSTANCEOF:
     774             :             case Node::node_t::NODE_LESS:
     775             :             case Node::node_t::NODE_LESS_EQUAL:
     776             :             case Node::node_t::NODE_GREATER:
     777             :             case Node::node_t::NODE_GREATER_EQUAL:
     778             :             // so the user can specify the default too
     779             :             case Node::node_t::NODE_DEFAULT:
     780       40965 :                 node->set_switch_operator(f_node->get_type());
     781       40965 :                 get_token();
     782       40965 :                 break;
     783             : 
     784             :             default:
     785             :             {
     786       16386 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     787       16386 :                 msg << "'" << f_node->get_type_name() << "' is not a supported operator for a 'switch() with()' expression.";
     788             : 
     789       16386 :                 if(f_node->get_type() != Node::node_t::NODE_OPEN_CURVLY_BRACKET)
     790             :                 {
     791             :                     // the user probably used an invalid operator, skip it
     792        8193 :                     get_token();
     793       16386 :                 }
     794             :             }
     795       16386 :                 break;
     796             : 
     797             :             }
     798       57351 :             if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     799             :             {
     800       32772 :                 get_token();
     801       32772 :                 if(!has_open)
     802             :                 {
     803        8193 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     804       32772 :                     msg << "'(' was expected to start the 'switch() with()' expression.";
     805             :                 }
     806             :             }
     807       24579 :             else if(has_open)
     808             :             {
     809       16386 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     810       57351 :                 msg << "')' expected to end the 'switch() with()' expression.";
     811             :             }
     812             :         }
     813       81930 :         Node::pointer_t attr_list;
     814       81930 :         attributes(attr_list);
     815       81930 :         if(attr_list && attr_list->get_children_size() > 0)
     816             :         {
     817       16386 :             node->set_link(Node::link_t::LINK_ATTRIBUTES, attr_list);
     818             :         }
     819       81930 :         if(f_node->get_type() == Node::node_t::NODE_OPEN_CURVLY_BRACKET)
     820             :         {
     821       73737 :             get_token();
     822       73737 :             Node::pointer_t one_block;
     823       73737 :             block(one_block);
     824       73737 :             node->append_child(one_block);
     825             :         }
     826             :         else
     827             :         {
     828        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     829        8193 :             msg << "'{' expected after the 'switch' expression.";
     830       81930 :         }
     831             :     }
     832             :     else
     833             :     {
     834        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     835        8193 :         msg << "'(' expected after the 'switch' keyword.";
     836             :     }
     837       90123 : }
     838             : 
     839             : 
     840             : 
     841             : /**********************************************************************/
     842             : /**********************************************************************/
     843             : /***  PARSER SYNCHRONIZED  ********************************************/
     844             : /**********************************************************************/
     845             : /**********************************************************************/
     846             : 
     847       32772 : void Parser::synchronized(Node::pointer_t& node)
     848             : {
     849       32772 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     850             :     {
     851       24579 :         node = f_lexer->get_new_node(Node::node_t::NODE_SYNCHRONIZED);
     852       24579 :         get_token();
     853             : 
     854             :         // retrieve the object being synchronized
     855       24579 :         Node::pointer_t expr;
     856       24579 :         expression(expr);
     857       24579 :         node->append_child(expr);
     858       24579 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     859             :         {
     860       16386 :             get_token();
     861             :         }
     862             :         else
     863             :         {
     864        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     865        8193 :             msg << "')' expected to end the 'synchronized' expression.";
     866             :         }
     867       24579 :         if(f_node->get_type() == Node::node_t::NODE_OPEN_CURVLY_BRACKET)
     868             :         {
     869       16386 :             get_token();
     870       16386 :             Node::pointer_t one_block;
     871       16386 :             block(one_block);
     872       16386 :             node->append_child(one_block);
     873             :         }
     874             :         else
     875             :         {
     876        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     877        8193 :             msg << "'{' expected after the 'synchronized' expression.";
     878       24579 :         }
     879             :     }
     880             :     else
     881             :     {
     882        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     883        8193 :         msg << "'(' expected after the 'synchronized' keyword.";
     884             :     }
     885       32772 : }
     886             : 
     887             : 
     888             : 
     889             : /**********************************************************************/
     890             : /**********************************************************************/
     891             : /***  PARSER THROW  ***************************************************/
     892             : /**********************************************************************/
     893             : /**********************************************************************/
     894             : 
     895       24579 : void Parser::throw_directive(Node::pointer_t& node)
     896             : {
     897       24579 :     node = f_lexer->get_new_node(Node::node_t::NODE_THROW);
     898             : 
     899             :     // if we already have a semi-colon, the user is rethrowing
     900       24579 :     if(f_node->get_type() != Node::node_t::NODE_SEMICOLON)
     901             :     {
     902       16386 :         Node::pointer_t expr;
     903       16386 :         expression(expr);
     904       16386 :         node->append_child(expr);
     905             :     }
     906       24579 : }
     907             : 
     908             : 
     909             : 
     910             : /**********************************************************************/
     911             : /**********************************************************************/
     912             : /***  PARSER WITH & WHILE  ********************************************/
     913             : /**********************************************************************/
     914             : /**********************************************************************/
     915             : 
     916      106509 : void Parser::with_while(Node::pointer_t& node, Node::node_t type)
     917             : {
     918      106509 :     char const *inst = type == Node::node_t::NODE_WITH ? "with" : "while";
     919             : 
     920      106509 :     if(type == Node::node_t::NODE_WITH)
     921             :     {
     922       32772 :         if(!has_option_set(Options::option_t::OPTION_ALLOW_WITH))
     923             :         {
     924             :             // WITH is just not allowed at all by default
     925       16388 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     926       16388 :             msg << "'WITH' is not allowed; you may authorize it with a pragam (use allow_with;) but it is not recommended.";
     927             :         }
     928       16384 :         else if(has_option_set(Options::option_t::OPTION_STRICT))
     929             :         {
     930             :             // WITH cannot be used in strict mode (see ECMAScript)
     931        8192 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED_IN_STRICT_MODE, f_lexer->get_input()->get_position());
     932       32772 :             msg << "'WITH' is not allowed in strict mode.";
     933             :         }
     934             :     }
     935             : 
     936      106509 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_PARENTHESIS)
     937             :     {
     938       90123 :         node = f_lexer->get_new_node(type);
     939       90123 :         get_token();
     940       90123 :         Node::pointer_t expr;
     941       90123 :         expression(expr);
     942       90123 :         node->append_child(expr);
     943       90123 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     944             :         {
     945       73737 :             get_token();
     946             :         }
     947             :         else
     948             :         {
     949       16386 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     950       16386 :             msg << "')' expected to end the '" << inst << "' expression.";
     951             :         }
     952       90123 :         Node::pointer_t one_directive;
     953       90123 :         forced_block(one_directive, node);
     954      180246 :         node->append_child(one_directive);
     955             :     }
     956             :     else
     957             :     {
     958       16386 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     959       16386 :         msg << "'(' expected after the '" << inst << "' keyword.";
     960             :     }
     961      106509 : }
     962             : 
     963             : 
     964             : 
     965             : /**********************************************************************/
     966             : /**********************************************************************/
     967             : /***  PARSER YIELD  ***************************************************/
     968             : /**********************************************************************/
     969             : /**********************************************************************/
     970             : 
     971       16386 : void Parser::yield(Node::pointer_t& node)
     972             : {
     973       16386 :     if(f_node->get_type() != Node::node_t::NODE_SEMICOLON)
     974             :     {
     975        8193 :         node = f_lexer->get_new_node(Node::node_t::NODE_YIELD);
     976             : 
     977        8193 :         Node::pointer_t expr;
     978        8193 :         expression(expr);
     979        8193 :         node->append_child(expr);
     980             :     }
     981             :     else
     982             :     {
     983        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_EXPRESSION_EXPECTED, f_lexer->get_input()->get_position());
     984        8193 :         msg << "yield is expected to be followed by an expression.";
     985             :     }
     986       16386 : }
     987             : 
     988             : 
     989             : 
     990             : 
     991             : 
     992             : 
     993          20 : }
     994             : // namespace as2js
     995             : 
     996             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.9