LCOV - code coverage report
Current view: top level - lib - parser_expression.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 550 550 100.0 %
Date: 2014-11-22 Functions: 24 24 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* parser_expression.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/exceptions.h"
      38             : #include "as2js/message.h"
      39             : 
      40             : 
      41             : namespace as2js
      42             : {
      43             : 
      44             : 
      45             : /**********************************************************************/
      46             : /**********************************************************************/
      47             : /***  PARSER EXPRESSION  **********************************************/
      48             : /**********************************************************************/
      49             : /**********************************************************************/
      50             : 
      51     2064840 : void Parser::expression(Node::pointer_t& node)
      52             : {
      53     2064840 :     list_expression(node, false, false);
      54             : 
      55     2064840 :     if(!node)
      56             :     {
      57             :         // should not happen, if it does, we have got a really bad internal error
      58             :         throw exception_internal_error("expression() cannot return a null node pointer"); // LCOV_EXCL_LINE
      59             :     }
      60     2064840 : }
      61             : 
      62             : 
      63     2482634 : void Parser::list_expression(Node::pointer_t& node, bool rest, bool empty)
      64             : {
      65     2482634 :     if(node)
      66             :     {
      67             :         // should not happen, if it does, we have got a really bad internal error
      68             :         throw exception_internal_error("list_expression() called with a non-null node pointer"); // LCOV_EXCL_LINE
      69             :     }
      70             : 
      71     2482634 :     int has_rest(0);
      72     2482634 :     if(empty && f_node->get_type() == Node::node_t::NODE_COMMA)
      73             :     {
      74             :         // empty at the start of the array
      75       24576 :         node = f_lexer->get_new_node(Node::node_t::NODE_EMPTY);
      76             :     }
      77     2458058 :     else if(rest && f_node->get_type() == Node::node_t::NODE_REST)
      78             :     {
      79             :         // the '...' in a function call is used to mean pass
      80             :         // my own rest down to the callee
      81        8192 :         node = f_lexer->get_new_node(Node::node_t::NODE_REST);
      82        8192 :         get_token();
      83        8192 :         has_rest = 1;
      84             :         // note: we expect ')' here but we
      85             :         // let the user put ',' <expr> still
      86             :         // and err in case it happens
      87             :     }
      88     2449866 :     else if(rest && f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
      89             :     {
      90             :         // identifiers ':' -> named parameter
      91      155648 :         Node::pointer_t save(f_node);
      92             :         // skip the identifier
      93      155648 :         get_token();
      94      155648 :         if(f_node->get_type() == Node::node_t::NODE_COLON)
      95             :         {
      96             :             // skip the ':'
      97       81920 :             get_token();
      98       81920 :             node = f_lexer->get_new_node(Node::node_t::NODE_NAME);
      99       81920 :             node->set_string(save->get_string());
     100       81920 :             if(f_node->get_type() == Node::node_t::NODE_REST)
     101             :             {
     102             :                 // the '...' in a function call is used to mean pass
     103             :                 // my own rest down to the callee
     104       16384 :                 Node::pointer_t rest_of_args(f_lexer->get_new_node(Node::node_t::NODE_REST));
     105       16384 :                 node->append_child(rest_of_args);
     106       16384 :                 get_token();
     107       16384 :                 has_rest = 1;
     108             :                 // note: we expect ')' here but we
     109             :                 // let the user put ',' <expr> still
     110             :                 // and err in case it happens
     111             :             }
     112             :             else
     113             :             {
     114       65536 :                 Node::pointer_t value;
     115       65536 :                 assignment_expression(value);
     116       65536 :                 node->append_child(value);
     117             :             }
     118             :         }
     119             :         else
     120             :         {
     121       73728 :             unget_token(f_node);
     122       73728 :             f_node = save;
     123       73728 :             assignment_expression(node);
     124      155648 :         }
     125             :     }
     126             :     else
     127             :     {
     128     2294218 :         assignment_expression(node);
     129             :     }
     130             : 
     131     2482634 :     if(f_node->get_type() == Node::node_t::NODE_COMMA)
     132             :     {
     133      196611 :         Node::pointer_t first_item(node);
     134             : 
     135      196611 :         node = f_lexer->get_new_node(Node::node_t::NODE_LIST);
     136      196611 :         node->append_child(first_item);
     137             : 
     138      843785 :         while(f_node->get_type() == Node::node_t::NODE_COMMA)
     139             :         {
     140      450563 :             get_token();
     141      450563 :             if(has_rest == 1)
     142             :             {
     143       24576 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_REST, f_lexer->get_input()->get_position());
     144       24576 :                 msg << "'...' was expected to be the last expression in this function call.";
     145       24576 :                 has_rest = 2;
     146             :             }
     147      450563 :             if(empty && f_node->get_type() == Node::node_t::NODE_COMMA)
     148             :             {
     149             :                 // empty inside the array
     150      106496 :                 Node::pointer_t empty_node(f_lexer->get_new_node(Node::node_t::NODE_EMPTY));
     151      106496 :                 node->append_child(empty_node);
     152             :             }
     153      344067 :             else if(empty && f_node->get_type() == Node::node_t::NODE_CLOSE_SQUARE_BRACKET)
     154             :             {
     155             :                 // empty at the end of the array
     156       16384 :                 Node::pointer_t empty_node(f_lexer->get_new_node(Node::node_t::NODE_EMPTY));
     157       16384 :                 node->append_child(empty_node);
     158             :             }
     159      327683 :             else if(rest && f_node->get_type() == Node::node_t::NODE_REST)
     160             :             {
     161             :                 // the '...' in a function call is used to mean pass
     162             :                 // my own rest down to the callee
     163        8192 :                 Node::pointer_t rest_node(f_lexer->get_new_node(Node::node_t::NODE_REST));
     164        8192 :                 node->append_child(rest_node);
     165        8192 :                 get_token();
     166        8192 :                 if(has_rest == 0)
     167             :                 {
     168        8192 :                     has_rest = 1;
     169        8192 :                 }
     170             :                 // note: we expect ')' here but we
     171             :                 // let the user put ',' <expr> still
     172             :                 // and err in case it happens
     173             :             }
     174      319491 :             else if(rest && f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
     175             :             {
     176      122880 :                 Node::pointer_t item;
     177             : 
     178             :                 // identifiers ':' -> named parameter
     179      245760 :                 Node::pointer_t save(f_node);
     180      122880 :                 get_token();
     181      122880 :                 if(f_node->get_type() == Node::node_t::NODE_COLON)
     182             :                 {
     183       90112 :                     get_token();
     184       90112 :                     item = f_lexer->get_new_node(Node::node_t::NODE_NAME);
     185       90112 :                     item->set_string(save->get_string());
     186             : 
     187       90112 :                     if(f_node->get_type() == Node::node_t::NODE_REST)
     188             :                     {
     189             :                         // the '...' in a function call is used to mean pass
     190             :                         // my own rest down to the callee
     191       65536 :                         Node::pointer_t rest_of_args(f_lexer->get_new_node(Node::node_t::NODE_REST));
     192       65536 :                         item->append_child(rest_of_args);
     193       65536 :                         get_token();
     194       65536 :                         if(has_rest == 0)
     195             :                         {
     196       49152 :                             has_rest = 1;
     197       65536 :                         }
     198             :                         // note: we expect ')' here but we
     199             :                         // let the user put ',' <expr> still
     200             :                         // and err in case it happens
     201             :                     }
     202             :                     else
     203             :                     {
     204       24576 :                         Node::pointer_t value;
     205       24576 :                         assignment_expression(value);
     206       24576 :                         item->append_child(value);
     207             :                     }
     208       90112 :                     node->append_child(item);
     209             :                 }
     210             :                 else
     211             :                 {
     212       32768 :                     unget_token(f_node);
     213       32768 :                     f_node = save;
     214       32768 :                     assignment_expression(item);
     215       32768 :                     node->append_child(item);
     216      122880 :                 }
     217             :             }
     218             :             else
     219             :             {
     220      196611 :                 Node::pointer_t item;
     221      196611 :                 assignment_expression(item);
     222      196611 :                 node->append_child(item);
     223             :             }
     224      196611 :         }
     225             : 
     226             :         // TODO: check that the list ends with a NODE_REST
     227             :     }
     228     2482634 : }
     229             : 
     230             : 
     231     3768818 : void Parser::assignment_expression(Node::pointer_t& node)
     232             : {
     233     3768818 :     conditional_expression(node, true);
     234             : 
     235             :     // TODO: check that the result is a postfix expression
     236     3768818 :     switch(f_node->get_type())
     237             :     {
     238             :     case Node::node_t::NODE_ASSIGNMENT:
     239             :     case Node::node_t::NODE_ASSIGNMENT_ADD:
     240             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_AND:
     241             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_OR:
     242             :     case Node::node_t::NODE_ASSIGNMENT_BITWISE_XOR:
     243             :     case Node::node_t::NODE_ASSIGNMENT_DIVIDE:
     244             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_AND:
     245             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_OR:
     246             :     case Node::node_t::NODE_ASSIGNMENT_MODULO:
     247             :     case Node::node_t::NODE_ASSIGNMENT_MULTIPLY:
     248             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_LEFT:
     249             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT:
     250             :     case Node::node_t::NODE_ASSIGNMENT_SHIFT_RIGHT_UNSIGNED:
     251             :     case Node::node_t::NODE_ASSIGNMENT_SUBTRACT:
     252      606234 :         break;
     253             : 
     254             :     case Node::node_t::NODE_ASSIGNMENT_LOGICAL_XOR:
     255             :     case Node::node_t::NODE_ASSIGNMENT_MAXIMUM:
     256             :     case Node::node_t::NODE_ASSIGNMENT_MINIMUM:
     257             :     case Node::node_t::NODE_ASSIGNMENT_POWER:
     258             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_LEFT:
     259             :     case Node::node_t::NODE_ASSIGNMENT_ROTATE_RIGHT:
     260        8197 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     261             :         {
     262        2048 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     263        2048 :             msg << "the '" << f_node->get_type_name() << "' operator is only available when extended operators are authorized (use extended_operators;).";
     264             :         }
     265        8197 :         break;
     266             : 
     267             :     default:
     268     6308774 :         return;
     269             : 
     270             :     }
     271             : 
     272      614431 :     Node::pointer_t left(node);
     273             : 
     274      614431 :     node = f_node;
     275             : 
     276      614431 :     get_token();
     277     1228862 :     Node::pointer_t right;
     278      614431 :     assignment_expression(right);
     279             : 
     280      614431 :     node->append_child(left);
     281     1228862 :     node->append_child(right);
     282             : }
     283             : 
     284             : 
     285     4891852 : void Parser::conditional_expression(Node::pointer_t& node, bool const assignment)
     286             : {
     287     4891852 :     min_max_expression(node);
     288             : 
     289     4891852 :     if(f_node->get_type() == Node::node_t::NODE_CONDITIONAL)
     290             :     {
     291       57347 :         f_node->append_child(node);
     292       57347 :         node = f_node;
     293             : 
     294       57347 :         get_token();
     295       57347 :         Node::pointer_t left;
     296             :         // not like C/C++, not a list expression here
     297       57347 :         if(assignment)
     298             :         {
     299       40963 :             assignment_expression(left);
     300             :         }
     301             :         else
     302             :         {
     303       16384 :             conditional_expression(left, false);
     304             :         }
     305       57347 :         node->append_child(left);
     306             : 
     307       57347 :         if(f_node->get_type() == Node::node_t::NODE_COLON)
     308             :         {
     309       49155 :             get_token();
     310       49155 :             Node::pointer_t right;
     311       49155 :             if(assignment)
     312             :             {
     313       40963 :                 assignment_expression(right);
     314             :             }
     315             :             else
     316             :             {
     317        8192 :                 conditional_expression(right, false);
     318             :             }
     319       49155 :             node->append_child(right);
     320             :         }
     321             :         else
     322             :         {
     323        8192 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_CONDITIONAL, f_lexer->get_input()->get_position());
     324        8192 :             msg << "invalid use of the conditional operator, ':' was expected.";
     325       57347 :         }
     326             :     }
     327     4891852 : }
     328             : 
     329             : 
     330             : 
     331     4891852 : void Parser::min_max_expression(Node::pointer_t& node)
     332             : {
     333     4891852 :     logical_or_expression(node);
     334             : 
     335     9783704 :     if(f_node->get_type() == Node::node_t::NODE_MINIMUM
     336     4891852 :     || f_node->get_type() == Node::node_t::NODE_MAXIMUM)
     337             :     {
     338        8198 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     339             :         {
     340        2048 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     341        2048 :             msg << "the '" << f_node->get_type_name() << "' operator is only available when extended operators are authorized (use extended_operators;).";
     342             :         }
     343        8198 :         f_node->append_child(node);
     344        8198 :         node = f_node;
     345             : 
     346        8198 :         get_token();
     347        8198 :         Node::pointer_t right;
     348        8198 :         logical_or_expression(right);
     349        8198 :         node->append_child(right);
     350             :     }
     351     4891852 : }
     352             : 
     353             : 
     354     4900050 : void Parser::logical_or_expression(Node::pointer_t& node)
     355             : {
     356     4900050 :     logical_xor_expression(node);
     357             : 
     358     4900050 :     if(f_node->get_type() == Node::node_t::NODE_LOGICAL_OR)
     359             :     {
     360        8203 :         f_node->append_child(node);
     361        8203 :         node = f_node;
     362             : 
     363        8203 :         get_token();
     364        8203 :         Node::pointer_t right;
     365        8203 :         logical_xor_expression(right);
     366        8203 :         node->append_child(right);
     367             :     }
     368     4900050 : }
     369             : 
     370             : 
     371     4908253 : void Parser::logical_xor_expression(Node::pointer_t& node)
     372             : {
     373     4908253 :     logical_and_expression(node);
     374             : 
     375     4908253 :     if(f_node->get_type() == Node::node_t::NODE_LOGICAL_XOR)
     376             :     {
     377        8202 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     378             :         {
     379        2048 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     380        2048 :             msg << "the '^^' operator is only available when extended operators are authorized (use extended_operators;).";
     381             :         }
     382        8202 :         f_node->append_child(node);
     383        8202 :         node = f_node;
     384             : 
     385        8202 :         get_token();
     386        8202 :         Node::pointer_t right;
     387        8202 :         logical_and_expression(right);
     388        8202 :         node->append_child(right);
     389             :     }
     390     4908253 : }
     391             : 
     392             : 
     393     4916455 : void Parser::logical_and_expression(Node::pointer_t& node)
     394             : {
     395     4916455 :     bitwise_or_expression(node);
     396             : 
     397     4916455 :     if(f_node->get_type() == Node::node_t::NODE_LOGICAL_AND)
     398             :     {
     399        8204 :         f_node->append_child(node);
     400        8204 :         node = f_node;
     401             : 
     402        8204 :         get_token();
     403        8204 :         Node::pointer_t right;
     404        8204 :         bitwise_or_expression(right);
     405        8204 :         node->append_child(right);
     406             :     }
     407     4916455 : }
     408             : 
     409             : 
     410             : 
     411     4924659 : void Parser::bitwise_or_expression(Node::pointer_t& node)
     412             : {
     413     4924659 :     bitwise_xor_expression(node);
     414             : 
     415     4924659 :     if(f_node->get_type() == Node::node_t::NODE_BITWISE_OR)
     416             :     {
     417       16386 :         f_node->append_child(node);
     418       16386 :         node = f_node;
     419             : 
     420       16386 :         get_token();
     421       16386 :         Node::pointer_t right;
     422       16386 :         bitwise_xor_expression(right);
     423       16386 :         node->append_child(right);
     424             :     }
     425     4924659 : }
     426             : 
     427             : 
     428     4941045 : void Parser::bitwise_xor_expression(Node::pointer_t& node)
     429             : {
     430     4941045 :     bitwise_and_expression(node);
     431             : 
     432     4941045 :     if(f_node->get_type() == Node::node_t::NODE_BITWISE_XOR)
     433             :     {
     434       16391 :         f_node->append_child(node);
     435       16391 :         node = f_node;
     436             : 
     437       16391 :         get_token();
     438       16391 :         Node::pointer_t right;
     439       16391 :         bitwise_and_expression(right);
     440       16391 :         node->append_child(right);
     441             :     }
     442     4941045 : }
     443             : 
     444             : 
     445     4957436 : void Parser::bitwise_and_expression(Node::pointer_t& node)
     446             : {
     447     4957436 :     equality_expression(node);
     448             : 
     449     4957436 :     if(f_node->get_type() == Node::node_t::NODE_BITWISE_AND)
     450             :     {
     451        8200 :         f_node->append_child(node);
     452        8200 :         node = f_node;
     453             : 
     454        8200 :         get_token();
     455        8200 :         Node::pointer_t right;
     456        8200 :         equality_expression(right);
     457        8200 :         node->append_child(right);
     458             :     }
     459     4957436 : }
     460             : 
     461             : 
     462     4965636 : void Parser::equality_expression(Node::pointer_t& node)
     463             : {
     464     4965636 :     relational_expression(node);
     465             : 
     466     4965636 :     Node::node_t type(f_node->get_type());
     467     9996936 :     while(type == Node::node_t::NODE_EQUAL
     468     4990320 :        || type == Node::node_t::NODE_NOT_EQUAL
     469     4982108 :        || type == Node::node_t::NODE_STRICTLY_EQUAL
     470     4982088 :        || type == Node::node_t::NODE_STRICTLY_NOT_EQUAL
     471     4982068 :        || type == Node::node_t::NODE_COMPARE
     472     4973850 :        || type == Node::node_t::NODE_SMART_MATCH)
     473             :     {
     474      123110 :         if((type == Node::node_t::NODE_COMPARE || type == Node::node_t::NODE_SMART_MATCH)
     475       82096 :         && !has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     476             :         {
     477        4096 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     478        4096 :             msg << "the '" << f_node->get_type_name() << "' operator is only available when extended operators are authorized (use extended_operators;).";
     479             :         }
     480       65664 :         f_node->append_child(node);
     481       65664 :         node = f_node;
     482             : 
     483       65664 :         get_token();
     484       65664 :         Node::pointer_t right;
     485       65664 :         relational_expression(right);
     486       65664 :         node->append_child(right);
     487             : 
     488       65664 :         type = f_node->get_type();
     489       65664 :     }
     490     4965636 : }
     491             : 
     492             : 
     493     5031300 : void Parser::relational_expression(Node::pointer_t& node)
     494             : {
     495     5031300 :     shift_expression(node);
     496             : 
     497    15470892 :     while(f_node->get_type() == Node::node_t::NODE_LESS
     498     5178816 :        || f_node->get_type() == Node::node_t::NODE_GREATER
     499     5137836 :        || f_node->get_type() == Node::node_t::NODE_LESS_EQUAL
     500     5113240 :        || f_node->get_type() == Node::node_t::NODE_GREATER_EQUAL
     501     5064068 :        || f_node->get_type() == Node::node_t::NODE_IS
     502     5064068 :        || f_node->get_type() == Node::node_t::NODE_AS
     503     5064068 :        || f_node->get_type() == Node::node_t::NODE_IN
     504    10267480 :        || f_node->get_type() == Node::node_t::NODE_INSTANCEOF)
     505             :     {
     506      188496 :         f_node->append_child(node);
     507      188496 :         node = f_node;
     508             : 
     509      188496 :         get_token();
     510      188496 :         Node::pointer_t right;
     511      188496 :         shift_expression(right);
     512      188496 :         node->append_child(right);
     513             : 
     514             :         // with IN we accept a range (optional)
     515      376992 :         if(node->get_type() == Node::node_t::NODE_IN
     516      188496 :         && (f_node->get_type() == Node::node_t::NODE_RANGE || f_node->get_type() == Node::node_t::NODE_REST))
     517             :         {
     518        8192 :             if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     519             :             {
     520        2048 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     521        2048 :                 msg << "the 'x in min .. max' operator is only available when extended operators are authorized (use extended_operators;).";
     522             :             }
     523             : 
     524        8192 :             get_token();
     525        8192 :             Node::pointer_t end;
     526        8192 :             shift_expression(end);
     527        8192 :             node->append_child(end);
     528             :         }
     529      188496 :     }
     530     5031300 : }
     531             : 
     532             : 
     533     5227988 : void Parser::shift_expression(Node::pointer_t& node)
     534             : {
     535     5227988 :     additive_expression(node);
     536             : 
     537     5227988 :     Node::node_t type(f_node->get_type());
     538    10472382 :     while(type == Node::node_t::NODE_SHIFT_LEFT
     539     5244391 :        || type == Node::node_t::NODE_SHIFT_RIGHT
     540     5244387 :        || type == Node::node_t::NODE_SHIFT_RIGHT_UNSIGNED
     541     5244383 :        || type == Node::node_t::NODE_ROTATE_LEFT
     542     5227996 :        || type == Node::node_t::NODE_ROTATE_RIGHT)
     543             :     {
     544       16425 :         if((type == Node::node_t::NODE_ROTATE_LEFT || type == Node::node_t::NODE_ROTATE_RIGHT)
     545       32801 :         && !has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     546             :         {
     547        4096 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     548        4096 :             msg << "the '" << f_node->get_type_name() << "' operator is only available when extended operators are authorized (use extended_operators;).";
     549             :         }
     550             : 
     551       16406 :         f_node->append_child(node);
     552       16406 :         node = f_node;
     553             : 
     554       16406 :         get_token();
     555       16406 :         Node::pointer_t right;
     556       16406 :         additive_expression(right);
     557       16406 :         node->append_child(right);
     558             : 
     559       16406 :         type = f_node->get_type();
     560       16406 :     }
     561     5227988 : }
     562             : 
     563             : 
     564     5244394 : void Parser::additive_expression(Node::pointer_t& node)
     565             : {
     566     5244394 :     multiplicative_expression(node);
     567             : 
     568    16159240 :     while(f_node->get_type() == Node::node_t::NODE_ADD
     569     5457423 :        || f_node->get_type() == Node::node_t::NODE_SUBTRACT)
     570             :     {
     571      213029 :         f_node->append_child(node);
     572      213029 :         node = f_node;
     573             : 
     574      213029 :         get_token();
     575      213029 :         Node::pointer_t right;
     576      213029 :         multiplicative_expression(right);
     577      213029 :         node->append_child(right);
     578      213029 :     }
     579     5244394 : }
     580             : 
     581             : 
     582     5457423 : void Parser::multiplicative_expression(Node::pointer_t& node)
     583             : {
     584     5457423 :     match_expression(node);
     585             : 
     586    16487021 :     while(f_node->get_type() == Node::node_t::NODE_MULTIPLY
     587     5457443 :        || f_node->get_type() == Node::node_t::NODE_DIVIDE
     588    10972232 :        || f_node->get_type() == Node::node_t::NODE_MODULO)
     589             :     {
     590       57376 :         f_node->append_child(node);
     591       57376 :         node = f_node;
     592             : 
     593       57376 :         get_token();
     594       57376 :         Node::pointer_t right;
     595       57376 :         match_expression(right);
     596       57376 :         node->append_child(right);
     597       57376 :     }
     598     5457423 : }
     599             : 
     600             : 
     601     5514799 : void Parser::match_expression(Node::pointer_t& node)
     602             : {
     603     5514799 :     power_expression(node);
     604             : 
     605    16560781 :     while(f_node->get_type() == Node::node_t::NODE_MATCH
     606     5522991 :        || f_node->get_type() == Node::node_t::NODE_NOT_MATCH)
     607             :     {
     608        8192 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     609             :         {
     610        2048 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     611        2048 :             msg << "the '" << f_node->get_type_name() << "' operator is only available when extended operators are authorized (use extended_operators;).";
     612             :         }
     613             : 
     614        8192 :         f_node->append_child(node);
     615        8192 :         node = f_node;
     616             : 
     617        8192 :         get_token();
     618        8192 :         Node::pointer_t right;
     619        8192 :         power_expression(right);
     620        8192 :         node->append_child(right);
     621        8192 :     }
     622     5514799 : }
     623             : 
     624             : 
     625     5539383 : void Parser::power_expression(Node::pointer_t& node)
     626             : {
     627     5539383 :     unary_expression(node);
     628             : 
     629     5539383 :     if(f_node->get_type() == Node::node_t::NODE_POWER)
     630             :     {
     631       16392 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     632             :         {
     633        4096 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     634        4096 :             msg << "the '**' operator is only available when extended operators are authorized (use extended_operators;).";
     635             :         }
     636             : 
     637       16392 :         f_node->append_child(node);
     638       16392 :         node = f_node;
     639             : 
     640       16392 :         get_token();
     641       16392 :         Node::pointer_t right;
     642       16392 :         power_expression(right); // right to left
     643       16392 :         node->append_child(right);
     644             :     }
     645     5539383 : }
     646             : 
     647             : 
     648             : 
     649     5670609 : void Parser::unary_expression(Node::pointer_t& node)
     650             : {
     651     5670609 :     if(node)
     652             :     {
     653             :         throw exception_internal_error("unary_expression() called with a non-null node pointer");  // LCOV_EXCL_LINE
     654             :     }
     655             : 
     656     5670609 :     switch(f_node->get_type())
     657             :     {
     658             :     case Node::node_t::NODE_DELETE:
     659             :     case Node::node_t::NODE_INCREMENT:
     660             :     case Node::node_t::NODE_DECREMENT:
     661             :     {
     662       40960 :         node = f_node;
     663       40960 :         get_token();
     664       40960 :         Node::pointer_t postfix;
     665       40960 :         postfix_expression(postfix);
     666       40960 :         node->append_child(postfix);
     667             :     }
     668       40960 :         break;
     669             : 
     670             :     case Node::node_t::NODE_VOID:
     671             :     case Node::node_t::NODE_TYPEOF:
     672             :     case Node::node_t::NODE_ADD: // +<value>
     673             :     case Node::node_t::NODE_SUBTRACT: // -<value>
     674             :     case Node::node_t::NODE_BITWISE_NOT:
     675             :     case Node::node_t::NODE_LOGICAL_NOT:
     676             :     {
     677      114840 :         node = f_node;
     678      114840 :         get_token();
     679      114840 :         Node::pointer_t unary;
     680      114840 :         unary_expression(unary);
     681      114840 :         node->append_child(unary);
     682             :     }
     683      114840 :         break;
     684             : 
     685             :     case Node::node_t::NODE_SMART_MATCH:
     686             :     {
     687             :         // we support the ~~ for Smart Match, but if found as a unary
     688             :         // operator the user had to mean '~' and '~' separated as in:
     689             :         //     a = ~ ~ b
     690             :         // so here we generate two bitwise not (DO NOT OPTIMIZE, if one
     691             :         // writes a = ~~b it is NOT the same as a = b because JavaScript
     692             :         // forces a conversion of b to a 32 bit integer when applying the
     693             :         // bitwise not operator.)
     694             :         //
     695        8193 :         node = f_lexer->get_new_node(Node::node_t::NODE_BITWISE_NOT);
     696        8193 :         Node::pointer_t child(f_lexer->get_new_node(Node::node_t::NODE_BITWISE_NOT));
     697        8193 :         node->append_child(child);
     698        8193 :         get_token();
     699       16386 :         Node::pointer_t unary;
     700        8193 :         unary_expression(unary);
     701       16386 :         child->append_child(unary);
     702             :     }
     703        8193 :         break;
     704             : 
     705             :     case Node::node_t::NODE_NOT_MATCH:
     706             :     {
     707             :         // we support the !~ for Not Match, but if found as a unary
     708             :         // operator the user had to mean '!' and '~' separated as in:
     709             :         //     a = ! ~ b
     710             :         // so here we generate two not (DO NOT OPTIMIZE, if one
     711             :         // writes a = !~b it is NOT the same as a = b because JavaScript
     712             :         // forces a conversion of b to a 32 bit integer when applying the
     713             :         // bitwise not operator.)
     714             :         //
     715        8193 :         node = f_lexer->get_new_node(Node::node_t::NODE_LOGICAL_NOT);
     716        8193 :         Node::pointer_t child(f_lexer->get_new_node(Node::node_t::NODE_BITWISE_NOT));
     717        8193 :         node->append_child(child);
     718        8193 :         get_token();
     719       16386 :         Node::pointer_t unary;
     720        8193 :         unary_expression(unary);
     721       16386 :         child->append_child(unary);
     722             :     }
     723        8193 :         break;
     724             : 
     725             :     default:
     726     5498423 :         postfix_expression(node);
     727     5498423 :         break;
     728             : 
     729             :     }
     730     5670609 : }
     731             : 
     732             : 
     733     5555767 : void Parser::postfix_expression(Node::pointer_t& node)
     734             : {
     735     5555767 :     primary_expression(node);
     736             : 
     737             :     for(;;)
     738             :     {
     739     6743611 :         switch(f_node->get_type())
     740             :         {
     741             :         case Node::node_t::NODE_MEMBER:
     742             :         {
     743      770048 :             f_node->append_child(node);
     744      770048 :             node = f_node;
     745             : 
     746      770048 :             get_token();
     747      770048 :             Node::pointer_t right;
     748      770048 :             primary_expression(right);
     749      770048 :             node->append_child(right);
     750             :         }
     751      770048 :             break;
     752             : 
     753             :         case Node::node_t::NODE_SCOPE:
     754             :         {
     755             :             // TBD: I do not think that we need a scope operator at all
     756             :             //      since we can use the '.' (MEMBER) operator in all cases
     757             :             //      I can currently think of (and in JavaScript you are
     758             :             //      expected to do so anyway!) therefore I only authorize
     759             :             //      it as an extension at the moment
     760       65536 :             if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     761             :             {
     762       16384 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     763       16384 :                 msg << "the '::' operator is only available when extended operators are authorized (use extended_operators;).";
     764             :             }
     765             : 
     766       65536 :             f_node->append_child(node);
     767       65536 :             node = f_node;
     768             : 
     769       65536 :             get_token();
     770       65536 :             if(f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
     771             :             {
     772       24576 :                 node->append_child(f_node);
     773       24576 :                 get_token();
     774             :             }
     775             :             else
     776             :             {
     777       40960 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_SCOPE, f_lexer->get_input()->get_position());
     778       40960 :                 msg << "scope operator '::' is expected to be followed by an identifier.";
     779             :             }
     780             :             // don't repeat scope (it seems)
     781       65536 :             return;
     782             :         }
     783             :             break;
     784             : 
     785             :         case Node::node_t::NODE_INCREMENT:
     786             :         {
     787       16384 :             Node::pointer_t decrement(f_lexer->get_new_node(Node::node_t::NODE_POST_INCREMENT));
     788       16384 :             decrement->append_child(node);
     789       16384 :             node = decrement;
     790       16384 :             get_token();
     791             :         }
     792       16384 :             break;
     793             : 
     794             :         case Node::node_t::NODE_DECREMENT:
     795             :         {
     796       16384 :             Node::pointer_t decrement(f_lexer->get_new_node(Node::node_t::NODE_POST_DECREMENT));
     797       16384 :             decrement->append_child(node);
     798       16384 :             node = decrement;
     799       16384 :             get_token();
     800             :         }
     801       16384 :             break;
     802             : 
     803             :         case Node::node_t::NODE_OPEN_PARENTHESIS:        // function call arguments
     804             :         {
     805      344068 :             Node::pointer_t left(node);
     806      344068 :             node = f_lexer->get_new_node(Node::node_t::NODE_CALL);
     807      344068 :             node->append_child(left);
     808             : 
     809      344068 :             get_token();
     810             : 
     811             :             // any arguments?
     812      688136 :             Node::pointer_t right;
     813      344068 :             if(f_node->get_type() != Node::node_t::NODE_CLOSE_PARENTHESIS)
     814             :             {
     815      262144 :                 Node::pointer_t list;
     816      262144 :                 list_expression(list, true, false);
     817      262144 :                 if(list->get_type() == Node::node_t::NODE_LIST)
     818             :                 {
     819             :                     // already a list, use it as is
     820       81920 :                     right = list;
     821             :                 }
     822             :                 else
     823             :                 {
     824             :                     // not a list, so put it in a one
     825      180224 :                     right = f_lexer->get_new_node(Node::node_t::NODE_LIST);
     826      180224 :                     right->append_child(list);
     827      262144 :                 }
     828             :             }
     829             :             else
     830             :             {
     831             :                 // an empty list!
     832       81924 :                 right = f_lexer->get_new_node(Node::node_t::NODE_LIST);
     833             :             }
     834      344068 :             node->append_child(right);
     835             : 
     836      344068 :             if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     837             :             {
     838      335876 :                 get_token();
     839             :             }
     840             :             else
     841             :             {
     842        8192 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     843        8192 :                 msg << "')' expected to end the list of arguments.";
     844      344068 :             }
     845             :         }
     846      344068 :             break;
     847             : 
     848             :         case Node::node_t::NODE_OPEN_SQUARE_BRACKET:        // array/property access
     849             :         {
     850       40960 :             Node::pointer_t array(f_lexer->get_new_node(Node::node_t::NODE_ARRAY));
     851       40960 :             array->append_child(node);
     852       40960 :             node = array;
     853             : 
     854       40960 :             get_token();
     855             : 
     856             :             // any arguments?
     857       40960 :             if(f_node->get_type() != Node::node_t::NODE_CLOSE_SQUARE_BRACKET)
     858             :             {
     859       40960 :                 Node::pointer_t right;
     860       40960 :                 list_expression(right, false, false);
     861       40960 :                 node->append_child(right);
     862             :             }
     863             : 
     864       40960 :             if(f_node->get_type() == Node::node_t::NODE_CLOSE_SQUARE_BRACKET)
     865             :             {
     866       32768 :                 get_token();
     867             :             }
     868             :             else
     869             :             {
     870        8192 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_SQUARE_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     871        8192 :                 msg << "']' expected to end the list of element references or declarations.";
     872       40960 :             }
     873             :         }
     874       40960 :             break;
     875             : 
     876             :         default:
     877     5490231 :             return;
     878             : 
     879             :         }
     880     1187844 :     }
     881             : }
     882             : 
     883             : 
     884     6325815 : void Parser::primary_expression(Node::pointer_t& node)
     885             : {
     886     6325815 :     switch(f_node->get_type())
     887             :     {
     888             :     case Node::node_t::NODE_FALSE:
     889             :     case Node::node_t::NODE_FLOAT64:
     890             :     case Node::node_t::NODE_IDENTIFIER:
     891             :     case Node::node_t::NODE_INT64:
     892             :     case Node::node_t::NODE_NULL:
     893             :     case Node::node_t::NODE_REGULAR_EXPRESSION:
     894             :     case Node::node_t::NODE_STRING:
     895             :     case Node::node_t::NODE_THIS:
     896             :     case Node::node_t::NODE_TRUE:
     897             :     case Node::node_t::NODE_UNDEFINED:
     898             :     case Node::node_t::NODE_SUPER:
     899     5965354 :         node = f_node;
     900     5965354 :         get_token();
     901     5965354 :         break;
     902             : 
     903             :     case Node::node_t::NODE_PRIVATE:
     904             :     case Node::node_t::NODE_PROTECTED:
     905             :     case Node::node_t::NODE_PUBLIC:
     906       40960 :         if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
     907             :         {
     908       10240 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
     909       10240 :             msg << "the '" << f_node->get_type_name() << "' operator is only available when extended operators are authorized (use extended_operators;).";
     910             :         }
     911       40960 :         node = f_node;
     912       40960 :         get_token();
     913       40960 :         break;
     914             : 
     915             :     case Node::node_t::NODE_NEW:
     916             :     {
     917       16384 :         node = f_node;
     918       16384 :         get_token();
     919       16384 :         Node::pointer_t object_name;
     920       16384 :         postfix_expression(object_name);
     921       16384 :         node->append_child(object_name);
     922             :     }
     923       16384 :         break;
     924             : 
     925             :     case Node::node_t::NODE_OPEN_PARENTHESIS:        // grouped expressions
     926             :     {
     927       57346 :         get_token();
     928       57346 :         list_expression(node, false, false);
     929             : 
     930             :         // NOTE: the following is important in different cases
     931             :         //       such as (a).field which is dynamic (i.e. we get the
     932             :         //       content of variable a as the name of the object to
     933             :         //       access and thus it is not equivalent to a.field)
     934       57346 :         if(node->get_type() == Node::node_t::NODE_IDENTIFIER)
     935             :         {
     936       16384 :             node->to_videntifier();
     937             :         }
     938       57346 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_PARENTHESIS)
     939             :         {
     940       40962 :             get_token();
     941             :         }
     942             :         else
     943             :         {
     944       16384 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_PARENTHESIS_EXPECTED, f_lexer->get_input()->get_position());
     945       16384 :             msg << "')' expected to match the '('.";
     946             :         }
     947             :     }
     948       57346 :         break;
     949             : 
     950             :     case Node::node_t::NODE_OPEN_SQUARE_BRACKET: // array declaration
     951             :     {
     952       57344 :         node = f_lexer->get_new_node(Node::node_t::NODE_ARRAY_LITERAL);
     953       57344 :         get_token();
     954             : 
     955       57344 :         Node::pointer_t elements;
     956       57344 :         list_expression(elements, false, true);
     957       57344 :         node->append_child(elements);
     958       57344 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_SQUARE_BRACKET)
     959             :         {
     960       49152 :             get_token();
     961             :         }
     962             :         else
     963             :         {
     964        8192 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_SQUARE_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     965        8192 :             msg << "']' expected to match the '[' of this array.";
     966       57344 :         }
     967             :     }
     968       57344 :         break;
     969             : 
     970             :     case Node::node_t::NODE_OPEN_CURVLY_BRACKET: // object declaration
     971             :     {
     972      131072 :         get_token();
     973      131072 :         object_literal_expression(node);
     974      131072 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
     975             :         {
     976       81920 :             get_token();
     977             :         }
     978             :         else
     979             :         {
     980       49152 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     981       49152 :             msg << "'}' expected to match the '{' of this object literal.";
     982             :         }
     983             :     }
     984      131072 :         break;
     985             : 
     986             :     case Node::node_t::NODE_FUNCTION:
     987             :     {
     988       32779 :         get_token();
     989       32779 :         function(node, true);
     990             :     }
     991       32779 :         break;
     992             : 
     993             :     default:
     994       24576 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_EXPRESSION, f_lexer->get_input()->get_position());
     995       24576 :         msg << "unexpected token '" << f_node->get_type_name() << "' found in an expression.";
     996             : 
     997             :         // callers expect to receive a node... give them something
     998       24576 :         node = f_lexer->get_new_node(Node::node_t::NODE_FALSE);
     999       24576 :         break;
    1000             : 
    1001             :     }
    1002     6325815 : }
    1003             : 
    1004             : 
    1005             : 
    1006      131072 : void Parser::object_literal_expression(Node::pointer_t& node)
    1007             : {
    1008      131072 :     Node::pointer_t name;
    1009             :     Node::node_t    type;
    1010             : 
    1011      131072 :     node = f_lexer->get_new_node(Node::node_t::NODE_OBJECT_LITERAL);
    1012             :     for(;;)
    1013             :     {
    1014      425984 :         name = f_lexer->get_new_node(Node::node_t::NODE_NAME);
    1015      425984 :         type = f_node->get_type();
    1016      425984 :         switch(type)
    1017             :         {
    1018             :         case Node::node_t::NODE_OPEN_PARENTHESIS: // (<expr>)::<name> only
    1019             :         {
    1020       24576 :             get_token();  // we MUST skip the '(' otherwise the '::' is eaten from within
    1021       24576 :             Node::pointer_t expr;
    1022       24576 :             expression(expr);
    1023       24576 :             if(expr->get_type() == Node::node_t::NODE_IDENTIFIER)
    1024             :             {
    1025             :                 // an identifier becomes a VIDENTIFIER to remain dynamic.
    1026        8192 :                 expr->to_videntifier();
    1027             :             }
    1028       24576 :             name->append_child(expr);
    1029       24576 :             if(f_node->get_type() != Node::node_t::NODE_CLOSE_PARENTHESIS)
    1030             :             {
    1031        8192 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_FIELD_NAME, f_lexer->get_input()->get_position());
    1032        8192 :                 msg << "')' is expected to close a dynamically named object field.";
    1033             :             }
    1034             :             else
    1035             :             {
    1036       16384 :                 get_token();
    1037       24576 :             }
    1038             :         }
    1039       24576 :             goto and_scope;
    1040             : 
    1041             :         case Node::node_t::NODE_IDENTIFIER:     // <name> or <namespace>::<name>
    1042             :             // NOTE: an IDENTIFIER here remains NODE_IDENTIFIER
    1043             :             //       so it does not look like the previous expression
    1044             :             //       (i.e. an expression literal can be just an
    1045             :             //       identifier but it will be marked as
    1046             :             //       NODE_VIDENTIFIER instead)
    1047      294912 :             name->set_string(f_node->get_string());
    1048             :             /*FALLTHROUGH*/
    1049             :         case Node::node_t::NODE_PRIVATE:        // private::<name> only
    1050             :         case Node::node_t::NODE_PROTECTED:      // protected::<name> only
    1051             :         case Node::node_t::NODE_PUBLIC:         // public::<name> only
    1052      344064 :             get_token();
    1053             : and_scope:
    1054      368640 :             if(f_node->get_type() == Node::node_t::NODE_SCOPE)
    1055             :             {
    1056             :                 // TBD: I do not think that we need a scope operator at all
    1057             :                 //      since we can use the '.' (MEMBER) operator in all cases
    1058             :                 //      I can currently think of (and in JavaScript you are
    1059             :                 //      expected to do so anyway!) therefore I only authorize
    1060             :                 //      it as an extension at the moment
    1061       40960 :                 if(!has_option_set(Options::option_t::OPTION_EXTENDED_OPERATORS))
    1062             :                 {
    1063       10240 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_NOT_ALLOWED, f_lexer->get_input()->get_position());
    1064       10240 :                     msg << "the '::' operator is only available when extended operators are authorized (use extended_operators;).";
    1065             :                 }
    1066             : 
    1067       40960 :                 get_token();
    1068       40960 :                 if(f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
    1069             :                 {
    1070       16384 :                     name->append_child(f_node);
    1071       16384 :                     get_token();
    1072             :                 }
    1073             :                 else
    1074             :                 {
    1075       24576 :                     Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_SCOPE, f_lexer->get_input()->get_position());
    1076       24576 :                     msg << "'::' is expected to always be followed by an identifier.";
    1077             :                 }
    1078             :             }
    1079      327680 :             else if(type != Node::node_t::NODE_IDENTIFIER)
    1080             :             {
    1081       32768 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_FIELD_NAME, f_lexer->get_input()->get_position());
    1082       32768 :                 msg << "'public', 'protected', or 'private' or a dynamic scope cannot be used as a field name, '::' was expected.";
    1083             :             }
    1084      368640 :             break;
    1085             : 
    1086             :         case Node::node_t::NODE_INT64:
    1087             :         case Node::node_t::NODE_FLOAT64:
    1088             :         case Node::node_t::NODE_STRING:
    1089       24576 :             name = f_node;
    1090       24576 :             get_token();
    1091       24576 :             break;
    1092             : 
    1093             :         default:
    1094       32768 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_FIELD, f_lexer->get_input()->get_position());
    1095       32768 :             msg << "the name of a field was expected.";
    1096       32768 :             break;
    1097             : 
    1098             :         }
    1099             : 
    1100      425984 :         if(f_node->get_type() == Node::node_t::NODE_COLON)
    1101             :         {
    1102      352256 :             get_token();
    1103             :         }
    1104             :         else
    1105             :         {
    1106       73728 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_COLON_EXPECTED, f_lexer->get_input()->get_position());
    1107       73728 :             msg << "':' expected after the name of a field.";
    1108             : 
    1109             :             // if we have a closing brace here, the programmer
    1110             :             // tried to end his list improperly; we just
    1111             :             // accept that one silently! (like in C/C++)
    1112      147456 :             if(f_node->get_type() == Node::node_t::NODE_CLOSE_CURVLY_BRACKET
    1113       73728 :             || f_node->get_type() == Node::node_t::NODE_SEMICOLON)
    1114             :             {
    1115             :                 // this is probably the end...
    1116       16384 :                 return;
    1117             :             }
    1118             : 
    1119             :             // if we have a comma here, the programmer
    1120             :             // just forgot a few things...
    1121       57344 :             if(f_node->get_type() == Node::node_t::NODE_COMMA)
    1122             :             {
    1123       24576 :                 get_token();
    1124             :                 // we accept a comma at the end here too!
    1125       49152 :                 if(f_node->get_type() == Node::node_t::NODE_CLOSE_CURVLY_BRACKET
    1126       24576 :                 || f_node->get_type() == Node::node_t::NODE_SEMICOLON)
    1127             :                 {
    1128       16384 :                     return;
    1129             :                 }
    1130        8192 :                 continue;
    1131       32768 :             }
    1132             :         }
    1133             : 
    1134             :         // add the name only now so we have a mostly
    1135             :         // valid tree from here on
    1136      385024 :         node->append_child(name);
    1137             : 
    1138      385024 :         Node::pointer_t set(f_lexer->get_new_node(Node::node_t::NODE_SET));
    1139      671744 :         Node::pointer_t value;
    1140      385024 :         assignment_expression(value);
    1141      385024 :         set->append_child(value);
    1142      385024 :         node->append_child(set);
    1143             : 
    1144             :         // got to the end?
    1145      385024 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
    1146             :         {
    1147       65536 :             return;
    1148             :         }
    1149             : 
    1150      319488 :         if(f_node->get_type() != Node::node_t::NODE_COMMA)
    1151             :         {
    1152       65536 :             if(f_node->get_type() == Node::node_t::NODE_SEMICOLON)
    1153             :             {
    1154       32768 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_COMMA_EXPECTED, f_lexer->get_input()->get_position());
    1155       32768 :                 msg << "'}' expected before the ';' to end an object literal.";
    1156       32768 :                 return;
    1157             :             }
    1158       32768 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_COMMA_EXPECTED, f_lexer->get_input()->get_position());
    1159       32768 :             msg << "',' or '}' expected after the value of a field.";
    1160             :         }
    1161             :         else
    1162             :         {
    1163      253952 :             get_token();
    1164             :         }
    1165      286720 :     }
    1166             :     /*NOTREACHED*/
    1167             : }
    1168             : 
    1169             : 
    1170             : 
    1171             : 
    1172             : 
    1173          63 : }
    1174             : // namespace as2js
    1175             : 
    1176             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.10