diff --git a/compiler/compiler.c b/compiler/compiler.c index 6f3277c..f36400d 100644 --- a/compiler/compiler.c +++ b/compiler/compiler.c @@ -31,6 +31,9 @@ void add_definitions_to_compiler(DefinitionList *definitions) compiler->func_definition_list = chain_func_definition_list( compiler->func_definition_list, pos->definition->u.func_d); break; + case DECLARATION_DEFINITION: + compiler->declaration_list = chain_declaration_definition_list( + compiler->declaration_list, pos->definition->u.declaration); default: break; } diff --git a/compiler/create.c b/compiler/create.c index 6ae0bec..90c5fd3 100644 --- a/compiler/create.c +++ b/compiler/create.c @@ -119,6 +119,13 @@ Statement *alloc_declaration_stmt(char *name, TypeSpecifier *type, Expression *i return stmt; } +Statement *alloc_const_declaration_stmt(char *name, TypeSpecifier *type, Expression *initializer) +{ + Statement *stmt = alloc_declaration_stmt(name, type, initializer); + stmt->u.decl_s->is_const = true; + return stmt; +} + Statement *alloc_return_stmt(Expression *expr) { Statement *stmt = alloc_stmt(RETURN_STATEMENT); @@ -126,7 +133,7 @@ Statement *alloc_return_stmt(Expression *expr) return stmt; } -Statement* alloc_expression_stmt(Expression *expr) +Statement *alloc_expression_stmt(Expression *expr) { Statement *stmt = alloc_stmt(EXPRESSION_STATEMENT); stmt->u.expr_s = expr; @@ -301,3 +308,22 @@ DefinitionList *chain_definition_list(DefinitionList *list, Definition *definiti pos->next = alloc_definition_list(definition); return list; } + +DeclarationList *chain_declaration_definition_list(DeclarationList *list, Declaration *declaration) +{ + DeclarationList *next = (DeclarationList *)malloc(sizeof(DeclarationList)); + next->declaration = declaration; + next->next = NULL; + + if (list == NULL) + { + return next; + } + + DeclarationList *pos; + for (pos = list; pos->next; pos = pos->next) + ; + + pos->next = next; + return list; +} diff --git a/compiler/grammar.y b/compiler/grammar.y index 9eb6d6b..214eed0 100644 --- a/compiler/grammar.y +++ b/compiler/grammar.y @@ -27,17 +27,17 @@ int yyerror(const char *s); %token DOUBLE_LITERAL %token INT_LITERAL %token IDENTIFIER; -%token VAR FUNCTION IF ELSE FOR RETURN BREAK CONTINUE NIL +%token VAR CONST FUNCTION IF ELSE FOR RETURN BREAK CONTINUE NIL %token BOOL_T INT_T DOUBLE_T STRING_T -%type expr bool_expr func_call_expr -%type stmt if_stmt declaration_stmt return_stmt variable_declaration +%type expr bool_expr func_call_expr literal +%type stmt if_stmt return_stmt declaration_stmt variable_declaration_stmt const_stmt %type stmt_list %type block %type elseif elseif_list %type type_specifier %type parameter_list paramter -%type definition func_definition +%type definition func_definition variable_definition const_definition %type definition_list %type argument_list @@ -66,7 +66,8 @@ definition_list: definition: func_definition - | variable_declaration { $$ = alloc_declaration_definition($1); } + | const_definition + | variable_definition ; func_definition: @@ -76,6 +77,14 @@ func_definition: | FUNCTION IDENTIFIER '(' ')' block { $$ = alloc_func_definition($2, NULL, NULL, $5); } ; +variable_definition: + variable_declaration_stmt { $$ = alloc_declaration_definition($1); } + ; + +const_definition: + const_stmt { $$ = alloc_declaration_definition($1); } + ; + parameter_list: paramter | parameter_list ',' paramter { $$ = chain_parameter($1, $3); } @@ -99,16 +108,21 @@ stmt: | return_stmt ; +const_stmt: + CONST IDENTIFIER '=' literal { $$ = alloc_const_declaration_stmt($2, NULL, $4); } + | CONST IDENTIFIER type_specifier '=' literal { $$ = alloc_const_declaration_stmt($2, $3, $5); } + ; + declaration_stmt: IDENTIFIER DECL_ASSIGN expr { $$ = alloc_declaration_stmt($1, NULL, $3); } - | variable_declaration + | variable_declaration_stmt ; -variable_declaration: - VAR IDENTIFIER type_specifier { $$ = alloc_declaration_stmt($2, $3, NULL); } - | VAR IDENTIFIER type_specifier '=' expr { $$ = alloc_declaration_stmt($2, $3, $5); } - | VAR IDENTIFIER '=' expr { $$ = alloc_declaration_stmt($2, NULL, $4); } - ; +variable_declaration_stmt: + VAR IDENTIFIER type_specifier { $$ = alloc_declaration_stmt($2, $3, NULL); } + | VAR IDENTIFIER type_specifier '=' expr { $$ = alloc_declaration_stmt($2, $3, $5); } + | VAR IDENTIFIER '=' expr { $$ = alloc_declaration_stmt($2, NULL, $4); } + ; type_specifier: BOOL_T { $$ = alloc_type_specifier(BOOLEAN_TYPE, NULL); } @@ -151,9 +165,7 @@ block: ; expr: - INT_LITERAL { $$ = alloc_int_expression($1); } - | DOUBLE_LITERAL { $$ = alloc_double_expression($1); } - | BOOL_LITERAL { $$ = alloc_bool_expression($1); } + literal | IDENTIFIER { $$ = alloc_identifier_expression($1); } | expr '+' expr { $$ = alloc_binary_expression(ADD_EXPRESSION, $1, $3); } | expr '-' expr { $$ = alloc_binary_expression(SUB_EXPRESSION, $1, $3); } @@ -165,6 +177,12 @@ expr: | func_call_expr ; +literal: + INT_LITERAL { $$ = alloc_int_expression($1); } + | DOUBLE_LITERAL { $$ = alloc_double_expression($1); } + | BOOL_LITERAL { $$ = alloc_bool_expression($1); } + ; + bool_expr: expr '>' expr { $$ = alloc_binary_expression(GT_EXPRESSION, $1, $3); } | expr GE expr { $$ = alloc_binary_expression(GE_EXPRESSION, $1, $3); } diff --git a/compiler/lex.l b/compiler/lex.l index dc03934..83b86d1 100644 --- a/compiler/lex.l +++ b/compiler/lex.l @@ -27,6 +27,7 @@ "for" return FOR; "nil" return NIL; "var" return VAR; +"const" return CONST; "func" return FUNCTION; "return" return RETURN; "break" return BREAK; diff --git a/compiler/summoner.h b/compiler/summoner.h index 0f924e4..0b34859 100644 --- a/compiler/summoner.h +++ b/compiler/summoner.h @@ -105,6 +105,7 @@ typedef struct Declaration TypeSpecifier *type; Expression *initializer; bool is_local; + bool is_const; } Declaration; typedef struct DeclarationList { @@ -163,6 +164,7 @@ Statement *alloc_assign_stmt(char *variable, Expression *operand); Statement *alloc_block_stmt(Block *block); Statement *alloc_if_stmt(Expression *condition, Block *then_block, Elseif *elseif_list, Block *else_block); Statement *alloc_declaration_stmt(char *name, TypeSpecifier *type, Expression *initializer); +Statement *alloc_const_declaration_stmt(char *name, TypeSpecifier *type, Expression *initializer); Statement *alloc_return_stmt(Expression *expr); Statement *alloc_expression_stmt(Expression *expr); StatementList *chain_stmt_list(StatementList *list, Statement *statement); @@ -220,6 +222,7 @@ typedef struct FuncDefinition Definition *alloc_func_definition(char *name, ParameterList *parameters, TypeSpecifier *return_type, Block *block); FuncDefinition *chain_func_definition_list(FuncDefinition *list, FuncDefinition *next); Definition *alloc_declaration_definition(Statement *declaration_stmt); +DeclarationList *chain_declaration_definition_list(DeclarationList *list, Declaration *declaration); DefinitionList *alloc_definition_list(Definition *definition); DefinitionList *chain_definition_list(DefinitionList *list, Definition *definition); diff --git a/interpreter/eval.cpp b/interpreter/eval.cpp index 9362901..b14e05a 100644 --- a/interpreter/eval.cpp +++ b/interpreter/eval.cpp @@ -223,6 +223,13 @@ ExprValue Interpreter::eval_expression(Expression *expr) void Interpreter::exec() { + for (DeclarationList *pos = this->declaration_list; pos != nullptr; pos = pos->next) + { + Declaration *declaration = pos->declaration; + bool is_const = declaration->is_const; + this->current_scope->put_identifier(new Identifier(declaration->name, this->eval_expression(declaration->initializer), is_const)); + } + FuncDefinition *func_d = this->find_func_definition("main"); if (func_d == nullptr) { @@ -305,6 +312,11 @@ StmtResult Interpreter::eval_stmt(Statement *stmt) cout << "\"" << assign_s->variable << "\" is undefined" << endl; exit(1); } + if (identifier->get_is_const()) + { + cout << "assign const is invalid" << endl; + exit(1); + } identifier->set_value(this->eval_expression(assign_s->operand)); return result; diff --git a/interpreter/eval.h b/interpreter/eval.h index 9ef0eff..c730427 100644 --- a/interpreter/eval.h +++ b/interpreter/eval.h @@ -46,13 +46,16 @@ class Identifier { public: Identifier(string name, ExprValue value) : name(name), value(value) {} + Identifier(string name, ExprValue value, bool is_const) : name(name), value(value), is_const(is_const) {} void set_value(ExprValue value) { this->value = value; } string get_name() { return this->name; } ExprValue get_value() { return this->value; } + bool get_is_const() { return this->is_const; } private: string name; ExprValue value; + bool is_const; }; class Scope @@ -82,12 +85,13 @@ class Scope class Interpreter { public: - Interpreter(FuncDefinition *func_list) : func_definition_list(func_list), current_scope(nullptr){}; + Interpreter(FuncDefinition *func_list, DeclarationList *declaration_list) : func_definition_list(func_list), declaration_list(declaration_list), current_scope(new Scope(nullptr)){}; void exec(); private: Scope *current_scope; FuncDefinition *func_definition_list; + DeclarationList *declaration_list; ExprValue *eval_func(FuncDefinition *fd, ArgumentList *arg_list); FuncDefinition *find_func_definition(const char *name); diff --git a/interpreter/main.cpp b/interpreter/main.cpp index 80512b4..c20aab2 100644 --- a/interpreter/main.cpp +++ b/interpreter/main.cpp @@ -21,7 +21,7 @@ int main(int argc, char *argv[]) yyparse(); } - Interpreter *interpreter = new Interpreter(compiler->func_definition_list); + Interpreter *interpreter = new Interpreter(compiler->func_definition_list, compiler->declaration_list); interpreter->exec(); return 0; -} \ No newline at end of file +}