parse.c

00001 /*
00002  * Copyright (c) 2011 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00035 #include <assert.h>
00036 #include <stdlib.h>
00037 #include "cspan.h"
00038 #include "debug.h"
00039 #include "lex.h"
00040 #include "list.h"
00041 #include "mytypes.h"
00042 #include "p_expr.h"
00043 #include "p_type.h"
00044 #include "stree.h"
00045 #include "strtab.h"
00046 #include "symbol.h"
00047 
00048 #include "parse.h"
00049 
00050 /*
00051  * Module and CSI members
00052  */
00053 static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
00054     stree_csi_t *outer_csi);
00055 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi);
00056 
00057 static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi);
00058 
00059 static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi);
00060 static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum);
00061 
00062 static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi);
00063 static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi);
00064 static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi);
00065 static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi);
00066 
00067 static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol);
00068 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse);
00069 
00070 static stree_proc_arg_t *parse_proc_arg(parse_t *parse);
00071 static stree_arg_attr_t *parse_arg_attr(parse_t *parse);
00072 static stree_fun_sig_t *parse_fun_sig(parse_t *parse);
00073 
00074 static void parse_prop_get(parse_t *parse, stree_prop_t *prop);
00075 static void parse_prop_set(parse_t *parse, stree_prop_t *prop);
00076 
00077 /*
00078  * Statements
00079  */
00080 static stree_block_t *parse_block(parse_t *parse);
00081 
00082 static stree_vdecl_t *parse_vdecl(parse_t *parse);
00083 static stree_if_t *parse_if(parse_t *parse);
00084 static stree_switch_t *parse_switch(parse_t *parse);
00085 static stree_while_t *parse_while(parse_t *parse);
00086 static stree_for_t *parse_for(parse_t *parse);
00087 static stree_raise_t *parse_raise(parse_t *parse);
00088 static stree_break_t *parse_break(parse_t *parse);
00089 static stree_return_t *parse_return(parse_t *parse);
00090 static stree_wef_t *parse_wef(parse_t *parse);
00091 static stree_exps_t *parse_exps(parse_t *parse);
00092 
00093 static stree_except_t *parse_except(parse_t *parse);
00094 
00106 void parse_init(parse_t *parse, stree_program_t *prog, struct lex *lex)
00107 {
00108         parse->program = prog;
00109         parse->cur_mod = parse->program->module;
00110         parse->lex = lex;
00111 
00112         parse->error = b_false;
00113         parse->error_bailout = b_false;
00114 
00115         lex_next(parse->lex);
00116 }
00117 
00133 void parse_module(parse_t *parse)
00134 {
00135         stree_csi_t *csi;
00136         stree_enum_t *enum_d;
00137         stree_modm_t *modm;
00138 
00139         while (lcur_lc(parse) != lc_eof && !parse_is_error(parse)) {
00140                 switch (lcur_lc(parse)) {
00141                 case lc_class:
00142                 case lc_struct:
00143                 case lc_interface:
00144                         csi = parse_csi(parse, lcur_lc(parse), NULL);
00145                         modm = stree_modm_new(mc_csi);
00146                         modm->u.csi = csi;
00147 
00148                         list_append(&parse->cur_mod->members, modm);
00149                         break;
00150                 case lc_enum:
00151                         enum_d = parse_enum(parse, NULL);
00152                         modm = stree_modm_new(mc_enum);
00153                         modm->u.enum_d = enum_d;
00154 
00155                         list_append(&parse->cur_mod->members, modm);
00156                         break;
00157                 default:
00158                         lunexpected_error(parse);
00159                         lex_next(parse->lex);
00160                         break;
00161                 }
00162 
00163         }
00164 }
00165 
00173 static stree_csi_t *parse_csi(parse_t *parse, lclass_t dclass,
00174     stree_csi_t *outer_csi)
00175 {
00176         stree_csi_t *csi;
00177         csi_class_t cc;
00178         stree_csimbr_t *csimbr;
00179         stree_symbol_t *symbol;
00180         stree_ident_t *targ_name;
00181         stree_targ_t *targ;
00182         stree_texpr_t *pref;
00183 
00184         switch (dclass) {
00185         case lc_class: cc = csi_class; break;
00186         case lc_struct: cc = csi_struct; break;
00187         case lc_interface: cc = csi_interface; break;
00188         default: assert(b_false);
00189         }
00190 
00191         lskip(parse);
00192 
00193         csi = stree_csi_new(cc);
00194         csi->name = parse_ident(parse);
00195 
00196         list_init(&csi->targ);
00197 
00198         while (lcur_lc(parse) == lc_slash) {
00199                 lskip(parse);
00200                 targ_name = parse_ident(parse);
00201 
00202                 targ = stree_targ_new();
00203                 targ->name = targ_name;
00204 
00205                 list_append(&csi->targ, targ);
00206         }
00207 
00208         symbol = stree_symbol_new(sc_csi);
00209         symbol->u.csi = csi;
00210         symbol->outer_csi = outer_csi;
00211         csi->symbol = symbol;
00212 
00213 #ifdef DEBUG_PARSE_TRACE
00214         printf("parse_csi: csi=%p, csi->name = %p (%s)\n", csi, csi->name,
00215             strtab_get_str(csi->name->sid));
00216 #endif
00217         if (lcur_lc(parse) == lc_colon) {
00218                 /* Inheritance list */
00219                 lskip(parse);
00220 
00221                 while (b_true) {
00222                         pref = parse_texpr(parse);
00223                         if (parse_is_error(parse))
00224                                 break;
00225 
00226                         list_append(&csi->inherit, pref);
00227                         if (lcur_lc(parse) != lc_plus)
00228                                 break;
00229 
00230                         lskip(parse);
00231                 }
00232         }
00233 
00234         lmatch(parse, lc_is);
00235         list_init(&csi->members);
00236 
00237         /* Parse class, struct or interface members. */
00238         while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
00239                 csimbr = parse_csimbr(parse, csi);
00240                 if (csimbr == NULL)
00241                         continue;
00242 
00243                 list_append(&csi->members, csimbr);
00244         }
00245 
00246         lmatch(parse, lc_end);
00247 
00248         if (outer_csi != NULL) {
00249                 switch (outer_csi->cc) {
00250                 case csi_class:
00251                 case csi_struct:
00252                         break;
00253                 case csi_interface:
00254                         cspan_print(csi->name->cspan);
00255                         printf(" Error: CSI declared inside interface.\n");
00256                         parse_note_error(parse);
00257                         /* XXX Free csi */
00258                         return NULL;
00259                 }
00260         }
00261 
00262         return csi;
00263 }
00264 
00272 static stree_csimbr_t *parse_csimbr(parse_t *parse, stree_csi_t *outer_csi)
00273 {
00274         stree_csimbr_t *csimbr;
00275 
00276         stree_csi_t *csi;
00277         stree_ctor_t *ctor;
00278         stree_deleg_t *deleg;
00279         stree_enum_t *enum_d;
00280         stree_fun_t *fun;
00281         stree_var_t *var;
00282         stree_prop_t *prop;
00283 
00284         csimbr = NULL;
00285 
00286         switch (lcur_lc(parse)) {
00287         case lc_class:
00288         case lc_struct:
00289         case lc_interface:
00290                 csi = parse_csi(parse, lcur_lc(parse), outer_csi);
00291                 if (csi != NULL) {
00292                         csimbr = stree_csimbr_new(csimbr_csi);
00293                         csimbr->u.csi = csi;
00294                 }
00295                 break;
00296         case lc_new:
00297                 ctor = parse_ctor(parse, outer_csi);
00298                 if (ctor != NULL) {
00299                         csimbr = stree_csimbr_new(csimbr_ctor);
00300                         csimbr->u.ctor = ctor;
00301                 }
00302                 break;
00303         case lc_deleg:
00304                 deleg = parse_deleg(parse, outer_csi);
00305                 if (deleg != NULL) {
00306                         csimbr = stree_csimbr_new(csimbr_deleg);
00307                         csimbr->u.deleg = deleg;
00308                 }
00309                 break;
00310         case lc_enum:
00311                 enum_d = parse_enum(parse, outer_csi);
00312                 if (enum_d != NULL) {
00313                         csimbr = stree_csimbr_new(csimbr_enum);
00314                         csimbr->u.enum_d = enum_d;
00315                 }
00316                 break;
00317         case lc_fun:
00318                 fun = parse_fun(parse, outer_csi);
00319                 csimbr = stree_csimbr_new(csimbr_fun);
00320                 csimbr->u.fun = fun;
00321                 break;
00322         case lc_var:
00323                 var = parse_var(parse, outer_csi);
00324                 if (var != NULL) {
00325                         csimbr = stree_csimbr_new(csimbr_var);
00326                         csimbr->u.var = var;
00327                 }
00328                 break;
00329         case lc_prop:
00330                 prop = parse_prop(parse, outer_csi);
00331                 csimbr = stree_csimbr_new(csimbr_prop);
00332                 csimbr->u.prop = prop;
00333                 break;
00334         default:
00335                 lunexpected_error(parse);
00336                 lex_next(parse->lex);
00337                 break;
00338         }
00339 
00340         return csimbr;
00341 }
00342 
00349 static stree_ctor_t *parse_ctor(parse_t *parse, stree_csi_t *outer_csi)
00350 {
00351         stree_ctor_t *ctor;
00352         stree_symbol_t *symbol;
00353         cspan_t *cspan;
00354 
00355         ctor = stree_ctor_new();
00356         symbol = stree_symbol_new(sc_ctor);
00357 
00358         symbol->u.ctor = ctor;
00359         symbol->outer_csi = outer_csi;
00360         ctor->symbol = symbol;
00361 
00362         lmatch(parse, lc_new);
00363         cspan = lprev_span(parse);
00364 
00365         /* Fake identifier. */
00366         ctor->name = stree_ident_new();
00367         ctor->name->sid = strtab_get_sid(CTOR_IDENT);
00368         ctor->name->cspan = lprev_span(parse);
00369 
00370 #ifdef DEBUG_PARSE_TRACE
00371         printf("Parsing constructor of CSI '");
00372         symbol_print_fqn(csi_to_symbol(outer_csi));
00373         printf("'.\n");
00374 #endif
00375         ctor->sig = parse_fun_sig(parse);
00376         if (ctor->sig->rtype != NULL) {
00377                 cspan_print(cspan);
00378                 printf(" Error: Constructor of CSI '");
00379                 symbol_print_fqn(csi_to_symbol(outer_csi));
00380                 printf("' has a return type.\n");
00381                 parse_note_error(parse);
00382         }
00383 
00384         /* Parse attributes. */
00385         parse_symbol_attrs(parse, symbol);
00386 
00387         ctor->proc = stree_proc_new();
00388         ctor->proc->outer_symbol = symbol;
00389 
00390         if (lcur_lc(parse) == lc_scolon) {
00391                 lskip(parse);
00392 
00393                 /* This constructor has no body. */
00394                 cspan_print(cspan);
00395                 printf(" Error: Constructor of CSI '");
00396                 symbol_print_fqn(csi_to_symbol(outer_csi));
00397                 printf("' has no body.\n");
00398                 parse_note_error(parse);
00399 
00400                 ctor->proc->body = NULL;
00401         } else {
00402                 lmatch(parse, lc_is);
00403                 ctor->proc->body = parse_block(parse);
00404                 lmatch(parse, lc_end);
00405         }
00406 
00407         switch (outer_csi->cc) {
00408         case csi_class:
00409         case csi_struct:
00410                 break;
00411         case csi_interface:
00412                 cspan_print(ctor->name->cspan);
00413                 printf(" Error: Constructor declared inside interface.\n");
00414                 parse_note_error(parse);
00415                 /* XXX Free ctor */
00416                 return NULL;
00417         }
00418 
00419         return ctor;
00420 }
00421 
00428 static stree_enum_t *parse_enum(parse_t *parse, stree_csi_t *outer_csi)
00429 {
00430         stree_enum_t *enum_d;
00431         stree_symbol_t *symbol;
00432         stree_embr_t *embr;
00433 
00434         enum_d = stree_enum_new();
00435         symbol = stree_symbol_new(sc_enum);
00436 
00437         symbol->u.enum_d = enum_d;
00438         symbol->outer_csi = outer_csi;
00439         enum_d->symbol = symbol;
00440 
00441         lmatch(parse, lc_enum);
00442         enum_d->name = parse_ident(parse);
00443         list_init(&enum_d->members);
00444 
00445 #ifdef DEBUG_PARSE_TRACE
00446         printf("Parse enum '%s'.\n", strtab_get_str(enum_d->name->sid));
00447 #endif
00448         lmatch(parse, lc_is);
00449 
00450         /* Parse enum members. */
00451         while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
00452                 embr = parse_embr(parse, enum_d);
00453                 if (embr == NULL)
00454                         break;
00455 
00456                 list_append(&enum_d->members, embr);
00457         }
00458 
00459         if (list_is_empty(&enum_d->members)) {
00460                 cspan_print(enum_d->name->cspan);
00461                 printf("Error: Enum type '%s' has no members.\n",
00462                     strtab_get_str(enum_d->name->sid));
00463                 parse_note_error(parse);
00464         }
00465 
00466         lmatch(parse, lc_end);
00467 
00468         if (outer_csi != NULL) {
00469                 switch (outer_csi->cc) {
00470                 case csi_class:
00471                 case csi_struct:
00472                         break;
00473                 case csi_interface:
00474                         cspan_print(enum_d->name->cspan);
00475                         printf(" Error: Enum declared inside interface.\n");
00476                         parse_note_error(parse);
00477                         /* XXX Free enum */
00478                         return NULL;
00479                 }
00480         }
00481 
00482         return enum_d;
00483 }
00484 
00492 static stree_embr_t *parse_embr(parse_t *parse, stree_enum_t *outer_enum)
00493 {
00494         stree_embr_t *embr;
00495 
00496         embr = stree_embr_new();
00497         embr->outer_enum = outer_enum;
00498         embr->name = parse_ident(parse);
00499 
00500         lmatch(parse, lc_scolon);
00501 
00502         return embr;
00503 }
00504 
00511 static stree_deleg_t *parse_deleg(parse_t *parse, stree_csi_t *outer_csi)
00512 {
00513         stree_deleg_t *deleg;
00514         stree_symbol_t *symbol;
00515 
00516         deleg = stree_deleg_new();
00517         symbol = stree_symbol_new(sc_deleg);
00518 
00519         symbol->u.deleg = deleg;
00520         symbol->outer_csi = outer_csi;
00521         deleg->symbol = symbol;
00522 
00523         lmatch(parse, lc_deleg);
00524         deleg->name = parse_ident(parse);
00525 
00526 #ifdef DEBUG_PARSE_TRACE
00527         printf("Parsing delegate '%s'.\n", strtab_get_str(deleg->name->sid));
00528 #endif
00529 
00530         deleg->sig = parse_fun_sig(parse);
00531 
00532         /* Parse attributes. */
00533         parse_symbol_attrs(parse, symbol);
00534 
00535         lmatch(parse, lc_scolon);
00536 
00537         switch (outer_csi->cc) {
00538         case csi_class:
00539         case csi_struct:
00540                 break;
00541         case csi_interface:
00542                 cspan_print(deleg->name->cspan);
00543                 printf(" Error: Delegate declared inside interface.\n");
00544                 parse_note_error(parse);
00545                 /* XXX Free deleg */
00546                 return NULL;
00547         }
00548 
00549         return deleg;
00550 }
00551 
00558 static stree_fun_t *parse_fun(parse_t *parse, stree_csi_t *outer_csi)
00559 {
00560         stree_fun_t *fun;
00561         stree_symbol_t *symbol;
00562         bool_t body_expected;
00563 
00564         fun = stree_fun_new();
00565         symbol = stree_symbol_new(sc_fun);
00566 
00567         symbol->u.fun = fun;
00568         symbol->outer_csi = outer_csi;
00569         fun->symbol = symbol;
00570 
00571         lmatch(parse, lc_fun);
00572         fun->name = parse_ident(parse);
00573 
00574 #ifdef DEBUG_PARSE_TRACE
00575         printf("Parsing function '%s'.\n", strtab_get_str(fun->name->sid));
00576 #endif
00577         fun->sig = parse_fun_sig(parse);
00578 
00579         /* Parse attributes. */
00580         parse_symbol_attrs(parse, symbol);
00581 
00582         body_expected = !stree_symbol_has_attr(symbol, sac_builtin) &&
00583             (outer_csi->cc != csi_interface);
00584 
00585         fun->proc = stree_proc_new();
00586         fun->proc->outer_symbol = symbol;
00587 
00588         if (lcur_lc(parse) == lc_scolon) {
00589                 lskip(parse);
00590 
00591                 /* Body not present */
00592                 if (body_expected) {
00593                         cspan_print(fun->name->cspan);
00594                         printf(" Error: Function '");
00595                         symbol_print_fqn(symbol);
00596                         printf("' should have a body.\n");
00597                         parse_note_error(parse);
00598                 }
00599 
00600                 fun->proc->body = NULL;
00601         } else {
00602                 lmatch(parse, lc_is);
00603                 fun->proc->body = parse_block(parse);
00604                 lmatch(parse, lc_end);
00605 
00606                 /* Body present */
00607                 if (!body_expected) {
00608                         cspan_print(fun->name->cspan);
00609                         printf(" Error: Function declaration '");
00610                         symbol_print_fqn(symbol);
00611                         printf("' should not have a body.\n");
00612                         parse_note_error(parse);
00613                 }
00614         }
00615 
00616         return fun;
00617 }
00618 
00625 static stree_var_t *parse_var(parse_t *parse, stree_csi_t *outer_csi)
00626 {
00627         stree_var_t *var;
00628         stree_symbol_t *symbol;
00629 
00630         var = stree_var_new();
00631         symbol = stree_symbol_new(sc_var);
00632         symbol->u.var = var;
00633         symbol->outer_csi = outer_csi;
00634         var->symbol = symbol;
00635 
00636         lmatch(parse, lc_var);
00637         var->name = parse_ident(parse);
00638         lmatch(parse, lc_colon);
00639         var->type =  parse_texpr(parse);
00640 
00641         parse_symbol_attrs(parse, symbol);
00642 
00643         lmatch(parse, lc_scolon);
00644 
00645         switch (outer_csi->cc) {
00646         case csi_class:
00647         case csi_struct:
00648                 break;
00649         case csi_interface:
00650                 cspan_print(var->name->cspan);
00651                 printf(" Error: Variable declared inside interface.\n");
00652                 parse_note_error(parse);
00653                 /* XXX Free var */
00654                 return NULL;
00655         }
00656 
00657         return var;
00658 }
00659 
00666 static stree_prop_t *parse_prop(parse_t *parse, stree_csi_t *outer_csi)
00667 {
00668         stree_prop_t *prop;
00669         stree_symbol_t *symbol;
00670 
00671         stree_ident_t *ident;
00672         stree_proc_arg_t *arg;
00673 
00674         prop = stree_prop_new();
00675         list_init(&prop->args);
00676 
00677         symbol = stree_symbol_new(sc_prop);
00678         symbol->u.prop = prop;
00679         symbol->outer_csi = outer_csi;
00680         prop->symbol = symbol;
00681 
00682         lmatch(parse, lc_prop);
00683 
00684         if (lcur_lc(parse) == lc_self) {
00685                 /* Indexed property set */
00686 
00687                 /* Use some name that is impossible as identifier. */
00688                 ident = stree_ident_new();
00689                 ident->sid = strtab_get_sid(INDEXER_IDENT);
00690                 prop->name = ident;
00691 
00692                 lskip(parse);
00693                 lmatch(parse, lc_lsbr);
00694 
00695                 /* Parse formal parameters. */
00696                 while (!parse_is_error(parse)) {
00697                         arg = parse_proc_arg(parse);
00698                         if (stree_arg_has_attr(arg, aac_packed)) {
00699                                 prop->varg = arg;
00700                                 break;
00701                         } else {
00702                                 list_append(&prop->args, arg);
00703                         }
00704 
00705                         if (lcur_lc(parse) == lc_rsbr)
00706                                 break;
00707 
00708                         lmatch(parse, lc_scolon);
00709                 }
00710 
00711                 lmatch(parse, lc_rsbr);
00712         } else {
00713                 /* Named property */
00714                 prop->name = parse_ident(parse);
00715         }
00716 
00717         lmatch(parse, lc_colon);
00718         prop->type = parse_texpr(parse);
00719 
00720         /* Parse attributes. */
00721         parse_symbol_attrs(parse, symbol);
00722 
00723         lmatch(parse, lc_is);
00724 
00725         while (lcur_lc(parse) != lc_end && !parse_is_error(parse)) {
00726                 switch (lcur_lc(parse)) {
00727                 case lc_get:
00728                         parse_prop_get(parse, prop);
00729                         break;
00730                 case lc_set:
00731                         parse_prop_set(parse, prop);
00732                         break;
00733                 default:
00734                         lunexpected_error(parse);
00735                 }
00736         }
00737 
00738         lmatch(parse, lc_end);
00739 
00740         return prop;
00741 }
00742 
00750 static void parse_symbol_attrs(parse_t *parse, stree_symbol_t *symbol)
00751 {
00752         stree_symbol_attr_t *attr;
00753 
00754         /* Parse attributes. */
00755         while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
00756                 lskip(parse);
00757                 attr = parse_symbol_attr(parse);
00758                 list_append(&symbol->attr, attr);
00759         }
00760 }
00761 
00767 static stree_symbol_attr_t *parse_symbol_attr(parse_t *parse)
00768 {
00769         stree_symbol_attr_t *attr;
00770         symbol_attr_class_t sac;
00771 
00772         /* Make compiler happy. */
00773         sac = 0;
00774 
00775         switch (lcur_lc(parse)) {
00776         case lc_builtin: sac = sac_builtin; break;
00777         case lc_static: sac = sac_static; break;
00778         default:
00779                 cspan_print(lcur_span(parse));
00780                 printf(" Error: Unexpected attribute '");
00781                 lem_print(lcur(parse));
00782                 printf("'.\n");
00783                 parse_note_error(parse);
00784                 break;
00785         }
00786 
00787         lskip(parse);
00788 
00789         attr = stree_symbol_attr_new(sac);
00790         return attr;
00791 }
00792 
00798 static stree_proc_arg_t *parse_proc_arg(parse_t *parse)
00799 {
00800         stree_proc_arg_t *arg;
00801         stree_arg_attr_t *attr;
00802 
00803         arg = stree_proc_arg_new();
00804         arg->name = parse_ident(parse);
00805         lmatch(parse, lc_colon);
00806         arg->type = parse_texpr(parse);
00807 
00808 #ifdef DEBUG_PARSE_TRACE
00809         printf("Parse procedure argument.\n");
00810 #endif
00811         list_init(&arg->attr);
00812 
00813         /* Parse attributes. */
00814         while (lcur_lc(parse) == lc_comma && !parse_is_error(parse)) {
00815                 lskip(parse);
00816                 attr = parse_arg_attr(parse);
00817                 list_append(&arg->attr, attr);
00818         }
00819 
00820         return arg;
00821 }
00822 
00828 static stree_arg_attr_t *parse_arg_attr(parse_t *parse)
00829 {
00830         stree_arg_attr_t *attr;
00831 
00832         if (lcur_lc(parse) != lc_packed) {
00833                 cspan_print(lcur_span(parse));
00834                 printf(" Error: Unexpected attribute '");
00835                 lem_print(lcur(parse));
00836                 printf("'.\n");
00837                 parse_note_error(parse);
00838         }
00839 
00840         lskip(parse);
00841 
00842         attr = stree_arg_attr_new(aac_packed);
00843         return attr;
00844 }
00845 
00851 static stree_fun_sig_t *parse_fun_sig(parse_t *parse)
00852 {
00853         stree_fun_sig_t *sig;
00854         stree_proc_arg_t *arg;
00855 
00856         sig = stree_fun_sig_new();
00857 
00858         lmatch(parse, lc_lparen);
00859 
00860 #ifdef DEBUG_PARSE_TRACE
00861         printf("Parsing function signature.\n");
00862 #endif
00863 
00864         list_init(&sig->args);
00865 
00866         if (lcur_lc(parse) != lc_rparen) {
00867 
00868                 /* Parse formal parameters. */
00869                 while (!parse_is_error(parse)) {
00870                         arg = parse_proc_arg(parse);
00871 
00872                         if (stree_arg_has_attr(arg, aac_packed)) {
00873                                 sig->varg = arg;
00874                                 break;
00875                         } else {
00876                                 list_append(&sig->args, arg);
00877                         }
00878 
00879                         if (lcur_lc(parse) == lc_rparen)
00880                                 break;
00881 
00882                         lmatch(parse, lc_scolon);
00883                 }
00884         }
00885 
00886         lmatch(parse, lc_rparen);
00887 
00888         if (lcur_lc(parse) == lc_colon) {
00889                 lskip(parse);
00890                 sig->rtype = parse_texpr(parse);
00891         } else {
00892                 sig->rtype = NULL;
00893         }
00894 
00895         return sig;
00896 }
00897 
00903 static void parse_prop_get(parse_t *parse, stree_prop_t *prop)
00904 {
00905         cspan_t *cspan;
00906         stree_block_t *block;
00907         stree_proc_t *getter;
00908         bool_t body_expected;
00909 
00910         body_expected = (prop->symbol->outer_csi->cc != csi_interface);
00911 
00912         lskip(parse);
00913         cspan = lprev_span(parse);
00914 
00915         if (prop->getter != NULL) {
00916                 cspan_print(cspan);
00917                 printf(" Error: Duplicate getter.\n");
00918                 parse_note_error(parse);
00919                 return;
00920         }
00921 
00922         if (lcur_lc(parse) == lc_scolon) {
00923                 /* Body not present */
00924                 lskip(parse);
00925                 block = NULL;
00926 
00927                 if (body_expected) {
00928                         cspan_print(prop->name->cspan);
00929                         printf(" Error: Property '");
00930                         symbol_print_fqn(prop->symbol);
00931                         printf("' getter should have "
00932                             "a body.\n");
00933                         parse_note_error(parse);
00934                 }
00935         } else {
00936                 /* Body present */
00937                 lmatch(parse, lc_is);
00938                 block = parse_block(parse);
00939                 lmatch(parse, lc_end);
00940 
00941                 if (!body_expected) {
00942                         cspan_print(prop->name->cspan);
00943                         printf(" Error: Property '");
00944                         symbol_print_fqn(prop->symbol);
00945                         printf("' getter declaration should "
00946                             "not have a body.\n");
00947                         parse_note_error(parse);
00948 
00949                         /* XXX Free block */
00950                         block = NULL;
00951                 }
00952         }
00953 
00954         /* Create getter procedure */
00955         getter = stree_proc_new();
00956         getter->body = block;
00957         getter->outer_symbol = prop->symbol;
00958 
00959         /* Store getter in property. */
00960         prop->getter = getter;
00961 }
00962 
00963 
00969 static void parse_prop_set(parse_t *parse, stree_prop_t *prop)
00970 {
00971         cspan_t *cspan;
00972         stree_block_t *block;
00973         stree_proc_t *setter;
00974         bool_t body_expected;
00975 
00976         body_expected = (prop->symbol->outer_csi->cc != csi_interface);
00977 
00978         lskip(parse);
00979         cspan = lprev_span(parse);
00980 
00981         if (prop->setter != NULL) {
00982                 cspan_print(cspan);
00983                 printf(" Error: Duplicate setter.\n");
00984                 parse_note_error(parse);
00985                 return;
00986         }
00987 
00988         prop->setter_arg = stree_proc_arg_new();
00989         prop->setter_arg->name = parse_ident(parse);
00990         prop->setter_arg->type = prop->type;
00991 
00992         if (lcur_lc(parse) == lc_scolon) {
00993                 /* Body not present */
00994                 lskip(parse);
00995 
00996                 block = NULL;
00997 
00998                 if (body_expected) {
00999                         cspan_print(prop->name->cspan);
01000                         printf(" Error: Property '");
01001                         symbol_print_fqn(prop->symbol);
01002                         printf("' setter should have "
01003                             "a body.\n");
01004                         parse_note_error(parse);
01005                 }
01006         } else {
01007                 /* Body present */
01008                 lmatch(parse, lc_is);
01009                 block = parse_block(parse);
01010                 lmatch(parse, lc_end);
01011 
01012                 if (!body_expected) {
01013                         cspan_print(prop->name->cspan);
01014                         printf(" Error: Property '");
01015                         symbol_print_fqn(prop->symbol);
01016                         printf("' setter declaration should "
01017                             "not have a body.\n");
01018                         parse_note_error(parse);
01019                 }
01020         }
01021 
01022 
01023         /* Create setter procedure */
01024         setter = stree_proc_new();
01025         setter->body = block;
01026         setter->outer_symbol = prop->symbol;
01027 
01028         /* Store setter in property. */
01029         prop->setter = setter;
01030 }
01031 
01037 static stree_block_t *parse_block(parse_t *parse)
01038 {
01039         stree_block_t *block;
01040         stree_stat_t *stat;
01041 
01042         block = stree_block_new();
01043         list_init(&block->stats);
01044 
01045         /* Avoid peeking if there is an error condition. */
01046         if (parse_is_error(parse))
01047                 return block;
01048 
01049         while (terminates_block(lcur_lc(parse)) != b_true &&
01050             !parse_is_error(parse)) {
01051 
01052                 stat = parse_stat(parse);
01053                 list_append(&block->stats, stat);
01054         }
01055 
01056         return block;
01057 }
01058 
01064 stree_stat_t *parse_stat(parse_t *parse)
01065 {
01066         stree_stat_t *stat;
01067 
01068         stree_vdecl_t *vdecl_s;
01069         stree_if_t *if_s;
01070         stree_switch_t *switch_s;
01071         stree_while_t *while_s;
01072         stree_for_t *for_s;
01073         stree_raise_t *raise_s;
01074         stree_break_t *break_s;
01075         stree_return_t *return_s;
01076         stree_wef_t *wef_s;
01077         stree_exps_t *exp_s;
01078 
01079 #ifdef DEBUG_PARSE_TRACE
01080         printf("Parse statement.\n");
01081 #endif
01082         switch (lcur_lc(parse)) {
01083         case lc_var:
01084                 vdecl_s = parse_vdecl(parse);
01085                 stat = stree_stat_new(st_vdecl);
01086                 stat->u.vdecl_s = vdecl_s;
01087                 break;
01088         case lc_if:
01089                 if_s = parse_if(parse);
01090                 stat = stree_stat_new(st_if);
01091                 stat->u.if_s = if_s;
01092                 break;
01093         case lc_switch:
01094                 switch_s = parse_switch(parse);
01095                 stat = stree_stat_new(st_switch);
01096                 stat->u.switch_s = switch_s;
01097                 break;
01098         case lc_while:
01099                 while_s = parse_while(parse);
01100                 stat = stree_stat_new(st_while);
01101                 stat->u.while_s = while_s;
01102                 break;
01103         case lc_for:
01104                 for_s = parse_for(parse);
01105                 stat = stree_stat_new(st_for);
01106                 stat->u.for_s = for_s;
01107                 break;
01108         case lc_raise:
01109                 raise_s = parse_raise(parse);
01110                 stat = stree_stat_new(st_raise);
01111                 stat->u.raise_s = raise_s;
01112                 break;
01113         case lc_break:
01114                 break_s = parse_break(parse);
01115                 stat = stree_stat_new(st_break);
01116                 stat->u.break_s = break_s;
01117                 break;
01118         case lc_return:
01119                 return_s = parse_return(parse);
01120                 stat = stree_stat_new(st_return);
01121                 stat->u.return_s = return_s;
01122                 break;
01123         case lc_do:
01124         case lc_with:
01125                 wef_s = parse_wef(parse);
01126                 stat = stree_stat_new(st_wef);
01127                 stat->u.wef_s = wef_s;
01128                 break;
01129         default:
01130                 exp_s = parse_exps(parse);
01131                 stat = stree_stat_new(st_exps);
01132                 stat->u.exp_s = exp_s;
01133                 break;
01134         }
01135 
01136 #ifdef DEBUG_PARSE_TRACE
01137         printf("Parsed statement %p\n", stat);
01138 #endif
01139         return stat;
01140 }
01141 
01147 static stree_vdecl_t *parse_vdecl(parse_t *parse)
01148 {
01149         stree_vdecl_t *vdecl;
01150 
01151         vdecl = stree_vdecl_new();
01152 
01153         lmatch(parse, lc_var);
01154         vdecl->name = parse_ident(parse);
01155         lmatch(parse, lc_colon);
01156         vdecl->type = parse_texpr(parse);
01157 
01158         if (lcur_lc(parse) == lc_assign) {
01159                 lskip(parse);
01160                 (void) parse_expr(parse);
01161         }
01162 
01163         lmatch(parse, lc_scolon);
01164 
01165 #ifdef DEBUG_PARSE_TRACE
01166         printf("Parsed vdecl for '%s'\n", strtab_get_str(vdecl->name->sid));
01167         printf("vdecl = %p, vdecl->name = %p, sid=%d\n",
01168             vdecl, vdecl->name, vdecl->name->sid);
01169 #endif
01170         return vdecl;
01171 }
01172 
01178 static stree_if_t *parse_if(parse_t *parse)
01179 {
01180         stree_if_t *if_s;
01181         stree_if_clause_t *if_c;
01182 
01183 #ifdef DEBUG_PARSE_TRACE
01184         printf("Parse 'if' statement.\n");
01185 #endif
01186         if_s = stree_if_new();
01187         list_init(&if_s->if_clauses);
01188 
01189         /* Parse @c if clause. */
01190         lmatch(parse, lc_if);
01191 
01192         if_c = stree_if_clause_new();
01193         if_c->cond = parse_expr(parse);
01194         lmatch(parse, lc_then);
01195         if_c->block = parse_block(parse);
01196 
01197         list_append(&if_s->if_clauses, if_c);
01198 
01199         /* Parse @c elif clauses. */
01200         while (lcur_lc(parse) == lc_elif) {
01201                 lskip(parse);
01202                 if_c = stree_if_clause_new();
01203                 if_c->cond = parse_expr(parse);
01204                 lmatch(parse, lc_then);
01205                 if_c->block = parse_block(parse);
01206 
01207                 list_append(&if_s->if_clauses, if_c);
01208         }
01209 
01210         /* Parse @c else clause. */
01211         if (lcur_lc(parse) == lc_else) {
01212                 lskip(parse);
01213                 if_s->else_block = parse_block(parse);
01214         } else {
01215                 if_s->else_block = NULL;
01216         }
01217 
01218         lmatch(parse, lc_end);
01219         return if_s;
01220 }
01221 
01227 static stree_switch_t *parse_switch(parse_t *parse)
01228 {
01229         stree_switch_t *switch_s;
01230         stree_when_t *when_c;
01231         stree_expr_t *expr;
01232 
01233 #ifdef DEBUG_PARSE_TRACE
01234         printf("Parse 'switch' statement.\n");
01235 #endif
01236         lmatch(parse, lc_switch);
01237 
01238         switch_s = stree_switch_new();
01239         list_init(&switch_s->when_clauses);
01240 
01241         switch_s->expr = parse_expr(parse);
01242         lmatch(parse, lc_is);
01243 
01244         /* Parse @c when clauses. */
01245         while (lcur_lc(parse) == lc_when) {
01246                 lskip(parse);
01247                 when_c = stree_when_new();
01248                 list_init(&when_c->exprs);
01249                 while (b_true) {
01250                         expr = parse_expr(parse);
01251                         list_append(&when_c->exprs, expr);
01252                         if (lcur_lc(parse) != lc_comma)
01253                                 break;
01254                         lskip(parse);
01255                 }
01256 
01257                 lmatch(parse, lc_do);
01258                 when_c->block = parse_block(parse);
01259 
01260                 list_append(&switch_s->when_clauses, when_c);
01261         }
01262 
01263         /* Parse @c else clause. */
01264         if (lcur_lc(parse) == lc_else) {
01265                 lskip(parse);
01266                 lmatch(parse, lc_do);
01267                 switch_s->else_block = parse_block(parse);
01268         } else {
01269                 switch_s->else_block = NULL;
01270         }
01271 
01272         lmatch(parse, lc_end);
01273         return switch_s;
01274 }
01275 
01280 static stree_while_t *parse_while(parse_t *parse)
01281 {
01282         stree_while_t *while_s;
01283 
01284 #ifdef DEBUG_PARSE_TRACE
01285         printf("Parse 'while' statement.\n");
01286 #endif
01287         while_s = stree_while_new();
01288 
01289         lmatch(parse, lc_while);
01290         while_s->cond = parse_expr(parse);
01291         lmatch(parse, lc_do);
01292         while_s->body = parse_block(parse);
01293         lmatch(parse, lc_end);
01294 
01295         return while_s;
01296 }
01297 
01303 static stree_for_t *parse_for(parse_t *parse)
01304 {
01305         stree_for_t *for_s;
01306 
01307 #ifdef DEBUG_PARSE_TRACE
01308         printf("Parse 'for' statement.\n");
01309 #endif
01310         for_s = stree_for_new();
01311 
01312         lmatch(parse, lc_for);
01313         lmatch(parse, lc_ident);
01314         lmatch(parse, lc_colon);
01315         (void) parse_texpr(parse);
01316         lmatch(parse, lc_in);
01317         (void) parse_expr(parse);
01318         lmatch(parse, lc_do);
01319         for_s->body = parse_block(parse);
01320         lmatch(parse, lc_end);
01321 
01322         return for_s;
01323 }
01324 
01329 static stree_raise_t *parse_raise(parse_t *parse)
01330 {
01331         stree_raise_t *raise_s;
01332 
01333 #ifdef DEBUG_PARSE_TRACE
01334         printf("Parse 'raise' statement.\n");
01335 #endif
01336         raise_s = stree_raise_new();
01337         lmatch(parse, lc_raise);
01338         raise_s->expr = parse_expr(parse);
01339         lmatch(parse, lc_scolon);
01340 
01341         return raise_s;
01342 }
01343 
01349 static stree_break_t *parse_break(parse_t *parse)
01350 {
01351         stree_break_t *break_s;
01352 
01353 #ifdef DEBUG_PARSE_TRACE
01354         printf("Parse 'break' statement.\n");
01355 #endif
01356         break_s = stree_break_new();
01357 
01358         lmatch(parse, lc_break);
01359         lmatch(parse, lc_scolon);
01360 
01361         return break_s;
01362 }
01363 
01369 static stree_return_t *parse_return(parse_t *parse)
01370 {
01371         stree_return_t *return_s;
01372 
01373 #ifdef DEBUG_PARSE_TRACE
01374         printf("Parse 'return' statement.\n");
01375 #endif
01376         return_s = stree_return_new();
01377 
01378         lmatch(parse, lc_return);
01379 
01380         if (lcur_lc(parse) != lc_scolon)
01381                 return_s->expr = parse_expr(parse);
01382 
01383         lmatch(parse, lc_scolon);
01384 
01385         return return_s;
01386 }
01387 
01388 /* Parse @c with-except-finally statement.
01389  *
01390  * @param parse         Parser object.
01391  * @return              New syntax tree node.
01392  */
01393 static stree_wef_t *parse_wef(parse_t *parse)
01394 {
01395         stree_wef_t *wef_s;
01396         stree_except_t *except_c;
01397 
01398 #ifdef DEBUG_PARSE_TRACE
01399         printf("Parse WEF statement.\n");
01400 #endif
01401         wef_s = stree_wef_new();
01402         list_init(&wef_s->except_clauses);
01403 
01404         if (lcur_lc(parse) == lc_with) {
01405                 lmatch(parse, lc_with);
01406                 lmatch(parse, lc_ident);
01407                 lmatch(parse, lc_colon);
01408                 (void) parse_texpr(parse);
01409                 lmatch(parse, lc_assign);
01410                 (void) parse_expr(parse);
01411         }
01412 
01413         lmatch(parse, lc_do);
01414         wef_s->with_block = parse_block(parse);
01415 
01416         while (lcur_lc(parse) == lc_except && !parse_is_error(parse)) {
01417                 except_c = parse_except(parse);
01418                 list_append(&wef_s->except_clauses, except_c);
01419         }
01420 
01421         if (lcur_lc(parse) == lc_finally) {
01422                 lmatch(parse, lc_finally);
01423                 lmatch(parse, lc_do);
01424                 wef_s->finally_block = parse_block(parse);
01425         } else {
01426                 wef_s->finally_block = NULL;
01427         }
01428 
01429         lmatch(parse, lc_end);
01430 
01431         return wef_s;
01432 }
01433 
01434 /* Parse expression statement.
01435  *
01436  * @param parse         Parser object.
01437  * @return              New syntax tree node.
01438  */
01439 static stree_exps_t *parse_exps(parse_t *parse)
01440 {
01441         stree_expr_t *expr;
01442         stree_exps_t *exps;
01443 
01444 #ifdef DEBUG_PARSE_TRACE
01445         printf("Parse expression statement.\n");
01446 #endif
01447         expr = parse_expr(parse);
01448         lmatch(parse, lc_scolon);
01449 
01450         exps = stree_exps_new();
01451         exps->expr = expr;
01452 
01453         return exps;
01454 }
01455 
01456 /* Parse @c except clause.
01457  *
01458  * @param parse         Parser object.
01459  * @return              New syntax tree node.
01460  */
01461 static stree_except_t *parse_except(parse_t *parse)
01462 {
01463         stree_except_t *except_c;
01464 
01465 #ifdef DEBUG_PARSE_TRACE
01466         printf("Parse 'except' statement.\n");
01467 #endif
01468         except_c = stree_except_new();
01469 
01470         lmatch(parse, lc_except);
01471         except_c->evar = parse_ident(parse);
01472         lmatch(parse, lc_colon);
01473         except_c->etype = parse_texpr(parse);
01474         lmatch(parse, lc_do);
01475 
01476         except_c->block = parse_block(parse);
01477 
01478         return except_c;
01479 }
01480 
01486 stree_ident_t *parse_ident(parse_t *parse)
01487 {
01488         stree_ident_t *ident;
01489 
01490 #ifdef DEBUG_PARSE_TRACE
01491         printf("Parse identifier.\n");
01492 #endif
01493         lcheck(parse, lc_ident);
01494         ident = stree_ident_new();
01495         ident->sid = lcur(parse)->u.ident.sid;
01496         ident->cspan = lcur_span(parse);
01497         lskip(parse);
01498 
01499         return ident;
01500 }
01501 
01506 void parse_raise_error(parse_t *parse)
01507 {
01508         parse->error = b_true;
01509         parse->error_bailout = b_true;
01510 }
01511 
01516 void parse_note_error(parse_t *parse)
01517 {
01518         parse->error = b_true;
01519 }
01520 
01525 bool_t parse_is_error(parse_t *parse)
01526 {
01527         return parse->error_bailout;
01528 }
01529 
01536 void parse_recover_error(parse_t *parse)
01537 {
01538         assert(parse->error == b_true);
01539         assert(parse->error_bailout == b_true);
01540 
01541         parse->error_bailout = b_false;
01542 }
01543 
01550 lem_t *lcur(parse_t *parse)
01551 {
01552 #ifdef DEBUG_LPARSE_TRACE
01553         printf("lcur()\n");
01554 #endif
01555         return lex_get_current(parse->lex);
01556 }
01557 
01563 lclass_t lcur_lc(parse_t *parse)
01564 {
01565         lem_t *lem;
01566 
01567         /*
01568          * This allows us to skip error checking in many places. If there is an
01569          * active error, lcur_lc() returns lc_invalid without reading input.
01570          *
01571          * Without this measure we would have to check for error all the time
01572          * or risk requiring extra input from the user (in interactive mode)
01573          * before actually bailing out from the parser.
01574          */
01575         if (parse_is_error(parse))
01576                 return lc_invalid;
01577 
01578         lem = lcur(parse);
01579         return lem->lclass;
01580 }
01581 
01588 cspan_t *lcur_span(parse_t *parse)
01589 {
01590         lem_t *lem;
01591 
01592         if (parse_is_error(parse))
01593                 return NULL;
01594 
01595         lem = lcur(parse);
01596         return lem->cspan;
01597 }
01598 
01606 cspan_t *lprev_span(parse_t *parse)
01607 {
01608         lem_t *lem;
01609 
01610         if (parse_is_error(parse))
01611                 return NULL;
01612 
01613         lem = lex_peek_prev(parse->lex);
01614         if (lem == NULL)
01615                 return NULL;
01616 
01617         return lem->cspan;
01618 }
01619 
01624 void lskip(parse_t *parse)
01625 {
01626 #ifdef DEBUG_LPARSE_TRACE
01627         printf("lskip()\n");
01628 #endif
01629         lex_next(parse->lex);
01630 }
01631 
01640 void lcheck(parse_t *parse, lclass_t lc)
01641 {
01642 #ifdef DEBUG_LPARSE_TRACE
01643         printf("lcheck(");
01644         lclass_print(lc);
01645         printf(")\n");
01646 #endif
01647         if (lcur(parse)->lclass != lc) {
01648                 lem_print_coords(lcur(parse));
01649                 printf(" Error: expected '"); lclass_print(lc);
01650                 printf("', got '"); lem_print(lcur(parse));
01651                 printf("'.\n");
01652                 parse_raise_error(parse);
01653         }
01654 }
01655 
01664 void lmatch(parse_t *parse, lclass_t lc)
01665 {
01666 #ifdef DEBUG_LPARSE_TRACE
01667         printf("lmatch(");
01668         lclass_print(lc);
01669         printf(")\n");
01670 #endif
01671         /*
01672          * This allows us to skip error checking in many places. If there is an
01673          * active error, lmatch() does nothing (similar to parse_block(), etc.
01674          *
01675          * Without this measure we would have to check for error all the time
01676          * or risk requiring extra input from the user (in interactive mode)
01677          * before actually bailing out from the parser.
01678          */
01679         if (parse_is_error(parse))
01680                 return;
01681 
01682         lcheck(parse, lc);
01683         lskip(parse);
01684 }
01685 
01690 void lunexpected_error(parse_t *parse)
01691 {
01692         lem_print_coords(lcur(parse));
01693         printf(" Error: unexpected token '");
01694         lem_print(lcur(parse));
01695         printf("'.\n");
01696         parse_raise_error(parse);
01697 }
01698 
01706 bool_t terminates_block(lclass_t lclass)
01707 {
01708         switch (lclass) {
01709         case lc_elif:
01710         case lc_else:
01711         case lc_end:
01712         case lc_except:
01713         case lc_finally:
01714         case lc_when:
01715                 return b_true;
01716         default:
01717                 return b_false;
01718         }
01719 }

Generated on Thu Jun 2 07:45:42 2011 for HelenOS/USB by  doxygen 1.4.7