📄 gbc_header.c
字号:
/*************************************************************************** header.c Analyzing class description (c) 2000-2004 Beno顃 Minisini <gambas@users.sourceforge.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define _TRANS_HEADER_C#include <stdlib.h>#include <string.h>#include <stdio.h>#include "gb_common.h"#include "gb_error.h"#include "gb_str.h"#include "gb_file.h"#include "gb_table.h"#include "gbc_compile.h"#include "gbc_trans.h"#include "gbc_header.h"/*#define DEBUG*/PRIVATE char *get_num_desc(int num){ static char *num_desc[3] = { "first", "second", "third" }; static char desc[6]; if (num < 1) return NULL; if (num < 4) return num_desc[num - 1]; sprintf(desc, "%dth", num); return desc;}PRIVATE void analyze_function_desc(TRANS_FUNC *func, int flag){ PATTERN *look = JOB->current; TRANS_PARAM *param; bool is_output; bool is_optional = FALSE; TRANS_DECL ttyp; if (!PATTERN_is_identifier(*look)) THROW("Syntax error. Invalid identifier in function name"); func->index = PATTERN_index(*look); look++; if (flag & HF_EVENT) TABLE_copy_symbol_with_prefix(JOB->class->table, func->index, ':', NULL, &func->index); if (!PATTERN_is(*look, RS_LBRA)) THROW("Syntax error. Missing '('"); look++; func->nparam = 0; for(;;) { param = &func->param[func->nparam]; if (PATTERN_is(*look, RS_RBRA)) { look++; break; } if (func->nparam > 0) { if (!PATTERN_is(*look, RS_COMMA)) THROW("Syntax error. Missing ','"); look++; } if (PATTERN_is(*look, RS_3PTS)) { param->type = TYPE_make(T_NULL, 0, 0); look++; if (!PATTERN_is(*look, RS_RBRA)) THROW("Syntax error. '...' must be the last parameter", get_num_desc(func->nparam + 1)); look++; break; } is_output = FALSE; /* Pas de param鑤re en sortie pour l'instant ! if (PATTERN_is(*look, RS_AT)) { is_output = TRUE; look++; } */ if (!(flag & HF_NO_OPT)) { if (PATTERN_is(*look, RS_OPTIONAL)) { look++; is_optional = TRUE; } } if (!PATTERN_is_identifier(*look)) THROW("Syntax error. The &1 parameter is not a valid identifier", get_num_desc(func->nparam + 1)); param->index = PATTERN_index(*look); look++; JOB->current = look; if (!TRANS_type(TT_NOTHING, &ttyp)) THROW("Syntax error. Invalid type description of &1 parameter", get_num_desc(func->nparam + 1)); param->type = ttyp.type; /* if (is_output) TYPE_set_flag(¶m->type, TF_OUTPUT); */ look = JOB->current; if (is_optional) { param->optional = look; for(;;) { if (PATTERN_is(*look, RS_COMMA) || PATTERN_is(*look, RS_RBRA) || PATTERN_is_newline(*look)) break; look++; } JOB->current = look; } func->nparam++; } JOB->current = look;}PRIVATE void header_module_type(void){ const char *ext; /*JOB->class->name = STR_copy(FILE_get_name(JOB->name));*/ ext = FILE_get_ext(JOB->name); if (strcasecmp(ext, "module") == 0) { JOB->is_module = TRUE; JOB->is_form = FALSE; } else if (strcasecmp(ext, "class") == 0) { JOB->is_module = FALSE; JOB->is_form = FALSE; } else if (strcasecmp(ext, "form") == 0) { JOB->is_module = FALSE; JOB->is_form = TRUE; } else THROW("Unknown file extension"); JOB->declared = TRUE;}PRIVATE bool header_event(TRANS_EVENT *event){ PATTERN *look = JOB->current; TRANS_DECL ttyp; if (!PATTERN_is(*look, RS_EVENT)) return FALSE; CLEAR(event); if (JOB->is_module) THROW("A module cannot raise events"); JOB->current++; analyze_function_desc((TRANS_FUNC *)event, HF_NORMAL); if (PATTERN_is(*JOB->current, RS_AS)) { if (!TRANS_type(TT_CAN_SQUARE, &ttyp)) THROW("Syntax error in return type"); event->type = ttyp.type; } TYPE_set_kind(&event->type, TK_EVENT); TYPE_set_flag(&event->type, TF_PUBLIC); return TRUE;}PRIVATE bool header_property(TRANS_PROPERTY *prop){ TRANS_DECL ptype; PATTERN *look = JOB->current; bool is_static = FALSE; bool is_public = TRUE; CLEAR(prop); /* static */ if (JOB->is_module) { is_static = TRUE; } else if (PATTERN_is(*look, RS_STATIC)) { is_static = TRUE; look++; } /* public */ if (PATTERN_is(*look, RS_PUBLIC) || PATTERN_is(*look, RS_PRIVATE)) { is_public = PATTERN_is(*look, RS_PUBLIC); look++; } if (!PATTERN_is(*look, RS_PROPERTY)) return FALSE; look++; JOB->current = look; if (!is_public) THROW("A property must be public"); /* read-only property */ if (PATTERN_is(*JOB->current, RS_READ)) { prop->read = TRUE; JOB->current++; } else prop->read = FALSE; /* property name */ if (!PATTERN_is_identifier(*JOB->current)) THROW("Syntax error. Invalid identifier in property name"); prop->index = PATTERN_index(*JOB->current); JOB->current++; if (!TRANS_type(TT_CAN_SQUARE, &ptype)) THROW("Syntax error. Bad property type"); prop->type = ptype.type; prop->line = JOB->line; TYPE_set_kind(&prop->type, TK_PROPERTY); if (is_static) TYPE_set_flag(&prop->type, TF_STATIC); TYPE_set_flag(&prop->type, TF_PUBLIC); return TRUE;}PRIVATE bool header_extern(TRANS_EXTERN *trans){ PATTERN *look = JOB->current; TRANS_DECL ttyp; CLEAR(trans); if (!PATTERN_is(*look, RS_EXTERN)) return FALSE; JOB->current++; analyze_function_desc((TRANS_FUNC *)trans, HF_NO_3PTS); if (PATTERN_is(*JOB->current, RS_AS)) { if (!TRANS_type(TT_CAN_SQUARE, &ttyp)) THROW("Syntax error in return type"); trans->type = ttyp.type; } if (!PATTERN_is(*JOB->current, RS_IN)) THROW("IN missing"); JOB->current++; if (!PATTERN_is_string(*JOB->current)) THROW("Syntax error in library name"); trans->library = PATTERN_index(*JOB->current); JOB->current++; TYPE_set_kind(&trans->type, TK_EXTERN); return TRUE;}PRIVATE bool header_class(TRANS_DECL *decl){ if (!PATTERN_is(*JOB->current, RS_CLASS)) return FALSE; JOB->current++; if (!PATTERN_is_identifier(*JOB->current)) THROW("Syntax error. CLASS needs an identifier"); decl->index = PATTERN_index(*JOB->current); JOB->current++; return TRUE;}PRIVATE bool header_declaration(TRANS_DECL *decl){ PATTERN *look = JOB->current; bool is_static = FALSE; bool is_public = FALSE; bool is_const = FALSE; /*bool other = FALSE;*/ CLEAR(decl); /* static ! */ if (JOB->is_module) { is_static = TRUE; } else if (PATTERN_is(*look, RS_STATIC)) { is_static = TRUE; look++; } /* public ou private ? */ is_public = JOB->is_module; if (PATTERN_is(*look, RS_PUBLIC)) { is_public = TRUE; look++; } else if (PATTERN_is(*look, RS_PRIVATE)) { is_public = FALSE; look++; } /* const ? */ is_const = FALSE; if (PATTERN_is(*look, RS_CONST)) { /* static const <=> const */ /* if (is_static) return FALSE; */ is_const = TRUE; look++; } if (!PATTERN_is_identifier(*look)) return FALSE; decl->index = PATTERN_index(*look); look++; JOB->current = look; if (!TRANS_type(((!is_const && !is_public) ? (TT_CAN_SQUARE | TT_CAN_ARRAY) : 0) | TT_CAN_NEW, decl)) return FALSE; if (is_static) TYPE_set_flag(&decl->type, TF_STATIC); if (is_public) TYPE_set_flag(&decl->type, TF_PUBLIC); if (is_const) TYPE_set_kind(&decl->type, TK_CONST); else TYPE_set_kind(&decl->type, TK_VARIABLE); look = JOB->current; if (is_const) { if (!PATTERN_is(*look, RS_EQUAL)) THROW("Syntax error. Missing '='"); look++; /* if ((!PATTERN_IS_STRING(*look)) && (!PATTERN_IS_NUMBER(*look))) THROW("Syntax error in constant declaration"); */ TRANS_get_constant_value(decl, *look); look++; } JOB->current = look; return TRUE;}PRIVATE bool header_function(TRANS_FUNC *func){ static HEADER_SPECIAL spec[] = { { "_init", HS_PUBLIC + HS_STATIC + HS_PROCEDURE }, { "_exit", HS_PUBLIC + HS_STATIC + HS_PROCEDURE }, { "_new", HS_PUBLIC + HS_DYNAMIC + HS_PROCEDURE }, { "_free", HS_PUBLIC + HS_DYNAMIC + HS_PROCEDURE }, { "_call", HS_PUBLIC }, { "_get", HS_ERROR }, { "_put", HS_ERROR }, { "_first", HS_ERROR }, { "_next", HS_ERROR }, { "_unknown", HS_ERROR }, { NULL, 0 } }; PATTERN *look = JOB->current; PATTERN pat; TRANS_DECL ttyp; SYMBOL *sym; HEADER_SPECIAL *hsp; bool is_proc = FALSE; bool is_static = FALSE; bool is_public = FALSE; CLEAR(func); /* static ? */ if (JOB->is_module) { is_static = TRUE; } else if (PATTERN_is(*look, RS_STATIC)) { is_static = TRUE; look++; } /* public ou private ? */ is_public = JOB->is_module; if (PATTERN_is(*look, RS_PUBLIC)) { is_public = TRUE; look++; } else if (PATTERN_is(*look, RS_PRIVATE)) { is_public = FALSE; look++; } if (PATTERN_is(*look, RS_PROCEDURE) || PATTERN_is(*look, RS_SUB)) is_proc = TRUE; else if (!PATTERN_is(*look, RS_FUNCTION)) return FALSE; look++; JOB->current = look; analyze_function_desc(func, HF_NORMAL); if (!is_proc) { if (!TRANS_type(TT_CAN_SQUARE, &ttyp)) THROW("Syntax error. Invalid return type"); func->type = ttyp.type; } TYPE_set_kind(&func->type, TK_FUNCTION); if (is_static) TYPE_set_flag(&func->type, TF_STATIC); if (is_public) TYPE_set_flag(&func->type, TF_PUBLIC); /* On v閞ifie les m閠hodes sp閏iales */ sym = TABLE_get_symbol(JOB->class->table, func->index); if (*sym->name == '_') { for (hsp = spec; hsp->name; hsp++) { if (sym->len != strlen(hsp->name)) continue; if (strncmp(sym->name, hsp->name, sym->len)) continue; if (hsp->flag == HS_ERROR) THROW("The special method &1 cannot be implemented", hsp->name); if ((hsp->flag & HS_PUBLIC) && !is_public) THROW("The special method &1 must be public", hsp->name); if ((hsp->flag & HS_STATIC) && !is_static) THROW("The special method &1 must be static", hsp->name); if ((hsp->flag & HS_DYNAMIC) && is_static) THROW("The special method &1 cannot be static", hsp->name); if ((hsp->flag & HS_PROCEDURE) && !is_proc) THROW("The special method &1 cannot be a function", hsp->name); break; } } /* on saute le corps de la fonction */ if (!PATTERN_is_newline(*(JOB->current))) THROW("Syntax error after function declaration"); func->line = PATTERN_index(*(JOB->current)) + 1; /* 鏰 commence
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -