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

          Line data    Source code
       1             : /* parser_class.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 CLASS  ***************************************************/
      47             : /**********************************************************************/
      48             : /**********************************************************************/
      49             : 
      50      122895 : void Parser::class_declaration(Node::pointer_t& node, Node::node_t type)
      51             : {
      52      122895 :     node = f_lexer->get_new_node(type);
      53             : 
      54             :     // *** NAME ***
      55      122895 :     if(f_node->get_type() != Node::node_t::NODE_IDENTIFIER)
      56             :     {
      57       32772 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_CLASS, f_lexer->get_input()->get_position());
      58       32772 :         msg << "the name of the class is expected after the keyword 'class'.";
      59             : 
      60       32772 :         switch(f_node->get_type())
      61             :         {
      62             :         case Node::node_t::NODE_EXTENDS:
      63             :         case Node::node_t::NODE_IMPLEMENTS:
      64             :         case Node::node_t::NODE_OPEN_CURVLY_BRACKET:
      65             :         //case Node::node_t::NODE_SEMICOLON: -- not necessary here
      66       32772 :             break;
      67             : 
      68             :         default:
      69      155667 :             return;
      70             : 
      71       32772 :         }
      72             :     }
      73             :     else
      74             :     {
      75       90123 :         node->set_string(f_node->get_string());
      76       90123 :         get_token();
      77             :     }
      78             : 
      79             :     // *** INHERITANCE ***
      80      376878 :     while(f_node->get_type() == Node::node_t::NODE_EXTENDS
      81      188439 :        || f_node->get_type() == Node::node_t::NODE_IMPLEMENTS)
      82             :     {
      83       65544 :         Node::pointer_t inherits(f_node);
      84       65544 :         node->append_child(inherits);
      85             : 
      86       65544 :         get_token();
      87             : 
      88       65544 :         Node::pointer_t expr;
      89       65544 :         expression(expr);
      90             :         // TODO: EXTENDS and IMPLEMENTS do not accept assignments.
      91             :         //       verify that expr does not include any
      92       65544 :         inherits->append_child(expr);
      93       65544 :     }
      94             : 
      95      122895 :     if(f_node->get_type() == Node::node_t::NODE_OPEN_CURVLY_BRACKET)
      96             :     {
      97      106509 :         get_token();
      98             : 
      99             :         // *** DECLARATION ***
     100      106509 :         if(f_node->get_type() != Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
     101             :         {
     102       98316 :             Node::pointer_t directive_list_node;
     103       98316 :             directive_list(directive_list_node);
     104       98316 :             node->append_child(directive_list_node);
     105             :         }
     106             :         else
     107             :         {
     108             :             // this is important to distinguish an empty node from
     109             :             // a forward declaration
     110        8193 :             Node::pointer_t empty_node(f_lexer->get_new_node(Node::node_t::NODE_EMPTY));
     111        8193 :             node->append_child(empty_node);
     112             :         }
     113             : 
     114      106509 :         if(f_node->get_type() == Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
     115             :         {
     116       98316 :             get_token();
     117             :         }
     118             :         else
     119             :         {
     120        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     121      106509 :             msg << "'}' expected to close the 'class' definition.";
     122             :         }
     123             :     }
     124       16386 :     else if(f_node->get_type() != Node::node_t::NODE_SEMICOLON)
     125             :     {
     126        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     127        8193 :         msg << "'{' expected to start the 'class' definition.";
     128             :     }
     129             :     // else -- accept empty class definitions (for typedef's and forward declaration)
     130             : }
     131             : 
     132             : 
     133             : 
     134             : 
     135             : /**********************************************************************/
     136             : /**********************************************************************/
     137             : /***  PARSER ENUM  ****************************************************/
     138             : /**********************************************************************/
     139             : /**********************************************************************/
     140             : 
     141      122895 : void Parser::enum_declaration(Node::pointer_t& node)
     142             : {
     143      122895 :     node = f_lexer->get_new_node(Node::node_t::NODE_ENUM);
     144             : 
     145      122895 :     bool const is_class(f_node->get_type() == Node::node_t::NODE_CLASS);
     146      122895 :     if(is_class)
     147             :     {
     148       32772 :         get_token();
     149       32772 :         node->set_flag(Node::flag_t::NODE_ENUM_FLAG_CLASS, true);
     150             :     }
     151             : 
     152             :     // enumerations can be unamed
     153      122895 :     if(f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
     154             :     {
     155      114702 :         node->set_string(f_node->get_string());
     156      114702 :         get_token();
     157             :     }
     158             : 
     159             :     // in case the name was not specified, we can still have a type
     160      122895 :     if(f_node->get_type() == Node::node_t::NODE_COLON)
     161             :     {
     162       40965 :         get_token();
     163       40965 :         Node::pointer_t expr;
     164       40965 :         expression(expr);
     165       81930 :         Node::pointer_t type(f_lexer->get_new_node(Node::node_t::NODE_TYPE));
     166       40965 :         type->append_child(expr);
     167       81930 :         node->append_child(type);
     168             :     }
     169             : 
     170      122895 :     if(f_node->get_type() != Node::node_t::NODE_OPEN_CURVLY_BRACKET)
     171             :     {
     172       24579 :         if(f_node->get_type() == Node::node_t::NODE_SEMICOLON)
     173             :         {
     174             :             // empty enumeration (i.e. forward declaration)
     175       16386 :             if(node->get_string().empty())
     176             :             {
     177        8193 :                 Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_ENUM, f_lexer->get_input()->get_position());
     178        8193 :                 msg << "a forward enumeration must be named.";
     179             :             }
     180       16386 :             return;
     181             :         }
     182        8193 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     183        8193 :         msg << "'{' expected to start the 'enum' definition.";
     184       24579 :         return;
     185             :     }
     186             : 
     187       98316 :     get_token();
     188             : 
     189       98316 :     Node::pointer_t previous(f_lexer->get_new_node(Node::node_t::NODE_NULL));
     190      770142 :     while(f_node->get_type() != Node::node_t::NODE_CLOSE_CURVLY_BRACKET
     191      303141 :        && f_node->get_type() != Node::node_t::NODE_SEMICOLON
     192      688212 :        && f_node->get_type() != Node::node_t::NODE_EOF)
     193             :     {
     194      286755 :         if(f_node->get_type() == Node::node_t::NODE_COMMA)
     195             :         {
     196             :             // skip to the next token
     197       16386 :             get_token();
     198             : 
     199       16386 :             Message msg(message_level_t::MESSAGE_LEVEL_WARNING, err_code_t::AS_ERR_UNEXPECTED_PUNCTUATION, f_lexer->get_input()->get_position());
     200       16386 :             msg << "',' unexpected without a name.";
     201       16386 :             continue;
     202             :         }
     203      270369 :         String current_name("null");
     204      540738 :         Node::pointer_t entry(f_lexer->get_new_node(Node::node_t::NODE_VARIABLE));
     205      270369 :         node->append_child(entry);
     206      270369 :         if(f_node->get_type() == Node::node_t::NODE_IDENTIFIER)
     207             :         {
     208      245790 :             entry->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_CONST, true);
     209      245790 :             entry->set_flag(Node::flag_t::NODE_VARIABLE_FLAG_ENUM, true);
     210      245790 :             current_name = f_node->get_string();
     211      245790 :             entry->set_string(current_name);
     212      245790 :             get_token();
     213             :         }
     214             :         else
     215             :         {
     216       24579 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_ENUM, f_lexer->get_input()->get_position());
     217       24579 :             msg << "each 'enum' entry needs to include an identifier.";
     218       49158 :             if(f_node->get_type() != Node::node_t::NODE_ASSIGNMENT
     219        8193 :             && f_node->get_type() != Node::node_t::NODE_COMMA
     220       32772 :             && f_node->get_type() != Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
     221             :             {
     222             :                 // skip that token otherwise we'd loop forever doing
     223             :                 // nothing more than generate errors
     224        8193 :                 get_token();
     225       24579 :             }
     226             :         }
     227      270369 :         Node::pointer_t expr;
     228      270369 :         if(f_node->get_type() == Node::node_t::NODE_ASSIGNMENT)
     229             :         {
     230      114702 :             get_token();
     231      114702 :             conditional_expression(expr, false);
     232             :         }
     233      155667 :         else if(previous->get_type() == Node::node_t::NODE_NULL)
     234             :         {
     235             :             // very first time
     236       65544 :             expr = f_lexer->get_new_node(Node::node_t::NODE_INT64);
     237             :             //expr->set_int64(0); -- this is the default
     238             :         }
     239             :         else
     240             :         {
     241       90123 :             expr = f_lexer->get_new_node(Node::node_t::NODE_ADD);
     242       90123 :             expr->append_child(previous); // left handside
     243       90123 :             Node::pointer_t one(f_lexer->get_new_node(Node::node_t::NODE_INT64));
     244       90123 :             Int64 int64_one;
     245       90123 :             int64_one.set(1);
     246       90123 :             one->set_int64(int64_one);
     247       90123 :             expr->append_child(one);
     248             :         }
     249             : 
     250      540738 :         Node::pointer_t set(f_lexer->get_new_node(Node::node_t::NODE_SET));
     251      270369 :         set->append_child(expr);
     252      270369 :         entry->append_child(set);
     253             : 
     254      270369 :         previous = f_lexer->get_new_node(Node::node_t::NODE_IDENTIFIER);
     255      270369 :         previous->set_string(current_name);
     256             : 
     257      270369 :         if(f_node->get_type() == Node::node_t::NODE_COMMA)
     258             :         {
     259      155667 :             get_token();
     260             :         }
     261      229404 :         else if(f_node->get_type() != Node::node_t::NODE_CLOSE_CURVLY_BRACKET
     262      114702 :              && f_node->get_type() != Node::node_t::NODE_SEMICOLON)
     263             :         {
     264       24579 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_COMMA_EXPECTED, f_lexer->get_input()->get_position());
     265       24579 :             msg << "',' expected between enumeration elements.";
     266             :         }
     267      270369 :     }
     268             : 
     269       98316 :     if(f_node->get_type() == Node::node_t::NODE_CLOSE_CURVLY_BRACKET)
     270             :     {
     271       81930 :         get_token();
     272             :     }
     273             :     else
     274             :     {
     275       16386 :         Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_CURVLY_BRACKETS_EXPECTED, f_lexer->get_input()->get_position());
     276       16386 :         msg << "'}' expected to close the 'enum' definition.";
     277      122895 :     }
     278             : }
     279             : 
     280             : 
     281       73737 : void Parser::contract_declaration(Node::pointer_t& node, Node::node_t type)
     282             : {
     283       73737 :     node = f_lexer->get_new_node(type);
     284             : 
     285             :     // contract are labeled expressions
     286             :     for(;;)
     287             :     {
     288      131088 :         Node::pointer_t label(f_lexer->get_new_node(Node::node_t::NODE_LABEL));
     289      131088 :         node->append_child(label);
     290      131088 :         if(f_node->get_type() != Node::node_t::NODE_IDENTIFIER)
     291             :         {
     292        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_INVALID_LABEL, f_lexer->get_input()->get_position());
     293        8193 :             msg << "'" << node->get_type_name() << "' must be followed by a list of labeled expressions.";
     294             :         }
     295             :         else
     296             :         {
     297      122895 :             label->set_string(f_node->get_string());
     298             :             // skip the identifier
     299      122895 :             get_token();
     300             :         }
     301      131088 :         if(f_node->get_type() != Node::node_t::NODE_COLON)
     302             :         {
     303        8193 :             Message msg(message_level_t::MESSAGE_LEVEL_ERROR, err_code_t::AS_ERR_COLON_EXPECTED, f_lexer->get_input()->get_position());
     304        8193 :             msg << "the '" << node->get_type_name() << "' label must be followed by a colon (:).";
     305             :         }
     306             :         else
     307             :         {
     308             :             // skip the colon
     309      122895 :             get_token();
     310             :         }
     311      131088 :         Node::pointer_t expr;
     312      131088 :         conditional_expression(expr, false);
     313      131088 :         label->append_child(expr);
     314      131088 :         if(f_node->get_type() != Node::node_t::NODE_COMMA)
     315             :         {
     316       73737 :             break;
     317             :         }
     318             :         // skip the comma
     319      131088 :         get_token();
     320       57351 :     }
     321       73737 : }
     322             : 
     323             : 
     324          20 : }
     325             : // namespace as2js
     326             : 
     327             : // vim: ts=4 sw=4 et

Generated by: LCOV version 1.9