Support else in if then conditions
This commit is contained in:
parent
c558c3d6b4
commit
75a691134f
4
config-lang.in
Normal file
4
config-lang.in
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
language="elna"
|
||||||
|
gcc_subdir="elna/gcc"
|
||||||
|
|
||||||
|
. ${srcdir}/elna/gcc/config-lang.in
|
@ -89,14 +89,27 @@ elna.stageprofile: stageprofile-start
|
|||||||
elna.stagefeedback: stagefeedback-start
|
elna.stagefeedback: stagefeedback-start
|
||||||
-mv elna/*$(objext) stagefeedback/elna
|
-mv elna/*$(objext) stagefeedback/elna
|
||||||
|
|
||||||
ELNA_INCLUDES = -I $(srcdir)/elna -I $(srcdir)/elna/generated
|
ELNA_INCLUDES = -I $(srcdir)/elna/include -I elna/generated
|
||||||
|
|
||||||
CFLAGS-elna/elna1.o += $(ELNA_INCLUDES)
|
elna/%.o: elna/source/%.cc elna/generated/parser.hh elna/generated/location.hh
|
||||||
|
|
||||||
elna/%.o: elna/source/%.cc
|
|
||||||
$(COMPILE) $(ELNA_INCLUDES) $<
|
$(COMPILE) $(ELNA_INCLUDES) $<
|
||||||
$(POSTCOMPILE)
|
$(POSTCOMPILE)
|
||||||
|
|
||||||
elna/%.o: elna/generated/%.cc
|
elna/%.o: elna/generated/%.cc elna/generated/parser.hh elna/generated/location.hh
|
||||||
$(COMPILE) $(ELNA_INCLUDES) $<
|
$(COMPILE) $(ELNA_INCLUDES) $<
|
||||||
$(POSTCOMPILE)
|
$(POSTCOMPILE)
|
||||||
|
|
||||||
|
elna/%.o: elna/gcc/%.cc elna/generated/parser.hh elna/generated/location.hh
|
||||||
|
$(COMPILE) $(ELNA_INCLUDES) $<
|
||||||
|
$(POSTCOMPILE)
|
||||||
|
|
||||||
|
elna/generated/parser.cc: elna/source/parser.yy
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
$(BISON) -d -o $@ $<
|
||||||
|
|
||||||
|
elna/generated/parser.hh elna/generated/location.hh: elna/generated/parser.cc
|
||||||
|
@touch $@
|
||||||
|
|
||||||
|
elna/generated/lexer.cc: elna/source/lexer.ll
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
$(FLEX) -o $@ $<
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# gcc-src/gcc/config/config-lang.in
|
|
||||||
language="elna"
|
language="elna"
|
||||||
|
gcc_subdir="elna/gcc"
|
||||||
|
|
||||||
compilers="elna1\$(exeext)"
|
compilers="elna1\$(exeext)"
|
||||||
|
|
||||||
target_libs=""
|
target_libs=""
|
||||||
|
|
||||||
gtfiles="\$(srcdir)/elna/elna1.cc"
|
gtfiles="\$(srcdir)/elna/gcc/elna1.cc"
|
||||||
|
|
||||||
lang_requires_boot_languages=c++
|
lang_requires_boot_languages=c++
|
||||||
|
|
||||||
|
@ -118,20 +118,25 @@ namespace gcc
|
|||||||
|
|
||||||
auto expression_location = get_location(&expression->position());
|
auto expression_location = get_location(&expression->position());
|
||||||
tree_code operator_code = ERROR_MARK;
|
tree_code operator_code = ERROR_MARK;
|
||||||
|
tree target_type = error_mark_node;
|
||||||
|
|
||||||
switch (expression->operation())
|
switch (expression->operation())
|
||||||
{
|
{
|
||||||
case source::binary_operator::sum:
|
case source::binary_operator::sum:
|
||||||
operator_code = PLUS_EXPR;
|
operator_code = PLUS_EXPR;
|
||||||
|
target_type = integer_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::subtraction:
|
case source::binary_operator::subtraction:
|
||||||
operator_code = MINUS_EXPR;
|
operator_code = MINUS_EXPR;
|
||||||
|
target_type = integer_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::division:
|
case source::binary_operator::division:
|
||||||
operator_code = TRUNC_DIV_EXPR;
|
operator_code = TRUNC_DIV_EXPR;
|
||||||
|
target_type = integer_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::multiplication:
|
case source::binary_operator::multiplication:
|
||||||
operator_code = MULT_EXPR;
|
operator_code = MULT_EXPR;
|
||||||
|
target_type = integer_type_node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (operator_code != ERROR_MARK) // An arithmetic operation.
|
if (operator_code != ERROR_MARK) // An arithmetic operation.
|
||||||
@ -150,21 +155,27 @@ namespace gcc
|
|||||||
{
|
{
|
||||||
case source::binary_operator::equals:
|
case source::binary_operator::equals:
|
||||||
operator_code = EQ_EXPR;
|
operator_code = EQ_EXPR;
|
||||||
|
target_type = boolean_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::not_equals:
|
case source::binary_operator::not_equals:
|
||||||
operator_code = NE_EXPR;
|
operator_code = NE_EXPR;
|
||||||
|
target_type = boolean_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::less:
|
case source::binary_operator::less:
|
||||||
operator_code = LT_EXPR;
|
operator_code = LT_EXPR;
|
||||||
|
target_type = boolean_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::greater:
|
case source::binary_operator::greater:
|
||||||
operator_code = GT_EXPR;
|
operator_code = GT_EXPR;
|
||||||
|
target_type = boolean_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::less_equal:
|
case source::binary_operator::less_equal:
|
||||||
operator_code = LE_EXPR;
|
operator_code = LE_EXPR;
|
||||||
|
target_type = boolean_type_node;
|
||||||
break;
|
break;
|
||||||
case source::binary_operator::greater_equal:
|
case source::binary_operator::greater_equal:
|
||||||
operator_code = GE_EXPR;
|
operator_code = GE_EXPR;
|
||||||
|
target_type = boolean_type_node;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (left_type != right_type)
|
if (left_type != right_type)
|
||||||
@ -176,8 +187,11 @@ namespace gcc
|
|||||||
this->current_expression = error_mark_node;
|
this->current_expression = error_mark_node;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
gcc_assert(operator_code != ERROR_MARK);
|
||||||
|
gcc_assert(target_type != error_mark_node);
|
||||||
|
|
||||||
this->current_expression = build2_loc(expression_location,
|
this->current_expression = build2_loc(expression_location,
|
||||||
operator_code, integer_type_node, left, right);
|
operator_code, target_type, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
void generic_visitor::visit(source::constant_definition *definition)
|
void generic_visitor::visit(source::constant_definition *definition)
|
||||||
@ -210,16 +224,25 @@ namespace gcc
|
|||||||
|
|
||||||
void generic_visitor::visit(source::declaration *declaration)
|
void generic_visitor::visit(source::declaration *declaration)
|
||||||
{
|
{
|
||||||
if (declaration->type().base() != "Int" && declaration->type().base() != "Bool")
|
tree declaration_type = error_mark_node;
|
||||||
|
|
||||||
|
if (declaration->type().base() == "Int")
|
||||||
|
{
|
||||||
|
declaration_type = integer_type_node;
|
||||||
|
}
|
||||||
|
else if (declaration->type().base() == "Bool")
|
||||||
|
{
|
||||||
|
declaration_type = boolean_type_node;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
error_at(get_location(&declaration->type().position()),
|
error_at(get_location(&declaration->type().position()),
|
||||||
"type '%s' not declared",
|
"type '%s' not declared", declaration->type().base().c_str());
|
||||||
declaration->type().base().c_str());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
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()), integer_type_node);
|
get_identifier(declaration->identifier().c_str()), declaration_type);
|
||||||
auto result = this->symbol_map.insert({ declaration->identifier(), declaration_tree });
|
auto result = this->symbol_map.insert({ declaration->identifier(), declaration_tree });
|
||||||
|
|
||||||
if (result.second)
|
if (result.second)
|
||||||
@ -312,8 +335,21 @@ namespace gcc
|
|||||||
auto goto_endif = build1_loc(prerequisite_location, GOTO_EXPR,
|
auto goto_endif = build1_loc(prerequisite_location, GOTO_EXPR,
|
||||||
void_type_node, endif_label_decl);
|
void_type_node, endif_label_decl);
|
||||||
|
|
||||||
|
tree else_label_decl = NULL_TREE;
|
||||||
|
tree goto_else_or_endif = NULL_TREE;
|
||||||
|
if (statement->alternative() != nullptr)
|
||||||
|
{
|
||||||
|
auto else_location = get_location(&statement->alternative()->position());
|
||||||
|
else_label_decl = build_label_decl("else", else_location);
|
||||||
|
goto_else_or_endif = build1_loc(else_location, GOTO_EXPR, void_type_node, else_label_decl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
goto_else_or_endif = goto_endif;
|
||||||
|
}
|
||||||
|
|
||||||
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
|
auto cond_expr = build3_loc(prerequisite_location, COND_EXPR,
|
||||||
void_type_node, this->current_expression, goto_then, goto_endif);
|
void_type_node, this->current_expression, goto_then, goto_else_or_endif);
|
||||||
append_to_statement_list(cond_expr, &this->current_statements);
|
append_to_statement_list(cond_expr, &this->current_statements);
|
||||||
|
|
||||||
auto then_label_expr = build1_loc(then_location, LABEL_EXPR,
|
auto then_label_expr = build1_loc(then_location, LABEL_EXPR,
|
||||||
@ -322,6 +358,13 @@ namespace gcc
|
|||||||
|
|
||||||
statement->body().accept(this);
|
statement->body().accept(this);
|
||||||
|
|
||||||
|
if (statement->alternative() != nullptr)
|
||||||
|
{
|
||||||
|
auto else_label_expr = build1(LABEL_EXPR, void_type_node, else_label_decl);
|
||||||
|
append_to_statement_list(else_label_expr, &this->current_statements);
|
||||||
|
|
||||||
|
statement->alternative()->accept(this);
|
||||||
|
}
|
||||||
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
|
auto endif_label_expr = build1(LABEL_EXPR, void_type_node, endif_label_decl);
|
||||||
append_to_statement_list(endif_label_expr, &this->current_statements);
|
append_to_statement_list(endif_label_expr, &this->current_statements);
|
||||||
|
|
||||||
|
@ -361,19 +361,22 @@ namespace source
|
|||||||
{
|
{
|
||||||
std::unique_ptr<expression> m_prerequisite;
|
std::unique_ptr<expression> m_prerequisite;
|
||||||
std::unique_ptr<statement> m_body;
|
std::unique_ptr<statement> m_body;
|
||||||
|
std::unique_ptr<statement> m_alternative;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* \param position Source code position.
|
* \param position Source code position.
|
||||||
* \param prerequisite Condition.
|
* \param prerequisite Condition.
|
||||||
* \param body Statement executed if the condition is met.
|
* \param body Statement executed if the condition is met.
|
||||||
|
* \param alternative Statement executed if the condition is not met.
|
||||||
*/
|
*/
|
||||||
if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
||||||
std::unique_ptr<statement>&& body);
|
std::unique_ptr<statement>&& body, std::unique_ptr<statement>&& alternative = nullptr);
|
||||||
virtual void accept(parser_visitor *visitor) override;
|
virtual void accept(parser_visitor *visitor) override;
|
||||||
|
|
||||||
expression& prerequisite();
|
expression& prerequisite();
|
||||||
statement& body();
|
statement& body();
|
||||||
|
std::unique_ptr<statement>& alternative();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -485,8 +485,9 @@ namespace source
|
|||||||
}
|
}
|
||||||
|
|
||||||
if_statement::if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
if_statement::if_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
||||||
std::unique_ptr<statement>&& body)
|
std::unique_ptr<statement>&& body, std::unique_ptr<statement>&& alternative)
|
||||||
: statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
: statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body)),
|
||||||
|
m_alternative(std::move(alternative))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,6 +506,11 @@ namespace source
|
|||||||
return *m_body;
|
return *m_body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<statement>& if_statement::alternative()
|
||||||
|
{
|
||||||
|
return m_alternative;
|
||||||
|
}
|
||||||
|
|
||||||
while_statement::while_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
while_statement::while_statement(const struct position position, std::unique_ptr<expression>&& prerequisite,
|
||||||
std::unique_ptr<statement>&& body)
|
std::unique_ptr<statement>&& body)
|
||||||
: statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
: statement(position), m_prerequisite(std::move(prerequisite)), m_body(std::move(body))
|
||||||
|
@ -37,6 +37,9 @@ if {
|
|||||||
then {
|
then {
|
||||||
return yy::parser::make_THEN(this->location);
|
return yy::parser::make_THEN(this->location);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return yy::parser::make_ELSE(this->location);
|
||||||
|
}
|
||||||
while {
|
while {
|
||||||
return yy::parser::make_WHILE(this->location);
|
return yy::parser::make_WHILE(this->location);
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@
|
|||||||
%token <std::string> IDENTIFIER "identifier"
|
%token <std::string> IDENTIFIER "identifier"
|
||||||
%token <std::int32_t> NUMBER "number"
|
%token <std::int32_t> NUMBER "number"
|
||||||
%token <bool> BOOLEAN
|
%token <bool> BOOLEAN
|
||||||
%token IF THEN WHILE DO
|
%token IF WHILE DO
|
||||||
%token CONST VAR PROCEDURE
|
%token CONST VAR PROCEDURE
|
||||||
%token BEGIN_BLOCK END_BLOCK
|
%token BEGIN_BLOCK END_BLOCK
|
||||||
%token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA
|
%token LEFT_PAREN RIGHT_PAREN SEMICOLON DOT COMMA
|
||||||
@ -67,6 +67,9 @@
|
|||||||
%token PLUS MINUS MULTIPLICATION DIVISION
|
%token PLUS MINUS MULTIPLICATION DIVISION
|
||||||
%token ASSIGNMENT COLON HAT AT
|
%token ASSIGNMENT COLON HAT AT
|
||||||
|
|
||||||
|
%precedence THEN
|
||||||
|
%precedence ELSE
|
||||||
|
|
||||||
%type <std::unique_ptr<elna::source::integer_literal>> integer_literal;
|
%type <std::unique_ptr<elna::source::integer_literal>> integer_literal;
|
||||||
%type <std::unique_ptr<elna::source::boolean_literal>> boolean_literal;
|
%type <std::unique_ptr<elna::source::boolean_literal>> boolean_literal;
|
||||||
%type <std::unique_ptr<elna::source::constant_definition>> constant_definition;
|
%type <std::unique_ptr<elna::source::constant_definition>> constant_definition;
|
||||||
@ -169,6 +172,11 @@ if_statement:
|
|||||||
$$ = std::make_unique<elna::source::if_statement>(elna::source::make_position(@1),
|
$$ = std::make_unique<elna::source::if_statement>(elna::source::make_position(@1),
|
||||||
std::move($2), std::move($4));
|
std::move($2), std::move($4));
|
||||||
}
|
}
|
||||||
|
| IF expression THEN statement ELSE statement
|
||||||
|
{
|
||||||
|
$$ = std::make_unique<elna::source::if_statement>(elna::source::make_position(@1),
|
||||||
|
std::move($2), std::move($4), std::move($6));
|
||||||
|
}
|
||||||
pointer:
|
pointer:
|
||||||
integer_literal { $$ = std::move($1); }
|
integer_literal { $$ = std::move($1); }
|
||||||
| boolean_literal { $$ = std::move($1); }
|
| boolean_literal { $$ = std::move($1); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user