Allow assigning nil to any pointer
This commit is contained in:
parent
aab16e4941
commit
8b654ed138
82
README.md
82
README.md
@ -19,83 +19,5 @@ and a possbility to compile Elna programs for different platforms.
|
|||||||
|
|
||||||
## Grammar
|
## Grammar
|
||||||
|
|
||||||
```ebnf
|
Flex and bison grammar specifications, `lexer.ll` and `parser.yy`, can be found
|
||||||
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9";
|
in the `boot/` directory.
|
||||||
letter = "A" | "B" | … | "Z" | "a" | "b" | … | "z";
|
|
||||||
|
|
||||||
ident = letter { letter | digit | "_" };
|
|
||||||
integer = digit { digit };
|
|
||||||
float = integer "." integer;
|
|
||||||
boolean = "true" | "false";
|
|
||||||
|
|
||||||
literal = integer | float | boolean | "'" character "'" | """ { character } """;
|
|
||||||
|
|
||||||
program = [ "type" type_definitions ";" ]
|
|
||||||
[ constant_part ]
|
|
||||||
{ procedure_definition }
|
|
||||||
[ variable_part ]
|
|
||||||
"begin" [ statement_list ] "end" ".";
|
|
||||||
|
|
||||||
procedure_definition = "proc" ident formal_parameter_list ";" ( block | "extern" ) ";";
|
|
||||||
|
|
||||||
block = [ constant_part ]
|
|
||||||
[ variable_part ]
|
|
||||||
statement;
|
|
||||||
|
|
||||||
constant_part = "const" ident "=" integer { "," ident "=" integer } ";";
|
|
||||||
variable_part = "var" variable_declarations ";";
|
|
||||||
|
|
||||||
statement = ident ":=" expression
|
|
||||||
| ident actual_parameter_list
|
|
||||||
| while_do
|
|
||||||
| if_then_else;
|
|
||||||
|
|
||||||
|
|
||||||
while_do = "while" condition "do" [ statement_list ] "end";
|
|
||||||
if_then_else = "if" expression
|
|
||||||
"then" [ statement_list ]
|
|
||||||
[ else statement_list ] "end";
|
|
||||||
|
|
||||||
statement_list = statement {";" statement };
|
|
||||||
|
|
||||||
condition = "odd" expression |
|
|
||||||
expression ("="|"#"|"<"|"<="|">"|">=") expression;
|
|
||||||
|
|
||||||
comparison_operator = "=", "<>", "<", ">", "<=", ">=";
|
|
||||||
unary_prefix = "not", "@";
|
|
||||||
|
|
||||||
expression = logical_operand { ("and" | "or") logical_operand };
|
|
||||||
logical_operand = comparand { comparison_operator comparand };
|
|
||||||
comparand = summand { ("+" | "-") summand };
|
|
||||||
summand = factor { ("*" | "/") factor };
|
|
||||||
factor = pointer { unary_prefix pointer };
|
|
||||||
|
|
||||||
pointer = literal
|
|
||||||
| designator_expression { $$ = $1; }
|
|
||||||
| "(" expression ")";
|
|
||||||
|
|
||||||
designator_expression = designator_expression "[" expression "]"
|
|
||||||
| designator_expression "." ident
|
|
||||||
| designator_expression "^"
|
|
||||||
| ident;
|
|
||||||
|
|
||||||
formal_parameter_list = "(" [ variable_declarations ] ")";
|
|
||||||
|
|
||||||
actual_parameter_list = "(" [ expressions ] ")";
|
|
||||||
|
|
||||||
expressions = expression { "," expression };
|
|
||||||
|
|
||||||
variable_declarations = variable_declaration { ";" variable_declaration };
|
|
||||||
|
|
||||||
variable_declaration = ident ":" type_expression;
|
|
||||||
|
|
||||||
type_expression = "array" integer "of" type_expression
|
|
||||||
| "pointer" "to" type_expression
|
|
||||||
| "record" field_list "end"
|
|
||||||
| "union" field_list "end"
|
|
||||||
| ident;
|
|
||||||
|
|
||||||
field_list = field_declaration { ";" field_declaration };
|
|
||||||
|
|
||||||
field_declaration = ident ":" type_expression;
|
|
||||||
```
|
|
||||||
|
@ -25,11 +25,19 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::call_expression *expression)
|
void generic_visitor::visit(boot::call_expression *expression)
|
||||||
{
|
{
|
||||||
if (auto symbol = this->symbol_map->lookup(expression->name()))
|
tree symbol = this->symbol_map->lookup(expression->name());
|
||||||
|
|
||||||
|
if (symbol == NULL_TREE)
|
||||||
{
|
{
|
||||||
tree return_type = TREE_TYPE(TREE_TYPE(symbol->payload));
|
error_at(get_location(&expression->position()),
|
||||||
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol->payload));
|
"procedure '%s' not declared",
|
||||||
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol->payload);
|
expression->name().c_str());
|
||||||
|
this->current_expression = error_mark_node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tree return_type = TREE_TYPE(TREE_TYPE(symbol));
|
||||||
|
tree fndecl_type = build_function_type(return_type, TYPE_ARG_TYPES(symbol));
|
||||||
|
tree printf_fn = build1(ADDR_EXPR, build_pointer_type(fndecl_type), symbol);
|
||||||
|
|
||||||
std::vector<tree> arguments(expression->arguments().size());
|
std::vector<tree> arguments(expression->arguments().size());
|
||||||
for (std::size_t i = 0; i < expression->arguments().size(); ++i)
|
for (std::size_t i = 0; i < expression->arguments().size(); ++i)
|
||||||
@ -50,14 +58,6 @@ namespace gcc
|
|||||||
this->current_expression = stmt;
|
this->current_expression = stmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
error_at(get_location(&expression->position()),
|
|
||||||
"procedure '%s' not declared",
|
|
||||||
expression->name().c_str());
|
|
||||||
this->current_expression = error_mark_node;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void generic_visitor::visit(boot::cast_expression *expression)
|
void generic_visitor::visit(boot::cast_expression *expression)
|
||||||
{
|
{
|
||||||
@ -74,22 +74,21 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
auto body_type = build_type(expression->body());
|
auto body_type = build_type(expression->body());
|
||||||
|
|
||||||
this->current_expression = build1(CONVERT_EXPR,
|
this->current_expression = build1(CONVERT_EXPR, this->symbol_map->lookup("Word"), TYPE_SIZE_UNIT(body_type));
|
||||||
this->symbol_map->lookup("Word")->payload, TYPE_SIZE_UNIT(body_type));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generic_visitor::is_integral_type(tree type)
|
bool generic_visitor::is_integral_type(tree type)
|
||||||
{
|
{
|
||||||
gcc_assert(TYPE_P(type));
|
gcc_assert(TYPE_P(type));
|
||||||
|
|
||||||
return type == this->symbol_map->lookup("Int")->payload
|
return type == this->symbol_map->lookup("Int")
|
||||||
|| type == this->symbol_map->lookup("Word")->payload;
|
|| type == this->symbol_map->lookup("Word");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generic_visitor::is_numeric_type(tree type)
|
bool generic_visitor::is_numeric_type(tree type)
|
||||||
{
|
{
|
||||||
return is_integral_type(type)
|
return is_integral_type(type)
|
||||||
|| type == this->symbol_map->lookup("Float")->payload;
|
|| type == this->symbol_map->lookup("Float");
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::program *program)
|
void generic_visitor::visit(boot::program *program)
|
||||||
@ -130,7 +129,7 @@ namespace gcc
|
|||||||
get_identifier(argument_name.c_str()), parameter_types[i]);
|
get_identifier(argument_name.c_str()), parameter_types[i]);
|
||||||
DECL_CONTEXT(argc_declaration_tree) = this->main_fndecl;
|
DECL_CONTEXT(argc_declaration_tree) = this->main_fndecl;
|
||||||
DECL_ARG_TYPE(argc_declaration_tree) = parameter_types[i];
|
DECL_ARG_TYPE(argc_declaration_tree) = parameter_types[i];
|
||||||
this->symbol_map->enter(argument_name, boot::make_info(argc_declaration_tree));
|
this->symbol_map->enter(argument_name, argc_declaration_tree);
|
||||||
argument_chain.append(argc_declaration_tree);
|
argument_chain.append(argc_declaration_tree);
|
||||||
}
|
}
|
||||||
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
||||||
@ -171,7 +170,7 @@ namespace gcc
|
|||||||
tree declaration_type = build_function_type_array(return_type,
|
tree declaration_type = build_function_type_array(return_type,
|
||||||
definition->parameters.size(), parameter_types.data());
|
definition->parameters.size(), parameter_types.data());
|
||||||
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->enter(definition->identifier(), boot::make_info(this->main_fndecl));
|
this->symbol_map->enter(definition->identifier(), this->main_fndecl);
|
||||||
|
|
||||||
if (definition->body() != nullptr)
|
if (definition->body() != nullptr)
|
||||||
{
|
{
|
||||||
@ -193,7 +192,7 @@ namespace gcc
|
|||||||
|
|
||||||
if (definition->body() != nullptr)
|
if (definition->body() != nullptr)
|
||||||
{
|
{
|
||||||
this->symbol_map->enter(parameter->identifier(), boot::make_info(declaration_tree));
|
this->symbol_map->enter(parameter->identifier(), declaration_tree);
|
||||||
}
|
}
|
||||||
argument_chain.append(declaration_tree);
|
argument_chain.append(declaration_tree);
|
||||||
}
|
}
|
||||||
@ -243,14 +242,14 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup("Int");
|
auto symbol = this->symbol_map->lookup("Int");
|
||||||
|
|
||||||
this->current_expression = build_int_cst(symbol->payload, literal->number());
|
this->current_expression = build_int_cst(symbol, literal->number());
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
|
void generic_visitor::visit(boot::number_literal<std::uint32_t> *literal)
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup("Word");
|
auto symbol = this->symbol_map->lookup("Word");
|
||||||
|
|
||||||
this->current_expression = build_int_cstu(symbol->payload, literal->number());
|
this->current_expression = build_int_cstu(symbol, literal->number());
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<double> *literal)
|
void generic_visitor::visit(boot::number_literal<double> *literal)
|
||||||
@ -272,14 +271,14 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup("Bool");
|
auto symbol = this->symbol_map->lookup("Bool");
|
||||||
|
|
||||||
this->current_expression = build_int_cst_type(symbol->payload, boolean->number());
|
this->current_expression = build_int_cst_type(symbol, boolean->number());
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
|
void generic_visitor::visit(boot::number_literal<unsigned char> *character)
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup("Char");
|
auto symbol = this->symbol_map->lookup("Char");
|
||||||
|
|
||||||
this->current_expression = build_int_cstu(symbol->payload, character->number());
|
this->current_expression = build_int_cstu(symbol, character->number());
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
|
void generic_visitor::visit(boot::number_literal<nullptr_t> *)
|
||||||
@ -303,7 +302,7 @@ namespace gcc
|
|||||||
tree_code operator_code, tree left, tree right)
|
tree_code operator_code, tree left, tree right)
|
||||||
{
|
{
|
||||||
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
|
return build_binary_operation(is_numeric_type(TREE_TYPE(left)) || is_pointer_type(TREE_TYPE(left)),
|
||||||
expression, operator_code, left, right, this->symbol_map->lookup("Bool")->payload);
|
expression, operator_code, left, right, this->symbol_map->lookup("Bool"));
|
||||||
}
|
}
|
||||||
|
|
||||||
tree generic_visitor::build_logic_operation(boot::binary_expression *expression,
|
tree generic_visitor::build_logic_operation(boot::binary_expression *expression,
|
||||||
@ -311,15 +310,15 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup("Bool");
|
auto symbol = this->symbol_map->lookup("Bool");
|
||||||
|
|
||||||
return build_binary_operation(TREE_TYPE(left) == symbol->payload,
|
return build_binary_operation(TREE_TYPE(left) == symbol,
|
||||||
expression, operator_code, left, right, symbol->payload);
|
expression, operator_code, left, right, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
tree generic_visitor::build_equality_operation(boot::binary_expression *expression,
|
tree generic_visitor::build_equality_operation(boot::binary_expression *expression,
|
||||||
tree_code operator_code, tree left, tree right)
|
tree_code operator_code, tree left, tree right)
|
||||||
{
|
{
|
||||||
return build_binary_operation(true, expression,
|
return build_binary_operation(true, expression,
|
||||||
operator_code, left, right, this->symbol_map->lookup("Bool")->payload);
|
operator_code, left, right, this->symbol_map->lookup("Bool"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::binary_expression *expression)
|
void generic_visitor::visit(boot::binary_expression *expression)
|
||||||
@ -425,7 +424,7 @@ namespace gcc
|
|||||||
|
|
||||||
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
tree definition_tree = build_decl(definition_location, CONST_DECL,
|
||||||
get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression));
|
get_identifier(definition->identifier().c_str()), TREE_TYPE(this->current_expression));
|
||||||
auto result = this->symbol_map->enter(definition->identifier(), boot::make_info(definition_tree));
|
auto result = this->symbol_map->enter(definition->identifier(), definition_tree);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@ -457,7 +456,7 @@ 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->enter(definition->identifier(), boot::make_info(tree_type));
|
auto result = this->symbol_map->enter(definition->identifier(), tree_type);
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
@ -480,11 +479,11 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
if (boot::basic_type_expression *basic_type = type.is_basic())
|
if (boot::basic_type_expression *basic_type = type.is_basic())
|
||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup(basic_type->base_name());
|
tree symbol = this->symbol_map->lookup(basic_type->base_name());
|
||||||
|
|
||||||
if (symbol && TYPE_P(symbol->payload))
|
if (symbol != NULL_TREE && TYPE_P(symbol))
|
||||||
{
|
{
|
||||||
return symbol->payload;
|
return symbol;
|
||||||
}
|
}
|
||||||
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());
|
||||||
@ -590,7 +589,7 @@ namespace gcc
|
|||||||
location_t declaration_location = get_location(&declaration->position());
|
location_t 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);
|
||||||
bool result = this->symbol_map->enter(declaration->identifier(), boot::make_info(declaration_tree));
|
bool result = this->symbol_map->enter(declaration->identifier(), declaration_tree);
|
||||||
|
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
@ -618,7 +617,7 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
auto symbol = this->symbol_map->lookup(expression->name());
|
auto symbol = this->symbol_map->lookup(expression->name());
|
||||||
|
|
||||||
if (!symbol)
|
if (symbol == NULL_TREE)
|
||||||
{
|
{
|
||||||
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",
|
||||||
@ -626,7 +625,7 @@ namespace gcc
|
|||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->current_expression = symbol->payload;
|
this->current_expression = symbol;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::array_access_expression *expression)
|
void generic_visitor::visit(boot::array_access_expression *expression)
|
||||||
@ -699,20 +698,23 @@ namespace gcc
|
|||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (TREE_TYPE(this->current_expression) != TREE_TYPE(lvalue))
|
if (TREE_TYPE(this->current_expression) == TREE_TYPE(lvalue)
|
||||||
|
|| (is_pointer_type(TREE_TYPE(lvalue)) && this->current_expression == null_pointer_node))
|
||||||
|
{
|
||||||
|
tree assignment = build2_loc(statement_location, MODIFY_EXPR,
|
||||||
|
void_type_node, lvalue, this->current_expression);
|
||||||
|
|
||||||
|
append_to_statement_list(assignment, &this->current_statements);
|
||||||
|
this->current_expression = NULL_TREE;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
error_at(statement_location,
|
error_at(statement_location,
|
||||||
"cannot assign value of type %s to variable of type %s",
|
"cannot assign value of type %s to variable of type %s",
|
||||||
print_type(TREE_TYPE(this->current_expression)),
|
print_type(TREE_TYPE(this->current_expression)),
|
||||||
print_type(TREE_TYPE(lvalue)));
|
print_type(TREE_TYPE(lvalue)));
|
||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
auto assignment = build2_loc(statement_location, MODIFY_EXPR,
|
|
||||||
void_type_node, lvalue, this->current_expression);
|
|
||||||
|
|
||||||
append_to_statement_list(assignment, &this->current_statements);
|
|
||||||
this->current_expression = NULL_TREE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::if_statement *statement)
|
void generic_visitor::visit(boot::if_statement *statement)
|
||||||
|
@ -74,13 +74,13 @@ namespace gcc
|
|||||||
std::shared_ptr<boot::symbol_table<tree>> initial_table =
|
std::shared_ptr<boot::symbol_table<tree>> initial_table =
|
||||||
std::make_shared<boot::symbol_table<tree>>();
|
std::make_shared<boot::symbol_table<tree>>();
|
||||||
|
|
||||||
initial_table->enter("Int", boot::make_info(long_integer_type_node));
|
initial_table->enter("Int", long_integer_type_node);
|
||||||
initial_table->enter("Word", boot::make_info(size_type_node));
|
initial_table->enter("Word", size_type_node);
|
||||||
initial_table->enter("Bool", boot::make_info(boolean_type_node));
|
initial_table->enter("Bool", boolean_type_node);
|
||||||
initial_table->enter("Float", boot::make_info(double_type_node));
|
initial_table->enter("Float", double_type_node);
|
||||||
initial_table->enter("Char", boot::make_info(unsigned_char_type_node));
|
initial_table->enter("Char", unsigned_char_type_node);
|
||||||
initial_table->enter("Byte", boot::make_info(make_unsigned_type(8)));
|
initial_table->enter("Byte", make_unsigned_type(8));
|
||||||
initial_table->enter("String", boot::make_info(elna_string_type_node));
|
initial_table->enter("String", elna_string_type_node);
|
||||||
|
|
||||||
return initial_table;
|
return initial_table;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
/* gcc/gcc.cc */
|
/* gcc/gcc.cc */
|
||||||
{".elna", "@elna", nullptr, 0, 0},
|
{".elna", "@elna", nullptr, 0, 0},
|
||||||
{"@elna",
|
{"@elna",
|
||||||
"elna1 %{!Q:-quiet} \
|
"elna1 %i \
|
||||||
%i %{!fsyntax-only:%(invoke_as)}",
|
%{!Q:-quiet} \
|
||||||
|
%{!fsyntax-only:%{S:%W{o*}%{!o*:-o %w%b.s}}} \
|
||||||
|
%{fsyntax-only:-o %j} %{-param*} \
|
||||||
|
%{!fsyntax-only:%(invoke_as)}",
|
||||||
nullptr, 0, 0},
|
nullptr, 0, 0},
|
||||||
|
@ -12,27 +12,6 @@ namespace elna
|
|||||||
{
|
{
|
||||||
namespace boot
|
namespace boot
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* 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.
|
* Symbol table.
|
||||||
*/
|
*/
|
||||||
@ -40,7 +19,7 @@ namespace boot
|
|||||||
class symbol_table
|
class symbol_table
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using symbol_ptr = std::shared_ptr<info<T>>;
|
using symbol_ptr = T;
|
||||||
using iterator = typename std::unordered_map<std::string, symbol_ptr>::iterator;
|
using iterator = typename std::unordered_map<std::string, symbol_ptr>::iterator;
|
||||||
using const_iterator = typename std::unordered_map<std::string, symbol_ptr>::const_iterator;
|
using const_iterator = typename std::unordered_map<std::string, symbol_ptr>::const_iterator;
|
||||||
|
|
||||||
|
46
source.elna
46
source.elna
@ -40,7 +40,8 @@ type
|
|||||||
dummy: Int
|
dummy: Int
|
||||||
end,
|
end,
|
||||||
CommandLine = record
|
CommandLine = record
|
||||||
input: pointer to Char
|
input: pointer to Char;
|
||||||
|
tokenize: Bool
|
||||||
end,
|
end,
|
||||||
Literal = record
|
Literal = record
|
||||||
value: Int
|
value: Int
|
||||||
@ -76,6 +77,7 @@ proc reallocarray(ptr: pointer to Byte, n: Word, size: Word): pointer to Byte; e
|
|||||||
|
|
||||||
proc memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; extern;
|
proc memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; extern;
|
||||||
|
|
||||||
|
proc strcmp(s1: pointer to Char, s2: pointer to Char): Int; extern;
|
||||||
proc strncmp(s1: pointer to Char, s2: pointer to Char, n: Word): Int; extern;
|
proc strncmp(s1: pointer to Char, s2: pointer to Char, n: Word): Int; extern;
|
||||||
proc strncpy(dst: pointer to Char, src: pointer to Char, dsize: Word): pointer to Char; extern;
|
proc strncpy(dst: pointer to Char, src: pointer to Char, dsize: Word): pointer to Char; extern;
|
||||||
proc strcpy(dst: pointer to Char, src: pointer to Char): pointer to Char; extern;
|
proc strcpy(dst: pointer to Char, src: pointer to Char): pointer to Char; extern;
|
||||||
@ -185,7 +187,7 @@ begin
|
|||||||
|
|
||||||
input := calloc(source_size + 1, 1);
|
input := calloc(source_size + 1, 1);
|
||||||
if fread(input, source_size, 1, input_file) <> 1u then
|
if fread(input, source_size, 1, input_file) <> 1u then
|
||||||
input := cast(nil as pointer to Byte)
|
input := nil
|
||||||
end;
|
end;
|
||||||
fclose(input_file);
|
fclose(input_file);
|
||||||
|
|
||||||
@ -548,7 +550,7 @@ var
|
|||||||
token_length: Word;
|
token_length: Word;
|
||||||
begin
|
begin
|
||||||
tokens_size^ := 0u;
|
tokens_size^ := 0u;
|
||||||
tokens := cast(nil as pointer to Token);
|
tokens := nil;
|
||||||
|
|
||||||
input_pointer := skip_spaces(input_pointer);
|
input_pointer := skip_spaces(input_pointer);
|
||||||
|
|
||||||
@ -564,7 +566,7 @@ begin
|
|||||||
|
|
||||||
input_pointer := token_end
|
input_pointer := token_end
|
||||||
elsif is_digit(input_pointer^) then
|
elsif is_digit(input_pointer^) then
|
||||||
token_end := cast(nil as pointer to Char);
|
token_end := nil;
|
||||||
current_token^.value.int_value := strtol(input_pointer, @token_end, 10);
|
current_token^.value.int_value := strtol(input_pointer, @token_end, 10);
|
||||||
|
|
||||||
if token_end^ = 'u' then
|
if token_end^ = 'u' then
|
||||||
@ -731,7 +733,7 @@ var
|
|||||||
begin
|
begin
|
||||||
result := cast(calloc(1, sizeof(Program)) as pointer to Program);
|
result := cast(calloc(1, sizeof(Program)) as pointer to Program);
|
||||||
|
|
||||||
result^.constants.elements := cast(nil as pointer to pointer to ConstantDefinition);
|
result^.constants.elements := nil;
|
||||||
result^.constants.count := 0u;
|
result^.constants.count := 0u;
|
||||||
|
|
||||||
if tokens^^.kind = TOKEN_CONST then
|
if tokens^^.kind = TOKEN_CONST then
|
||||||
@ -760,28 +762,34 @@ var
|
|||||||
i: Int,
|
i: Int,
|
||||||
result: pointer to CommandLine;
|
result: pointer to CommandLine;
|
||||||
begin
|
begin
|
||||||
if argc < 2 then
|
i := 1;
|
||||||
write_s("Fatal error: no input files.\n");
|
result := cast(malloc(sizeof(CommandLine)) as pointer to CommandLine);
|
||||||
return nil
|
result^.tokenize := false;
|
||||||
end;
|
result^.input := nil;
|
||||||
if argc > 2 then
|
|
||||||
write_s("Fatal error: Unknown command line options:");
|
|
||||||
|
|
||||||
i := 2;
|
|
||||||
while i < argc do
|
while i < argc do
|
||||||
parameter := argv + i * cast(sizeof(pointer to Char) as Int);
|
parameter := argv + i * cast(sizeof(pointer to Char) as Int);
|
||||||
|
|
||||||
|
if strcmp(parameter^, "--tokenize") = 0 then
|
||||||
|
result^.tokenize := true
|
||||||
|
elsif parameter^^ <> '-' then
|
||||||
|
result^.input := parameter^
|
||||||
|
else
|
||||||
|
write_s("Fatal error: Unknown command line options:");
|
||||||
|
|
||||||
write_c(' ');
|
write_c(' ');
|
||||||
write_s(parameter^);
|
write_s(parameter^);
|
||||||
i := i + 1
|
|
||||||
end;
|
|
||||||
write_s(".\n");
|
write_s(".\n");
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end;
|
end;
|
||||||
|
|
||||||
parameter := argv + cast(sizeof(pointer to Char) as Int);
|
i := i + 1
|
||||||
result := cast(malloc(sizeof(CommandLine)) as pointer to CommandLine);
|
end;
|
||||||
result^.input := parameter^;
|
if result^.input = nil then
|
||||||
|
write_s("Fatal error: no input files.\n");
|
||||||
|
return nil
|
||||||
|
end;
|
||||||
|
|
||||||
return result
|
return result
|
||||||
end;
|
end;
|
||||||
@ -805,7 +813,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
tokens := tokenize(input, @tokens_size);
|
tokens := tokenize(input, @tokens_size);
|
||||||
|
|
||||||
print_tokens(tokens, tokens_size);
|
if command_line^.tokenize then
|
||||||
|
print_tokens(tokens, tokens_size)
|
||||||
|
end;
|
||||||
|
|
||||||
parse_program(@tokens, @tokens_size);
|
parse_program(@tokens, @tokens_size);
|
||||||
return 0
|
return 0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user