Allow comparing all pointer types to nil
This commit is contained in:
parent
607bf09434
commit
aab16e4941
49
boot/ast.cc
49
boot/ast.cc
@ -92,15 +92,15 @@ namespace boot
|
|||||||
|
|
||||||
void empty_visitor::visit(block *block)
|
void empty_visitor::visit(block *block)
|
||||||
{
|
{
|
||||||
for (const auto constant : block->constants)
|
for (constant_definition *const constant : block->constants)
|
||||||
{
|
{
|
||||||
constant->accept(this);
|
constant->accept(this);
|
||||||
}
|
}
|
||||||
for (const auto variable : block->variables)
|
for (variable_declaration *const variable : block->variables)
|
||||||
{
|
{
|
||||||
variable->accept(this);
|
variable->accept(this);
|
||||||
}
|
}
|
||||||
for (const auto body_statement : block->body)
|
for (statement *const body_statement : block->body)
|
||||||
{
|
{
|
||||||
body_statement->accept(this);
|
body_statement->accept(this);
|
||||||
}
|
}
|
||||||
@ -108,11 +108,15 @@ namespace boot
|
|||||||
|
|
||||||
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));
|
||||||
|
for (type_definition *const type : program->types)
|
||||||
|
{
|
||||||
|
type->accept(this);
|
||||||
|
}
|
||||||
|
for (procedure_definition *const procedure : program->procedures)
|
||||||
|
{
|
||||||
|
procedure->accept(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void empty_visitor::visit(binary_expression *expression)
|
void empty_visitor::visit(binary_expression *expression)
|
||||||
@ -490,23 +494,22 @@ namespace boot
|
|||||||
|
|
||||||
block::~block()
|
block::~block()
|
||||||
{
|
{
|
||||||
for (auto variable : this->variables)
|
for (statement *body_statement : this->body)
|
||||||
{
|
|
||||||
delete variable;
|
|
||||||
}
|
|
||||||
for (auto constant : this->constants)
|
|
||||||
{
|
|
||||||
delete constant;
|
|
||||||
}
|
|
||||||
for (auto body_statement : this->body)
|
|
||||||
{
|
{
|
||||||
delete body_statement;
|
delete body_statement;
|
||||||
}
|
}
|
||||||
|
for (variable_declaration *variable : this->variables)
|
||||||
|
{
|
||||||
|
delete variable;
|
||||||
|
}
|
||||||
|
for (constant_definition *constant : this->constants)
|
||||||
|
{
|
||||||
|
delete constant;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
program::program(const struct position position, std::vector<definition *>&& type_definitions)
|
program::program(const struct position position)
|
||||||
: block(position),
|
: block(position)
|
||||||
type_definitions(std::move(type_definitions))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,9 +520,13 @@ namespace boot
|
|||||||
|
|
||||||
program::~program()
|
program::~program()
|
||||||
{
|
{
|
||||||
for (auto definition : type_definitions)
|
for (procedure_definition *procedure : this->procedures)
|
||||||
{
|
{
|
||||||
delete definition;
|
delete procedure;
|
||||||
|
}
|
||||||
|
for (type_definition *type : this->types)
|
||||||
|
{
|
||||||
|
delete type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,23 +111,14 @@
|
|||||||
%type <elna::boot::cast_expression *> cast_expression;
|
%type <elna::boot::cast_expression *> cast_expression;
|
||||||
%%
|
%%
|
||||||
program:
|
program:
|
||||||
type_part constant_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||||
{
|
{
|
||||||
std::vector<elna::boot::definition *> definitions($1.size() + $4.size());
|
auto tree = new elna::boot::program(elna::boot::make_position(@5));
|
||||||
std::vector<elna::boot::definition *>::iterator definition = definitions.begin();
|
|
||||||
|
|
||||||
for (auto type : $1)
|
std::swap(tree->constants, $1);
|
||||||
{
|
std::swap(tree->types , $2);
|
||||||
*definition++ = type;
|
|
||||||
}
|
|
||||||
for (auto procedure : $4)
|
|
||||||
{
|
|
||||||
*definition++ = procedure;
|
|
||||||
}
|
|
||||||
auto tree = new elna::boot::program(elna::boot::make_position(@5), std::move(definitions));
|
|
||||||
|
|
||||||
std::swap(tree->constants, $2);
|
|
||||||
std::swap(tree->variables, $3);
|
std::swap(tree->variables, $3);
|
||||||
|
std::swap(tree->procedures, $4);
|
||||||
std::swap(tree->body, $6);
|
std::swap(tree->body, $6);
|
||||||
|
|
||||||
driver.tree.reset(tree);
|
driver.tree.reset(tree);
|
||||||
|
@ -94,35 +94,21 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(boot::program *program)
|
void generic_visitor::visit(boot::program *program)
|
||||||
{
|
{
|
||||||
for (const auto& type_definition : program->type_definitions)
|
for (boot::constant_definition *const constant : program->constants)
|
||||||
{
|
|
||||||
type_definition->accept(this);
|
|
||||||
}
|
|
||||||
for (const auto constant : program->constants)
|
|
||||||
{
|
{
|
||||||
constant->accept(this);
|
constant->accept(this);
|
||||||
}
|
}
|
||||||
for (const auto declaration : program->variables)
|
for (boot::type_definition *const type : program->types)
|
||||||
{
|
{
|
||||||
tree declaration_type = build_type(declaration->type());
|
type->accept(this);
|
||||||
gcc_assert(declaration_type != NULL_TREE);
|
|
||||||
|
|
||||||
auto declaration_location = get_location(&declaration->position());
|
|
||||||
tree declaration_tree = build_decl(declaration_location, VAR_DECL,
|
|
||||||
get_identifier(declaration->identifier().c_str()), declaration_type);
|
|
||||||
auto result = this->symbol_map->enter(declaration->identifier(), boot::make_info(declaration_tree));
|
|
||||||
|
|
||||||
if (result)
|
|
||||||
{
|
|
||||||
TREE_STATIC(declaration_tree) = 1;
|
|
||||||
varpool_node::get_create(declaration_tree);
|
|
||||||
varpool_node::finalize_decl(declaration_tree);
|
|
||||||
}
|
}
|
||||||
else
|
for (boot::variable_declaration *const variable : program->variables)
|
||||||
{
|
{
|
||||||
error_at(declaration_location, "variable '%s' already declared in this scope",
|
variable->accept(this);
|
||||||
declaration->identifier().c_str());
|
|
||||||
}
|
}
|
||||||
|
for (boot::procedure_definition *const procedure : program->procedures)
|
||||||
|
{
|
||||||
|
procedure->accept(this);
|
||||||
}
|
}
|
||||||
std::array<tree, 2> parameter_types{
|
std::array<tree, 2> parameter_types{
|
||||||
integer_type_node,
|
integer_type_node,
|
||||||
@ -149,7 +135,7 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
DECL_ARGUMENTS(this->main_fndecl) = argument_chain.head();
|
||||||
|
|
||||||
for (const auto body_statement : program->body)
|
for (boot::statement *const body_statement : program->body)
|
||||||
{
|
{
|
||||||
body_statement->accept(this);
|
body_statement->accept(this);
|
||||||
}
|
}
|
||||||
@ -359,7 +345,7 @@ namespace gcc
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (left_type != right_type)
|
if (left_type != right_type && !are_compatible_pointers(left, right))
|
||||||
{
|
{
|
||||||
error_at(expression_location,
|
error_at(expression_location,
|
||||||
"invalid operands of type %s and %s for operator %s",
|
"invalid operands of type %s and %s for operator %s",
|
||||||
@ -601,12 +587,23 @@ namespace gcc
|
|||||||
tree declaration_type = build_type(declaration->type());
|
tree declaration_type = build_type(declaration->type());
|
||||||
gcc_assert(declaration_type != NULL_TREE);
|
gcc_assert(declaration_type != NULL_TREE);
|
||||||
|
|
||||||
auto 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);
|
||||||
auto result = this->symbol_map->enter(declaration->identifier(), boot::make_info(declaration_tree));
|
bool result = this->symbol_map->enter(declaration->identifier(), boot::make_info(declaration_tree));
|
||||||
|
|
||||||
if (result)
|
if (!result)
|
||||||
|
{
|
||||||
|
error_at(declaration_location, "variable '%s' already declared in this scope",
|
||||||
|
declaration->identifier().c_str());
|
||||||
|
}
|
||||||
|
else if (this->main_fndecl == NULL_TREE)
|
||||||
|
{
|
||||||
|
TREE_STATIC(declaration_tree) = 1;
|
||||||
|
varpool_node::get_create(declaration_tree);
|
||||||
|
varpool_node::finalize_decl(declaration_tree);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
DECL_CONTEXT(declaration_tree) = this->main_fndecl;
|
||||||
variable_chain.append(declaration_tree);
|
variable_chain.append(declaration_tree);
|
||||||
@ -615,12 +612,6 @@ namespace gcc
|
|||||||
void_type_node, declaration_tree);
|
void_type_node, declaration_tree);
|
||||||
append_to_statement_list(declaration_statement, &this->current_statements);
|
append_to_statement_list(declaration_statement, &this->current_statements);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
error_at(declaration_location,
|
|
||||||
"variable '%s' already declared in this scope",
|
|
||||||
declaration->identifier().c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(boot::variable_expression *expression)
|
void generic_visitor::visit(boot::variable_expression *expression)
|
||||||
|
@ -23,6 +23,12 @@ namespace gcc
|
|||||||
return TREE_CODE(type) == POINTER_TYPE;
|
return TREE_CODE(type) == POINTER_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool are_compatible_pointers(tree lhs, tree rhs)
|
||||||
|
{
|
||||||
|
return (lhs == null_pointer_node || rhs == null_pointer_node)
|
||||||
|
&& is_pointer_type(TREE_TYPE(lhs)) && is_pointer_type(TREE_TYPE(rhs));
|
||||||
|
}
|
||||||
|
|
||||||
tree tree_chain_base::head()
|
tree tree_chain_base::head()
|
||||||
{
|
{
|
||||||
return first;
|
return first;
|
||||||
|
@ -650,9 +650,10 @@ namespace boot
|
|||||||
class program : public block
|
class program : public block
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::vector<definition *> type_definitions;
|
std::vector<type_definition *> types;
|
||||||
|
std::vector<procedure_definition *> procedures;
|
||||||
|
|
||||||
program(const struct position position, std::vector<definition *>&& type_definitions);
|
program(const struct position position);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
virtual ~program() override;
|
virtual ~program() override;
|
||||||
|
@ -24,6 +24,7 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
void init_ttree();
|
void init_ttree();
|
||||||
bool is_pointer_type(tree type);
|
bool is_pointer_type(tree type);
|
||||||
|
bool are_compatible_pointers(tree lhs, tree rhs);
|
||||||
|
|
||||||
class tree_chain_base
|
class tree_chain_base
|
||||||
{
|
{
|
||||||
|
142
source.elna
142
source.elna
@ -1,3 +1,21 @@
|
|||||||
|
const
|
||||||
|
SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2,
|
||||||
|
|
||||||
|
TOKEN_IDENTIFIER = 1, TOKEN_IF = 2, TOKEN_THEN = 3, TOKEN_ELSE = 4, TOKEN_ELSIF = 5,
|
||||||
|
TOKEN_WHILE = 6, TOKEN_DO = 7, TOKEN_PROC = 8, TOKEN_BEGIN = 9, TOKEN_END = 10,
|
||||||
|
TOKEN_EXTERN = 11, TOKEN_CONST = 12, TOKEN_VAR = 13, TOKEN_ARRAY = 14, TOKEN_OF = 15,
|
||||||
|
TOKEN_TYPE = 16, TOKEN_RECORD = 17, TOKEN_UNION = 18, TOKEN_POINTER = 19, TOKEN_TO = 20,
|
||||||
|
TOKEN_BOOLEAN = 21, TOKEN_NIL = 22, TOKEN_AND = 23, TOKEN_OR = 24, TOKEN_NOT = 25,
|
||||||
|
TOKEN_RETURN = 26, TOKEN_CAST = 27, TOKEN_AS = 28, TOKEN_SIZEOF = 29,
|
||||||
|
TOKEN_LEFT_PAREN = 30, TOKEN_RIGHT_PAREN = 31, TOKEN_LEFT_SQUARE = 32,
|
||||||
|
TOKEN_RIGHT_SQUARE = 33, TOKEN_GREATER_EQUAL = 34, TOKEN_LESS_EQUAL = 35,
|
||||||
|
TOKEN_GREATER_THAN = 36, TOKEN_LESS_THAN = 37, TOKEN_NOT_EQUAL = 38, TOKEN_EQUAL = 39,
|
||||||
|
TOKEN_SEMICOLON = 40, TOKEN_DOT = 41, TOKEN_COMMA = 42,
|
||||||
|
TOKEN_PLUS = 43, TOKEN_MINUS = 44, TOKEN_MULTIPLICATION = 45, TOKEN_DIVISION = 46,
|
||||||
|
TOKEN_REMAINDER = 47, TOKEN_ASSIGNMENT = 48, TOKEN_COLON = 49, TOKEN_HAT = 50,
|
||||||
|
TOKEN_AT = 51, TOKEN_COMMENT = 52, TOKEN_INTEGER = 53, TOKEN_WORD = 54,
|
||||||
|
TOKEN_CHARACTER = 55, TOKEN_STRING = 56;
|
||||||
|
|
||||||
type
|
type
|
||||||
Position = record
|
Position = record
|
||||||
line: Word;
|
line: Word;
|
||||||
@ -23,32 +41,29 @@ type
|
|||||||
end,
|
end,
|
||||||
CommandLine = record
|
CommandLine = record
|
||||||
input: pointer to Char
|
input: pointer to Char
|
||||||
|
end,
|
||||||
|
Literal = record
|
||||||
|
value: Int
|
||||||
|
end,
|
||||||
|
ConstantDefinition = record
|
||||||
|
name: pointer to Char;
|
||||||
|
body: pointer to Literal
|
||||||
|
end,
|
||||||
|
ConstantPart = record
|
||||||
|
elements: pointer to pointer to ConstantDefinition;
|
||||||
|
count: Word
|
||||||
|
end,
|
||||||
|
Program = record
|
||||||
|
constants: ConstantPart
|
||||||
end;
|
end;
|
||||||
|
|
||||||
const
|
|
||||||
SEEK_SET = 0, SEEK_CUR = 1, SEEK_END = 2,
|
|
||||||
|
|
||||||
TOKEN_IDENTIFIER = 1, TOKEN_IF = 2, TOKEN_THEN = 3, TOKEN_ELSE = 4, TOKEN_ELSIF = 5,
|
|
||||||
TOKEN_WHILE = 6, TOKEN_DO = 7, TOKEN_PROC = 8, TOKEN_BEGIN = 9, TOKEN_END = 10,
|
|
||||||
TOKEN_EXTERN = 11, TOKEN_CONST = 12, TOKEN_VAR = 13, TOKEN_ARRAY = 14, TOKEN_OF = 15,
|
|
||||||
TOKEN_TYPE = 16, TOKEN_RECORD = 17, TOKEN_UNION = 18, TOKEN_POINTER = 19, TOKEN_TO = 20,
|
|
||||||
TOKEN_BOOLEAN = 21, TOKEN_NIL = 22, TOKEN_AND = 23, TOKEN_OR = 24, TOKEN_NOT = 25,
|
|
||||||
TOKEN_RETURN = 26, TOKEN_CAST = 27, TOKEN_AS = 28, TOKEN_SIZEOF = 29,
|
|
||||||
TOKEN_LEFT_PAREN = 30, TOKEN_RIGHT_PAREN = 31, TOKEN_LEFT_SQUARE = 32,
|
|
||||||
TOKEN_RIGHT_SQUARE = 33, TOKEN_GREATER_EQUAL = 34, TOKEN_LESS_EQUAL = 35,
|
|
||||||
TOKEN_GREATER_THAN = 36, TOKEN_LESS_THAN = 37, TOKEN_NOT_EQUAL = 38, TOKEN_EQUAL = 39,
|
|
||||||
TOKEN_SEMICOLON = 40, TOKEN_DOT = 41, TOKEN_COMMA = 42,
|
|
||||||
TOKEN_PLUS = 43, TOKEN_MINUS = 44, TOKEN_MULTIPLICATION = 45, TOKEN_DIVISION = 46,
|
|
||||||
TOKEN_REMAINDER = 47, TOKEN_ASSIGNMENT = 48, TOKEN_COLON = 49, TOKEN_HAT = 50,
|
|
||||||
TOKEN_AT = 51, TOKEN_COMMENT = 52, TOKEN_INTEGER = 53, TOKEN_WORD = 54,
|
|
||||||
TOKEN_CHARACTER = 55, TOKEN_STRING = 56;
|
|
||||||
|
|
||||||
(*
|
(*
|
||||||
External procedures.
|
External procedures.
|
||||||
*)
|
*)
|
||||||
proc fopen(pathname: String, mode: String): pointer to FILE; extern;
|
proc fopen(pathname: String, mode: String): pointer to FILE; extern;
|
||||||
proc fclose(stream: pointer to FILE): Int; extern;
|
proc fclose(stream: pointer to FILE): Int; extern;
|
||||||
proc fseek(stream: pointer to FILE, off: Int, whence: Int): Int; extern;
|
proc fseek(stream: pointer to FILE, off: Int, whence: Int): Int; extern;
|
||||||
|
proc rewind(stream: pointer to FILE); extern;
|
||||||
proc ftell(stream: pointer to FILE): Int; extern;
|
proc ftell(stream: pointer to FILE): Int; extern;
|
||||||
proc fread(ptr: pointer to Byte, size: Word, nmemb: Word, stream: pointer to FILE): Word; extern;
|
proc fread(ptr: pointer to Byte, size: Word, nmemb: Word, stream: pointer to FILE): Word; extern;
|
||||||
proc write(fd: Int, buf: pointer to Byte, Word: Int): Int; extern;
|
proc write(fd: Int, buf: pointer to Byte, Word: Int): Int; extern;
|
||||||
@ -63,10 +78,12 @@ proc memset(ptr: pointer to Char, c: Int, n: Int): pointer to Char; 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 strlen(ptr: pointer to Char): Word; extern;
|
proc strlen(ptr: pointer to Char): Word; extern;
|
||||||
|
|
||||||
proc strtol(nptr: pointer to Char, endptr: pointer to pointer to Char, base: Int): Int; extern;
|
proc strtol(nptr: pointer to Char, endptr: pointer to pointer to Char, base: Int): Int; extern;
|
||||||
|
|
||||||
|
proc perror(s: pointer to Char); extern;
|
||||||
proc exit(code: Int); extern;
|
proc exit(code: Int); extern;
|
||||||
|
|
||||||
(*
|
(*
|
||||||
@ -152,13 +169,24 @@ var
|
|||||||
begin
|
begin
|
||||||
input_file := fopen(filename, "rb");
|
input_file := fopen(filename, "rb");
|
||||||
|
|
||||||
fseek(input_file, 0, SEEK_END);
|
if input_file = nil then
|
||||||
|
return nil
|
||||||
|
end;
|
||||||
|
if fseek(input_file, 0, SEEK_END) <> 0 then
|
||||||
|
fclose(input_file);
|
||||||
|
return nil
|
||||||
|
end;
|
||||||
source_size := ftell(input_file);
|
source_size := ftell(input_file);
|
||||||
fseek(input_file, 0, SEEK_SET);
|
if source_size < 0 then
|
||||||
|
fclose(input_file);
|
||||||
|
return nil
|
||||||
|
end;
|
||||||
|
rewind(input_file);
|
||||||
|
|
||||||
input := calloc(source_size + 1, 1);
|
input := calloc(source_size + 1, 1);
|
||||||
fread(input, source_size, 1, input_file);
|
if fread(input, source_size, 1, input_file) <> 1u then
|
||||||
|
input := cast(nil as pointer to Byte)
|
||||||
|
end;
|
||||||
fclose(input_file);
|
fclose(input_file);
|
||||||
|
|
||||||
return input
|
return input
|
||||||
@ -551,7 +579,7 @@ begin
|
|||||||
if input_pointer^ = '*' then
|
if input_pointer^ = '*' then
|
||||||
token_end := lex_comment(input_pointer + 1);
|
token_end := lex_comment(input_pointer + 1);
|
||||||
|
|
||||||
if token_end <> cast(nil as pointer to Char) then
|
if token_end <> nil then
|
||||||
token_length := cast(token_end as Word) - cast(input_pointer as Word);
|
token_length := cast(token_end as Word) - cast(input_pointer as Word);
|
||||||
current_token^.value.string_value := cast(calloc(token_length + 1u, 1) as pointer to Char);
|
current_token^.value.string_value := cast(calloc(token_length + 1u, 1) as pointer to Char);
|
||||||
strncpy(current_token^.value.string_value, input_pointer, token_length);
|
strncpy(current_token^.value.string_value, input_pointer, token_length);
|
||||||
@ -667,6 +695,65 @@ begin
|
|||||||
return tokens
|
return tokens
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
proc parse_literal(tokens: pointer to pointer to Token, tokens_size: pointer to Word): pointer to Literal;
|
||||||
|
begin
|
||||||
|
return cast(calloc(1, sizeof(Literal)) as pointer to Literal)
|
||||||
|
end;
|
||||||
|
|
||||||
|
proc parse_constant_definition(tokens: pointer to pointer to Token,
|
||||||
|
tokens_size: pointer to Word): pointer to ConstantDefinition;
|
||||||
|
var
|
||||||
|
result: pointer to ConstantDefinition;
|
||||||
|
begin
|
||||||
|
result := cast(calloc(1, sizeof(ConstantDefinition)) as pointer to ConstantDefinition);
|
||||||
|
|
||||||
|
result^.name := cast(malloc(strlen(tokens^^.value.string_value)) as pointer to Char);
|
||||||
|
strcpy(result^.name, tokens^^.value.string_value);
|
||||||
|
|
||||||
|
tokens^ := tokens^ + sizeof(Token) * 2u;
|
||||||
|
tokens_size := tokens_size - sizeof(Token) * 2u;
|
||||||
|
|
||||||
|
write_s(result^.name);
|
||||||
|
write_c('\n');
|
||||||
|
|
||||||
|
result^.body := parse_literal(tokens, tokens_size);
|
||||||
|
|
||||||
|
tokens^ := tokens^ + sizeof(Token) * 2u;
|
||||||
|
tokens_size := tokens_size - sizeof(Token) * 2u;
|
||||||
|
|
||||||
|
return result
|
||||||
|
end;
|
||||||
|
|
||||||
|
proc parse_program(tokens: pointer to pointer to Token, tokens_size: pointer to Word): pointer to Program;
|
||||||
|
var
|
||||||
|
result: pointer to Program,
|
||||||
|
current_constant: pointer to pointer to ConstantDefinition;
|
||||||
|
begin
|
||||||
|
result := cast(calloc(1, sizeof(Program)) as pointer to Program);
|
||||||
|
|
||||||
|
result^.constants.elements := cast(nil as pointer to pointer to ConstantDefinition);
|
||||||
|
result^.constants.count := 0u;
|
||||||
|
|
||||||
|
if tokens^^.kind = TOKEN_CONST then
|
||||||
|
tokens^ := tokens^ + sizeof(Token);
|
||||||
|
tokens_size^ := tokens_size^ - sizeof(Token);
|
||||||
|
|
||||||
|
while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do
|
||||||
|
result^.constants.elements := cast(
|
||||||
|
reallocarray(result^.constants.elements, result^.constants.count + 1u, sizeof(pointer to ConstantDefinition))
|
||||||
|
as pointer to pointer to ConstantDefinition);
|
||||||
|
current_constant := result^.constants.elements + result^.constants.count * sizeof(pointer to ConstantDefinition);
|
||||||
|
|
||||||
|
result^.constants.count := result^.constants.count + 1u;
|
||||||
|
|
||||||
|
current_constant^ := parse_constant_definition(tokens, tokens_size);
|
||||||
|
if current_constant^ = nil then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
proc parse_command_line(argc: Int, argv: pointer to pointer to Char): pointer to CommandLine;
|
proc parse_command_line(argc: Int, argv: pointer to pointer to Char): pointer to CommandLine;
|
||||||
var
|
var
|
||||||
parameter: pointer to pointer to Char,
|
parameter: pointer to pointer to Char,
|
||||||
@ -712,11 +799,16 @@ begin
|
|||||||
return 2
|
return 2
|
||||||
end;
|
end;
|
||||||
input := read_source(command_line^.input);
|
input := read_source(command_line^.input);
|
||||||
|
if input = nil then
|
||||||
|
perror(command_line^.input);
|
||||||
|
return 3
|
||||||
|
end;
|
||||||
tokens := tokenize(input, @tokens_size);
|
tokens := tokenize(input, @tokens_size);
|
||||||
|
|
||||||
free(input);
|
print_tokens(tokens, tokens_size);
|
||||||
|
|
||||||
print_tokens(tokens, tokens_size)
|
parse_program(@tokens, @tokens_size);
|
||||||
|
return 0
|
||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
Loading…
x
Reference in New Issue
Block a user