Move type definitions to the program node
This commit is contained in:
parent
7985704981
commit
b45b00a3f6
74
README
74
README
@ -1,37 +1,73 @@
|
|||||||
# Elna programming language
|
# Elna programming language
|
||||||
|
|
||||||
Elna compiles simple mathematical operations to machine code.
|
Elna is a simple, imperative, low-level programming language.
|
||||||
The compiled program returns the result of the operation.
|
|
||||||
|
It is intendet to accompany other languages in the areas, where a high-level
|
||||||
|
language doesn't fit well. It is also supposed to be an intermediate
|
||||||
|
representation for a such high-level hypothetical programming language.
|
||||||
|
|
||||||
## File extension
|
## File extension
|
||||||
|
|
||||||
.elna
|
.elna
|
||||||
|
|
||||||
## Grammar PL/0
|
## Current implementation
|
||||||
|
|
||||||
program = block "." ;
|
This repository contains a GCC frontend for Elna. After finishing the frontend
|
||||||
|
I'm planning to rewrite the compiler in Elna itself with its own backend and
|
||||||
|
a hand-written parser. So GCC gives a way to have a simple bootstrap compiler
|
||||||
|
and a possbility to compile Elna programs for different platforms.
|
||||||
|
|
||||||
block = [ "const" ident "=" number {"," ident "=" number} ";"]
|
## Grammar
|
||||||
[ "var" ident {"," ident} ";"]
|
|
||||||
{ "procedure" ident ";" block ";" } statement ;
|
|
||||||
|
|
||||||
statement = [ ident ":=" expression | "call" ident
|
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
||||||
| "?" ident | "!" expression
|
|
||||||
| "begin" statement {";" statement } "end"
|
integer = digit { digit };
|
||||||
| "if" condition "then" statement
|
boolean = "true" | "false";
|
||||||
| "while" condition "do" statement ];
|
|
||||||
|
program = [ "type" type_definitions ";" ]
|
||||||
|
[ "const" ident "=" integer { "," ident "=" integer } ";"]
|
||||||
|
{ procedure_definition }
|
||||||
|
[ "var" variable_declarations ";" ]
|
||||||
|
compound_statement ".";
|
||||||
|
|
||||||
|
procedure_definition = "procedure" ident formal_parameter_list ";" block ";";
|
||||||
|
|
||||||
|
block = [ "const" ident "=" integer { "," ident "=" integer } ";" ]
|
||||||
|
[ "var" variable_declarations ";" ]
|
||||||
|
statement;
|
||||||
|
|
||||||
|
statement = [ ident ":=" expression
|
||||||
|
| ident actual_parameter_list
|
||||||
|
| compound_statement
|
||||||
|
| "if" condition "then" statement
|
||||||
|
| "while" condition "do" statement ];
|
||||||
|
|
||||||
|
compound_statement = "begin" statement {";" statement } "end" ;
|
||||||
|
|
||||||
condition = "odd" expression |
|
condition = "odd" expression |
|
||||||
expression ("="|"#"|"<"|"<="|">"|">=") expression ;
|
expression ("="|"#"|"<"|"<="|">"|">=") expression;
|
||||||
|
|
||||||
expression = [ "+"|"-"] term { ("+"|"-") term};
|
expression = [ "+"|"-"] term { ("+"|"-") term};
|
||||||
|
|
||||||
term = factor {("*"|"/") factor};
|
term = factor { ("*"|"/") factor };
|
||||||
|
|
||||||
factor = ident | number | "(" expression ")";
|
factor = ident | integer | "(" expression ")";
|
||||||
|
|
||||||
## Operations
|
formal_parameter_list = "(" [ variable_declarations ] ")";
|
||||||
|
|
||||||
"!" - Write a line.
|
actual_parameter_list = "(" [ expressions ] ")";
|
||||||
"?" - Read user input.
|
|
||||||
"odd" - The only function, returns whether a number is odd.
|
expressions = expression { "," expression };
|
||||||
|
|
||||||
|
variable_declarations = variable_declaration { ";" variable_declaration };
|
||||||
|
|
||||||
|
variable_declaration = ident ":" type_expression;
|
||||||
|
|
||||||
|
type_expression = "array" integer "of" type_expression
|
||||||
|
| "^" type_expression
|
||||||
|
| "record" field_list "end"
|
||||||
|
| ident;
|
||||||
|
|
||||||
|
field_list = field_declaration { ";" field_declaration };
|
||||||
|
|
||||||
|
field_declaration = ident ":" type_expression;
|
||||||
|
22
example.elna
22
example.elna
@ -15,7 +15,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
proc test_array();
|
proc test_array();
|
||||||
var a: T, x_3: Int;
|
var a: T, x: Int;
|
||||||
begin
|
begin
|
||||||
a[0] := 2;
|
a[0] := 2;
|
||||||
a[1] := 5;
|
a[1] := 5;
|
||||||
@ -23,19 +23,19 @@ begin
|
|||||||
writei("");
|
writei("");
|
||||||
writei("Test array:");
|
writei("Test array:");
|
||||||
|
|
||||||
x_3 := 0;
|
x := 0;
|
||||||
while x_3 < 2 do
|
while x < 2 do
|
||||||
begin
|
begin
|
||||||
writei(a[x_3]);
|
writei(a[x]);
|
||||||
x_3 := x_3 + 1
|
x := x + 1
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc test_pointer();
|
proc test_pointer();
|
||||||
var x_2: Int, p: ^Int;
|
var x: Int, p: ^Int;
|
||||||
begin
|
begin
|
||||||
x_2 := 5;
|
x := 5;
|
||||||
p := @x_2;
|
p := @x;
|
||||||
|
|
||||||
writei("");
|
writei("");
|
||||||
writei("Test pointer:");
|
writei("Test pointer:");
|
||||||
@ -69,13 +69,13 @@ end;
|
|||||||
|
|
||||||
proc test_const();
|
proc test_const();
|
||||||
const t = 5;
|
const t = 5;
|
||||||
var x_1: Int;
|
var x: Int;
|
||||||
begin
|
begin
|
||||||
x_1 := t;
|
x := t;
|
||||||
|
|
||||||
writei("");
|
writei("");
|
||||||
writei("Test const:");
|
writei("Test const:");
|
||||||
writei(x_1)
|
writei(x)
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc test_if();
|
proc test_if();
|
||||||
|
@ -30,7 +30,6 @@ elna_OBJS = \
|
|||||||
elna/lexer.o \
|
elna/lexer.o \
|
||||||
elna/parser.o \
|
elna/parser.o \
|
||||||
elna/result.o \
|
elna/result.o \
|
||||||
elna/types.o \
|
|
||||||
$(END)
|
$(END)
|
||||||
|
|
||||||
elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS)
|
elna1$(exeext): attribs.o $(elna_OBJS) $(BACKEND) $(LIBDEPS)
|
||||||
|
@ -15,9 +15,14 @@ namespace elna
|
|||||||
{
|
{
|
||||||
namespace gcc
|
namespace gcc
|
||||||
{
|
{
|
||||||
|
generic_visitor::generic_visitor()
|
||||||
|
{
|
||||||
|
this->symbol_map = std::make_shared<source::symbol_table<tree>>();
|
||||||
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::call_statement *statement)
|
void generic_visitor::visit(source::call_statement *statement)
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map.find(statement->name());
|
auto symbol = this->symbol_map->lookup(statement->name());
|
||||||
|
|
||||||
if (statement->name() == "writei")
|
if (statement->name() == "writei")
|
||||||
{
|
{
|
||||||
@ -80,10 +85,10 @@ namespace gcc
|
|||||||
append_to_statement_list(stmt, &this->current_statements);
|
append_to_statement_list(stmt, &this->current_statements);
|
||||||
this->current_expression = NULL_TREE;
|
this->current_expression = NULL_TREE;
|
||||||
}
|
}
|
||||||
else if (symbol != this->symbol_map.end())
|
else if (symbol)
|
||||||
{
|
{
|
||||||
tree fndecl_type = build_function_type_list(integer_type_node, NULL_TREE);
|
tree fndecl_type = build_function_type_list(integer_type_node, NULL_TREE);
|
||||||
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->second);
|
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
||||||
|
|
||||||
tree stmt = build_call_nary(integer_type_node, printf_fn, 0);
|
tree stmt = build_call_nary(integer_type_node, printf_fn, 0);
|
||||||
|
|
||||||
@ -100,7 +105,7 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(source::program *program)
|
void generic_visitor::visit(source::program *program)
|
||||||
{
|
{
|
||||||
for (const auto& constant : program->definitions())
|
for (const auto& constant : program->type_definitions)
|
||||||
{
|
{
|
||||||
constant->accept(this);
|
constant->accept(this);
|
||||||
}
|
}
|
||||||
@ -153,7 +158,7 @@ namespace gcc
|
|||||||
definition->parameters().size(), parameter_types);
|
definition->parameters().size(), parameter_types);
|
||||||
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
|
this->main_fndecl = build_fn_decl(definition->identifier().c_str(), declaration_type);
|
||||||
|
|
||||||
this->symbol_map.insert({ definition->identifier(), this->main_fndecl });
|
this->symbol_map->enter(definition->identifier(), source::make_info(this->main_fndecl));
|
||||||
|
|
||||||
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
|
tree resdecl = build_decl(UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, integer_type_node);
|
||||||
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
DECL_CONTEXT(resdecl) = this->main_fndecl;
|
||||||
@ -186,6 +191,7 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
this->current_statements = alloc_stmt_list();
|
this->current_statements = alloc_stmt_list();
|
||||||
this->variable_chain = tree_chain();
|
this->variable_chain = tree_chain();
|
||||||
|
this->symbol_map = std::make_shared<source::symbol_table<tree>>(this->symbol_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree_symbol_mapping generic_visitor::leave_scope()
|
tree_symbol_mapping generic_visitor::leave_scope()
|
||||||
@ -194,6 +200,7 @@ namespace gcc
|
|||||||
NULL_TREE, NULL_TREE, NULL_TREE);
|
NULL_TREE, NULL_TREE, NULL_TREE);
|
||||||
tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(),
|
tree bind_expr = build3(BIND_EXPR, void_type_node, variable_chain.head(),
|
||||||
this->current_statements, new_block);
|
this->current_statements, new_block);
|
||||||
|
this->symbol_map = this->symbol_map->scope();
|
||||||
|
|
||||||
return tree_symbol_mapping{ bind_expr, new_block };
|
return tree_symbol_mapping{ bind_expr, new_block };
|
||||||
}
|
}
|
||||||
@ -344,9 +351,9 @@ namespace gcc
|
|||||||
location_t definition_location = get_location(&definition->position());
|
location_t definition_location = get_location(&definition->position());
|
||||||
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
||||||
get_identifier(definition->identifier().c_str()), integer_type_node);
|
get_identifier(definition->identifier().c_str()), integer_type_node);
|
||||||
auto result = this->symbol_map.insert({ definition->identifier(), definition_tree });
|
auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree));
|
||||||
|
|
||||||
if (result.second)
|
if (result)
|
||||||
{
|
{
|
||||||
definition->body().accept(this);
|
definition->body().accept(this);
|
||||||
|
|
||||||
@ -378,9 +385,9 @@ namespace gcc
|
|||||||
location_t definition_location = get_location(&definition->position());
|
location_t definition_location = get_location(&definition->position());
|
||||||
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
tree definition_tree = build_decl(definition_location, TYPE_DECL,
|
||||||
get_identifier(definition->identifier().c_str()), tree_type);
|
get_identifier(definition->identifier().c_str()), tree_type);
|
||||||
auto result = this->symbol_map.insert({ definition->identifier(), definition_tree });
|
auto result = this->symbol_map->enter(definition->identifier(), source::make_info(definition_tree));
|
||||||
|
|
||||||
if (result.second)
|
if (result)
|
||||||
{
|
{
|
||||||
DECL_CONTEXT(definition_tree) = this->main_fndecl;
|
DECL_CONTEXT(definition_tree) = this->main_fndecl;
|
||||||
variable_chain.append(definition_tree);
|
variable_chain.append(definition_tree);
|
||||||
@ -421,11 +428,11 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
return elna_string_type_node;
|
return elna_string_type_node;
|
||||||
}
|
}
|
||||||
auto symbol = this->symbol_map.find(basic_type->base_name());
|
auto symbol = this->symbol_map->lookup(basic_type->base_name());
|
||||||
|
|
||||||
if (symbol != this->symbol_map.end())
|
if (symbol)
|
||||||
{
|
{
|
||||||
return TREE_TYPE(symbol->second);
|
return TREE_TYPE(symbol->payload);
|
||||||
}
|
}
|
||||||
error_at(get_location(&basic_type->position()),
|
error_at(get_location(&basic_type->position()),
|
||||||
"type '%s' not declared", basic_type->base_name().c_str());
|
"type '%s' not declared", basic_type->base_name().c_str());
|
||||||
@ -499,9 +506,9 @@ namespace gcc
|
|||||||
auto declaration_location = get_location(&declaration->position());
|
auto declaration_location = get_location(&declaration->position());
|
||||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
||||||
get_identifier(declaration->identifier().c_str()), declaration_type);
|
get_identifier(declaration->identifier().c_str()), declaration_type);
|
||||||
auto result = this->symbol_map.insert({ declaration->identifier(), declaration_tree });
|
auto result = this->symbol_map->enter(declaration->identifier(), source::make_info(declaration_tree));
|
||||||
|
|
||||||
if (result.second)
|
if (result)
|
||||||
{
|
{
|
||||||
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
||||||
variable_chain.append(declaration_tree);
|
variable_chain.append(declaration_tree);
|
||||||
@ -520,9 +527,9 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(source::variable_expression *expression)
|
void generic_visitor::visit(source::variable_expression *expression)
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map.find(expression->name());
|
auto symbol = this->symbol_map->lookup(expression->name());
|
||||||
|
|
||||||
if (symbol == this->symbol_map.end())
|
if (!symbol)
|
||||||
{
|
{
|
||||||
error_at(get_location(&expression->position()),
|
error_at(get_location(&expression->position()),
|
||||||
"variable '%s' not declared in the current scope",
|
"variable '%s' not declared in the current scope",
|
||||||
@ -530,7 +537,7 @@ namespace gcc
|
|||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->current_expression = symbol->second;
|
this->current_expression = symbol->payload;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::array_access_expression *expression)
|
void generic_visitor::visit(source::array_access_expression *expression)
|
||||||
|
@ -1,3 +1,6 @@
|
|||||||
/* gcc-src/gcc/config/lang-specs.in */
|
/* gcc/gcc.cc */
|
||||||
{".elna", "@elna", 0, 1, 0},
|
{".elna", "@elna", nullptr, 0, 0},
|
||||||
{"@elna", "elna1 %i %(cc1_options) %{!fsyntax-only:%(invoke_as)}", 0, 1, 0},
|
{"@elna",
|
||||||
|
"elna1 %{!Q:-quiet} \
|
||||||
|
%i %{!fsyntax-only:%(invoke_as)}",
|
||||||
|
nullptr, 0, 0},
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "elna/source/ast.h"
|
#include "elna/source/ast.h"
|
||||||
|
#include "elna/source/symbol.h"
|
||||||
#include "elna/gcc/elna-tree.h"
|
#include "elna/gcc/elna-tree.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
@ -20,7 +21,7 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
tree current_statements{ NULL_TREE };
|
tree current_statements{ NULL_TREE };
|
||||||
tree current_expression{ NULL_TREE };
|
tree current_expression{ NULL_TREE };
|
||||||
std::unordered_map<std::string, tree> symbol_map;
|
std::shared_ptr<source::symbol_table<tree>> symbol_map;
|
||||||
tree main_fndecl{ NULL_TREE };
|
tree main_fndecl{ NULL_TREE };
|
||||||
tree_chain variable_chain;
|
tree_chain variable_chain;
|
||||||
|
|
||||||
@ -31,6 +32,8 @@ namespace gcc
|
|||||||
tree_symbol_mapping leave_scope();
|
tree_symbol_mapping leave_scope();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
generic_visitor();
|
||||||
|
|
||||||
void visit(source::program *program) override;
|
void visit(source::program *program) override;
|
||||||
void visit(source::procedure_definition *definition) override;
|
void visit(source::procedure_definition *definition) override;
|
||||||
void visit(source::call_statement *statement) override;
|
void visit(source::call_statement *statement) override;
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "elna/source/result.h"
|
#include "elna/source/result.h"
|
||||||
#include "elna/source/types.h"
|
|
||||||
|
|
||||||
namespace elna
|
namespace elna
|
||||||
{
|
{
|
||||||
@ -210,7 +209,6 @@ namespace source
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::shared_ptr<operand> place;
|
std::shared_ptr<operand> place;
|
||||||
std::shared_ptr<const type> data_type;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
@ -596,19 +594,16 @@ namespace source
|
|||||||
|
|
||||||
class block : public node
|
class block : public node
|
||||||
{
|
{
|
||||||
std::vector<definition *> m_definitions;
|
|
||||||
statement *m_body;
|
statement *m_body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<definition *> value_definitions;
|
std::vector<definition *> value_definitions;
|
||||||
|
|
||||||
block(const struct position position, std::vector<definition *>&& definitions,
|
block(const struct position position, std::vector<definition *>&& value_definitions,
|
||||||
std::vector<definition *>&& value_definitions,
|
|
||||||
statement *body);
|
statement *body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
statement& body();
|
statement& body();
|
||||||
std::vector<definition *>& definitions();
|
|
||||||
|
|
||||||
virtual ~block() override;
|
virtual ~block() override;
|
||||||
};
|
};
|
||||||
@ -616,9 +611,13 @@ namespace source
|
|||||||
class program : public block
|
class program : public block
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
program(const struct position position, std::vector<definition *>&& definitions,
|
std::vector<definition *> type_definitions;
|
||||||
|
|
||||||
|
program(const struct position position, std::vector<definition *>&& type_definitions,
|
||||||
std::vector<definition *>&& value_definitions, statement *body);
|
std::vector<definition *>&& value_definitions, statement *body);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
|
virtual ~program() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include "elna/source/types.h"
|
#include <string>
|
||||||
|
|
||||||
namespace elna
|
namespace elna
|
||||||
{
|
{
|
||||||
|
106
include/elna/source/symbol.h
Normal file
106
include/elna/source/symbol.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public License
|
||||||
|
// v. 2.0. If a copy of the MPL was not distributed with this file, You can
|
||||||
|
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace elna
|
||||||
|
{
|
||||||
|
namespace source
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Generic language entity information.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class info
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
T payload;
|
||||||
|
|
||||||
|
info(T payload)
|
||||||
|
: payload(payload)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::shared_ptr<info<T>> make_info(T payload)
|
||||||
|
{
|
||||||
|
return std::make_shared<info<T>>(info(payload));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symbol table.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
class symbol_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using symbol_ptr = std::shared_ptr<info<T>>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, symbol_ptr> entries;
|
||||||
|
std::shared_ptr<symbol_table> outer_scope;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Constructs a new symbol with an optional outer scope.
|
||||||
|
*
|
||||||
|
* \param scope Outer scope.
|
||||||
|
*/
|
||||||
|
explicit symbol_table(std::shared_ptr<symbol_table> scope = nullptr)
|
||||||
|
: outer_scope(scope)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks for symbol in the table by name. Returns nullptr if the symbol
|
||||||
|
* can not be found.
|
||||||
|
*
|
||||||
|
* \param name Symbol name.
|
||||||
|
* \return Symbol from the table if found.
|
||||||
|
*/
|
||||||
|
symbol_ptr lookup(const std::string& name)
|
||||||
|
{
|
||||||
|
auto entry = entries.find(name);
|
||||||
|
|
||||||
|
if (entry != entries.cend())
|
||||||
|
{
|
||||||
|
return entry->second;
|
||||||
|
}
|
||||||
|
if (this->outer_scope != nullptr)
|
||||||
|
{
|
||||||
|
return this->outer_scope->lookup(name);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers new symbol.
|
||||||
|
*
|
||||||
|
* \param name Symbol name.
|
||||||
|
* \param entry Symbol information.
|
||||||
|
*
|
||||||
|
* \return Whether the insertion took place.
|
||||||
|
*/
|
||||||
|
bool enter(const std::string& name, symbol_ptr entry)
|
||||||
|
{
|
||||||
|
return entries.insert({ name, entry }).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the outer scope or nullptr if the this is the global scope.
|
||||||
|
*
|
||||||
|
* \return Outer scope.
|
||||||
|
*/
|
||||||
|
std::shared_ptr<symbol_table> scope()
|
||||||
|
{
|
||||||
|
return this->outer_scope;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -65,10 +65,6 @@ namespace source
|
|||||||
|
|
||||||
void empty_visitor::visit(block *block)
|
void empty_visitor::visit(block *block)
|
||||||
{
|
{
|
||||||
for (const auto& constant : block->definitions())
|
|
||||||
{
|
|
||||||
constant->accept(this);
|
|
||||||
}
|
|
||||||
for (const auto& definition : block->value_definitions)
|
for (const auto& definition : block->value_definitions)
|
||||||
{
|
{
|
||||||
definition->accept(this);
|
definition->accept(this);
|
||||||
@ -78,6 +74,10 @@ namespace source
|
|||||||
|
|
||||||
void empty_visitor::visit(program *program)
|
void empty_visitor::visit(program *program)
|
||||||
{
|
{
|
||||||
|
for (auto definition : program->type_definitions)
|
||||||
|
{
|
||||||
|
definition->accept(this);
|
||||||
|
}
|
||||||
visit(reinterpret_cast<block *>(program));
|
visit(reinterpret_cast<block *>(program));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,11 +447,9 @@ namespace source
|
|||||||
delete m_body;
|
delete m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
block::block(const struct position position, std::vector<definition *>&& definitions,
|
block::block(const struct position position, std::vector<definition *>&& value_definitions,
|
||||||
std::vector<definition *>&& value_definitions,
|
|
||||||
statement *body)
|
statement *body)
|
||||||
: node(position), m_definitions(std::move(definitions)),
|
: node(position), m_body(std::move(body)), value_definitions(std::move(value_definitions))
|
||||||
m_body(std::move(body)), value_definitions(std::move(value_definitions))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -460,11 +458,6 @@ namespace source
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<definition *>& block::definitions()
|
|
||||||
{
|
|
||||||
return m_definitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
statement& block::body()
|
statement& block::body()
|
||||||
{
|
{
|
||||||
return *m_body;
|
return *m_body;
|
||||||
@ -472,10 +465,6 @@ namespace source
|
|||||||
|
|
||||||
block::~block()
|
block::~block()
|
||||||
{
|
{
|
||||||
for (auto definition : m_definitions)
|
|
||||||
{
|
|
||||||
delete definition;
|
|
||||||
}
|
|
||||||
for (auto definition : value_definitions)
|
for (auto definition : value_definitions)
|
||||||
{
|
{
|
||||||
delete definition;
|
delete definition;
|
||||||
@ -483,9 +472,11 @@ namespace source
|
|||||||
delete m_body;
|
delete m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
program::program(const struct position position, std::vector<definition *>&& definitions,
|
program::program(const struct position position,
|
||||||
|
std::vector<definition *>&& type_definitions,
|
||||||
std::vector<definition *>&& value_definitions, statement *body)
|
std::vector<definition *>&& value_definitions, statement *body)
|
||||||
: block(position, std::move(definitions), std::move(value_definitions), body)
|
: block(position, std::move(value_definitions), body),
|
||||||
|
type_definitions(std::move(type_definitions))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -494,6 +485,14 @@ namespace source
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
program::~program()
|
||||||
|
{
|
||||||
|
for (auto definition : type_definitions)
|
||||||
|
{
|
||||||
|
delete definition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char_literal::char_literal(const struct position position, const unsigned char value)
|
char_literal::char_literal(const struct position position, const unsigned char value)
|
||||||
: expression(position), m_character(value)
|
: expression(position), m_character(value)
|
||||||
{
|
{
|
||||||
|
@ -126,8 +126,10 @@ program:
|
|||||||
{
|
{
|
||||||
*value_definition++ = variable;
|
*value_definition++ = variable;
|
||||||
}
|
}
|
||||||
driver.tree = std::make_unique<elna::source::program>(elna::source::position{},
|
auto tree = new elna::source::program(elna::source::position{},
|
||||||
std::move(definitions), std::move(value_definitions), std::move($5));
|
std::move(definitions), std::move(value_definitions), std::move($5));
|
||||||
|
|
||||||
|
driver.tree.reset(tree);
|
||||||
}
|
}
|
||||||
block: constant_part variable_part statement
|
block: constant_part variable_part statement
|
||||||
{
|
{
|
||||||
@ -143,7 +145,7 @@ block: constant_part variable_part statement
|
|||||||
*definition++ = variable;
|
*definition++ = variable;
|
||||||
}
|
}
|
||||||
$$ = new elna::source::block(elna::source::position{},
|
$$ = new elna::source::block(elna::source::position{},
|
||||||
{}, std::move(definitions), std::move($3));
|
std::move(definitions), std::move($3));
|
||||||
};
|
};
|
||||||
procedure_definition:
|
procedure_definition:
|
||||||
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
PROCEDURE IDENTIFIER formal_parameter_list SEMICOLON block SEMICOLON
|
||||||
@ -285,7 +287,7 @@ expressions:
|
|||||||
}
|
}
|
||||||
| expression { $$.emplace_back(std::move($1)); }
|
| expression { $$.emplace_back(std::move($1)); }
|
||||||
designator_expression:
|
designator_expression:
|
||||||
designator_expression LEFT_SQUARE expression RIGHT_SQUARE
|
designator_expression LEFT_SQUARE expression RIGHT_SQUARE
|
||||||
{
|
{
|
||||||
$$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3);
|
$$ = new elna::source::array_access_expression(elna::source::make_position(@1), $1, $3);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user