Add source location to all AST nodes
This commit is contained in:
parent
6a3835951f
commit
16680ad801
16 changed files with 204 additions and 70 deletions
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <pslang/ast/expression_fwd.hpp>
|
||||
#include <pslang/ast/location.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -10,12 +11,14 @@ namespace pslang::ast
|
|||
struct array
|
||||
{
|
||||
std::vector<expression_ptr> elements;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct array_access
|
||||
{
|
||||
expression_ptr array;
|
||||
expression_ptr index;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <pslang/ast/expression_fwd.hpp>
|
||||
#include <pslang/ast/location.hpp>
|
||||
#include <pslang/type/type.hpp>
|
||||
|
||||
namespace pslang::ast
|
||||
|
|
@ -10,6 +11,7 @@ namespace pslang::ast
|
|||
{
|
||||
expression_ptr expression;
|
||||
type::type_ptr type;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <pslang/ast/expression_fwd.hpp>
|
||||
#include <pslang/ast/statement_fwd.hpp>
|
||||
#include <pslang/ast/location.hpp>
|
||||
|
||||
namespace pslang::ast
|
||||
{
|
||||
|
|
@ -13,17 +14,20 @@ namespace pslang::ast
|
|||
{
|
||||
expression_ptr condition;
|
||||
statement_list_ptr statements;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct else_block
|
||||
{
|
||||
statement_list_ptr statements;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct else_if_block
|
||||
{
|
||||
expression_ptr condition;
|
||||
statement_list_ptr statements;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
// Interpreted as a consecutive "if -> else if -> else if -> else" chain
|
||||
|
|
@ -38,12 +42,14 @@ namespace pslang::ast
|
|||
};
|
||||
|
||||
std::vector<block> blocks;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct while_block
|
||||
{
|
||||
expression_ptr condition;
|
||||
statement_list_ptr statements;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <pslang/ast/location.hpp>
|
||||
#include <pslang/ast/literal.hpp>
|
||||
#include <pslang/ast/identifier.hpp>
|
||||
#include <pslang/ast/operation.hpp>
|
||||
|
|
@ -16,6 +17,7 @@ namespace pslang::ast
|
|||
{
|
||||
unary_operation_type type;
|
||||
expression_ptr arg1;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct binary_operation
|
||||
|
|
@ -23,6 +25,7 @@ namespace pslang::ast
|
|||
binary_operation_type type;
|
||||
expression_ptr arg1;
|
||||
expression_ptr arg2;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
using expression_impl = std::variant<
|
||||
|
|
@ -43,4 +46,6 @@ namespace pslang::ast
|
|||
using expression_impl::expression_impl;
|
||||
};
|
||||
|
||||
location get_location(expression const & expression);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <pslang/ast/statement_fwd.hpp>
|
||||
#include <pslang/ast/expression_fwd.hpp>
|
||||
#include <pslang/ast/location.hpp>
|
||||
#include <pslang/type/type_fwd.hpp>
|
||||
|
||||
#include <string>
|
||||
|
|
@ -16,18 +17,21 @@ namespace pslang::ast
|
|||
{
|
||||
std::string name;
|
||||
type::type_ptr type;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
std::string name;
|
||||
std::vector<argument> arguments;
|
||||
type::type_ptr return_type;
|
||||
statement_list_ptr statements;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct function_call
|
||||
{
|
||||
std::string name;
|
||||
std::vector<expression_ptr> arguments;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <pslang/ast/location.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace pslang::ast
|
||||
|
|
@ -8,6 +10,7 @@ namespace pslang::ast
|
|||
struct identifier
|
||||
{
|
||||
std::string name;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <pslang/ast/location.hpp>
|
||||
|
||||
#include <variant>
|
||||
#include <cstdint>
|
||||
|
||||
|
|
@ -10,6 +12,7 @@ namespace pslang::ast
|
|||
struct numeric_literal_base
|
||||
{
|
||||
T value;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
using bool_literal = numeric_literal_base<bool>;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,15 @@ namespace pslang::ast
|
|||
}
|
||||
};
|
||||
|
||||
inline location merge(location const & l1,location const & l2)
|
||||
{
|
||||
return location {
|
||||
.filename = l1.filename,
|
||||
.begin = l1.begin,
|
||||
.end = l2.end,
|
||||
};
|
||||
}
|
||||
|
||||
inline std::ostream & operator << (std::ostream & out, location const & location)
|
||||
{
|
||||
out << location.filename << ':' << location.begin.line << '.' << location.begin.column;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <pslang/ast/location.hpp>
|
||||
#include <pslang/ast/expression.hpp>
|
||||
#include <pslang/ast/value_category.hpp>
|
||||
#include <pslang/ast/control.hpp>
|
||||
|
|
@ -19,18 +20,21 @@ namespace pslang::ast
|
|||
std::string name;
|
||||
type::type_ptr type;
|
||||
expression_ptr initializer;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct assignment
|
||||
{
|
||||
expression_ptr lhs;
|
||||
expression_ptr rhs;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct return_statement
|
||||
{
|
||||
// can be null, which means "return unit"
|
||||
expression_ptr value;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
using statement_impl = std::variant<
|
||||
|
|
@ -54,4 +58,6 @@ namespace pslang::ast
|
|||
using statement_impl::statement_impl;
|
||||
};
|
||||
|
||||
location get_location(statement const & statement);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <pslang/type/type_fwd.hpp>
|
||||
#include <pslang/ast/expression_fwd.hpp>
|
||||
#include <pslang/ast/location.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
@ -13,18 +14,21 @@ namespace pslang::ast
|
|||
{
|
||||
std::string name;
|
||||
type::type_ptr type;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct struct_definition
|
||||
{
|
||||
std::string name;
|
||||
std::vector<field_definition> fields;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
struct field_access
|
||||
{
|
||||
expression_ptr object;
|
||||
std::string field_name;
|
||||
ast::location location;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
38
libs/ast/source/expression.cpp
Normal file
38
libs/ast/source/expression.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#include <pslang/ast/expression.hpp>
|
||||
|
||||
namespace pslang::ast
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
location get_location_impl(numeric_literal_base<T> const & expression)
|
||||
{
|
||||
return expression.location;
|
||||
}
|
||||
|
||||
location get_location_impl(literal const & expression)
|
||||
{
|
||||
return std::visit([](auto const & expression){ return get_location_impl(expression); }, expression);
|
||||
}
|
||||
|
||||
template <typename Expression>
|
||||
location get_location_impl(Expression const & expression)
|
||||
{
|
||||
return expression.location;
|
||||
}
|
||||
|
||||
location get_location_impl(expression const & expression)
|
||||
{
|
||||
return std::visit([](auto const & expression){ return get_location_impl(expression); }, expression);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
location get_location(expression const & expression)
|
||||
{
|
||||
return get_location_impl(expression);
|
||||
}
|
||||
|
||||
}
|
||||
32
libs/ast/source/statement.cpp
Normal file
32
libs/ast/source/statement.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#include <pslang/ast/statement.hpp>
|
||||
|
||||
namespace pslang::ast
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
location get_location_impl(expression_ptr const & statement)
|
||||
{
|
||||
return get_location(*statement);
|
||||
}
|
||||
|
||||
template <typename Statement>
|
||||
location get_location_impl(Statement const & statement)
|
||||
{
|
||||
return statement.location;
|
||||
}
|
||||
|
||||
location get_location_impl(statement const & statement)
|
||||
{
|
||||
return std::visit([](auto const & statement){ return get_location_impl(statement); }, statement);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
location get_location(statement const & statement)
|
||||
{
|
||||
return get_location_impl(statement);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
#include <pslang/ast/expression.hpp>
|
||||
#include <pslang/type/print.hpp>
|
||||
|
||||
#include <pslang/parser/error.hpp>
|
||||
|
||||
#include <sstream>
|
||||
#include <optional>
|
||||
|
||||
|
|
|
|||
|
|
@ -35,4 +35,20 @@ namespace pslang::parser
|
|||
ast::location location_;
|
||||
};
|
||||
|
||||
struct internal_error
|
||||
: std::exception
|
||||
{
|
||||
internal_error(std::string message)
|
||||
: message_(message)
|
||||
{}
|
||||
|
||||
char const * what() const noexcept
|
||||
{
|
||||
return message_.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string message_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,13 +56,13 @@ struct context;
|
|||
YY_DECL;
|
||||
|
||||
template <typename T>
|
||||
::pslang::ast::literal parse_numeric_literal(std::string const & str)
|
||||
::pslang::ast::literal parse_numeric_literal(std::string const & str, ::pslang::ast::location const & location)
|
||||
{
|
||||
T value;
|
||||
auto result = std::from_chars(str.data(), str.data() + str.size(), value);
|
||||
if (result.ec != std::errc())
|
||||
throw std::system_error(std::make_error_code(result.ec));
|
||||
return ::pslang::ast::numeric_literal_base<T>{value};
|
||||
return ::pslang::ast::numeric_literal_base<T>{value, location};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -185,17 +185,17 @@ indentation
|
|||
|
||||
statement
|
||||
: expression { $$ = std::make_unique<ast::expression>($1); }
|
||||
| expression assignment expression { $$ = ast::assignment{ std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| expression assignment expression { $$ = ast::assignment{ std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| variable_declaration { $$ = $1; }
|
||||
| if expression colon { $$ = ast::if_block{std::make_unique<ast::expression>($2), {}}; }
|
||||
| else colon { $$ = ast::else_block{{}}; }
|
||||
| else if expression colon { $$ = ast::else_if_block{std::make_unique<ast::expression>($3), {}}; }
|
||||
| while expression colon { $$ = ast::while_block{std::make_unique<ast::expression>($2), {}}; }
|
||||
| func name lparen function_definition_argument_list rparen function_return_type colon { $$ = ast::function_definition{$2, $4, $6, {}}; }
|
||||
| return expression { $$ = ast::return_statement{std::make_unique<ast::expression>($2)}; }
|
||||
| return { $$ = ast::return_statement{nullptr}; }
|
||||
| struct name colon { $$ = ast::struct_definition{$2, {}}; }
|
||||
| name colon type_expression { $$ = ast::field_definition{$1, std::make_unique<type::type>($3)}; }
|
||||
| if expression colon { $$ = ast::if_block{std::make_unique<ast::expression>($2), {}, @$}; }
|
||||
| else colon { $$ = ast::else_block{{}, @$}; }
|
||||
| else if expression colon { $$ = ast::else_if_block{std::make_unique<ast::expression>($3), {}, @$}; }
|
||||
| while expression colon { $$ = ast::while_block{std::make_unique<ast::expression>($2), {}, @$}; }
|
||||
| func name lparen function_definition_argument_list rparen function_return_type colon { $$ = ast::function_definition{$2, $4, $6, {}, @$}; }
|
||||
| return expression { $$ = ast::return_statement{std::make_unique<ast::expression>($2), @$}; }
|
||||
| return { $$ = ast::return_statement{nullptr, @$}; }
|
||||
| struct name colon { $$ = ast::struct_definition{$2, {}, @$}; }
|
||||
| name colon type_expression { $$ = ast::field_definition{$1, std::make_unique<type::type>($3), @$}; }
|
||||
;
|
||||
|
||||
function_definition_argument_list
|
||||
|
|
@ -204,7 +204,7 @@ function_definition_argument_list
|
|||
;
|
||||
|
||||
nonempty_function_definition_argument_list
|
||||
: name colon type_expression { std::vector<ast::function_definition::argument> tmp; tmp.push_back({.name = $1, .type = std::make_unique<type::type>($3)}); $$ = std::move(tmp); }
|
||||
: name colon type_expression { std::vector<ast::function_definition::argument> tmp; tmp.push_back({.name = $1, .type = std::make_unique<type::type>($3), @$}); $$ = std::move(tmp); }
|
||||
| nonempty_function_definition_argument_list comma name colon type_expression { auto tmp = $1; tmp.push_back({.name = $3, .type = std::make_unique<type::type>($5)}); $$ = std::move(tmp); }
|
||||
;
|
||||
|
||||
|
|
@ -214,8 +214,8 @@ function_return_type
|
|||
;
|
||||
|
||||
variable_declaration
|
||||
: variable_keyword name assignment expression { $$ = ast::variable_declaration{$1, $2, nullptr, std::make_unique<ast::expression>($4)}; }
|
||||
| variable_keyword name colon type_expression assignment expression { $$ = ast::variable_declaration{$1, $2, std::make_unique<type::type>($4), std::make_unique<ast::expression>($6)}; }
|
||||
: variable_keyword name assignment expression { $$ = ast::variable_declaration{$1, $2, nullptr, std::make_unique<ast::expression>($4), @$}; }
|
||||
| variable_keyword name colon type_expression assignment expression { $$ = ast::variable_declaration{$1, $2, std::make_unique<type::type>($4), std::make_unique<ast::expression>($6), @$}; }
|
||||
;
|
||||
|
||||
variable_keyword
|
||||
|
|
@ -251,61 +251,61 @@ expression
|
|||
|
||||
bool_expression
|
||||
: compare_expression { $$ = $1; }
|
||||
| bool_expression ampersand compare_expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_and, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| bool_expression vertical_bar compare_expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_or, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| bool_expression circumflex compare_expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_xor, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| bool_expression ampersand compare_expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_and, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| bool_expression vertical_bar compare_expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_or, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| bool_expression circumflex compare_expression { $$ = ast::binary_operation{ast::binary_operation_type::logical_xor, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
;
|
||||
|
||||
compare_expression
|
||||
: as_expression { $$ = $1; }
|
||||
| compare_expression equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| compare_expression not_equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::not_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| compare_expression less as_expression { $$ = ast::binary_operation{ast::binary_operation_type::less, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| compare_expression greater as_expression { $$ = ast::binary_operation{ast::binary_operation_type::greater, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| compare_expression less_equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| compare_expression greater_equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| compare_expression equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| compare_expression not_equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::not_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| compare_expression less as_expression { $$ = ast::binary_operation{ast::binary_operation_type::less, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| compare_expression greater as_expression { $$ = ast::binary_operation{ast::binary_operation_type::greater, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| compare_expression less_equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::less_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| compare_expression greater_equals as_expression { $$ = ast::binary_operation{ast::binary_operation_type::greater_equals, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
;
|
||||
|
||||
as_expression
|
||||
: negate_expression { $$ = $1; }
|
||||
| negate_expression as type_expression { $$ = ast::cast_operation{ std::make_unique<ast::expression>($1), std::make_unique<type::type>($3) }; }
|
||||
| negate_expression as type_expression { $$ = ast::cast_operation{ std::make_unique<ast::expression>($1), std::make_unique<type::type>($3), @$ }; }
|
||||
;
|
||||
|
||||
negate_expression
|
||||
: sum_expression { $$ = $1; }
|
||||
| minus sum_expression { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique<ast::expression>($2) }; }
|
||||
| minus sum_expression { $$ = ast::unary_operation{ast::unary_operation_type::negation, std::make_unique<ast::expression>($2), @$ }; }
|
||||
;
|
||||
|
||||
sum_expression
|
||||
: mult_expression { $$ = $1; }
|
||||
| sum_expression plus mult_expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| sum_expression minus mult_expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| sum_expression plus mult_expression { $$ = ast::binary_operation{ast::binary_operation_type::addition, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| sum_expression minus mult_expression { $$ = ast::binary_operation{ast::binary_operation_type::subtraction, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
;
|
||||
|
||||
mult_expression
|
||||
: not_expression { $$ = $1; }
|
||||
| mult_expression asterisk not_expression { $$ = ast::binary_operation{ast::binary_operation_type::multiplication, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| mult_expression slash not_expression { $$ = ast::binary_operation{ast::binary_operation_type::division, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| mult_expression percent not_expression { $$ = ast::binary_operation{ast::binary_operation_type::remainder, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3) }; }
|
||||
| mult_expression asterisk not_expression { $$ = ast::binary_operation{ast::binary_operation_type::multiplication, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| mult_expression slash not_expression { $$ = ast::binary_operation{ast::binary_operation_type::division, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
| mult_expression percent not_expression { $$ = ast::binary_operation{ast::binary_operation_type::remainder, std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$ }; }
|
||||
;
|
||||
|
||||
not_expression
|
||||
: postfix_expression
|
||||
| exclamation postfix_expression { $$ = ast::unary_operation{ast::unary_operation_type::logical_not, std::make_unique<ast::expression>($2) }; }
|
||||
| exclamation postfix_expression { $$ = ast::unary_operation{ast::unary_operation_type::logical_not, std::make_unique<ast::expression>($2), @$ }; }
|
||||
;
|
||||
|
||||
postfix_expression
|
||||
: base_expression
|
||||
| postfix_expression lbracket expression rbracket { $$ = ast::array_access{std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3)}; }
|
||||
| postfix_expression dot name { $$ = ast::field_access{std::make_unique<ast::expression>($1), $3}; }
|
||||
| postfix_expression lbracket expression rbracket { $$ = ast::array_access{std::make_unique<ast::expression>($1), std::make_unique<ast::expression>($3), @$}; }
|
||||
| postfix_expression dot name { $$ = ast::field_access{std::make_unique<ast::expression>($1), $3, @$}; }
|
||||
;
|
||||
|
||||
base_expression
|
||||
: literal
|
||||
| name { $$ = ast::identifier{$1}; }
|
||||
| name { $$ = ast::identifier{$1, ctx.location}; }
|
||||
| lparen expression rparen { $$ = $2; }
|
||||
| name lparen comma_separated_expression_list rparen { $$ = ast::function_call{$1, $3}; }
|
||||
| lbracket nonempty_comma_separated_expression_list rbracket { $$ = ast::array{$2}; }
|
||||
| name lparen comma_separated_expression_list rparen { $$ = ast::function_call{$1, $3, @$}; }
|
||||
| lbracket nonempty_comma_separated_expression_list rbracket { $$ = ast::array{$2, @$}; }
|
||||
;
|
||||
|
||||
comma_separated_expression_list
|
||||
|
|
@ -319,18 +319,18 @@ nonempty_comma_separated_expression_list
|
|||
;
|
||||
|
||||
literal
|
||||
: true { $$ = ast::literal(ast::bool_literal{true}); }
|
||||
| false { $$ = ast::literal(ast::bool_literal{false}); }
|
||||
| lit_i8 { $$ = parse_numeric_literal<std::int8_t>($1); }
|
||||
| lit_u8 { $$ = parse_numeric_literal<std::uint8_t>($1); }
|
||||
| lit_i16 { $$ = parse_numeric_literal<std::int16_t>($1); }
|
||||
| lit_u16 { $$ = parse_numeric_literal<std::uint16_t>($1); }
|
||||
| lit_i32 { $$ = parse_numeric_literal<std::int32_t>($1); }
|
||||
| lit_u32 { $$ = parse_numeric_literal<std::uint32_t>($1); }
|
||||
| lit_i64 { $$ = parse_numeric_literal<std::int64_t>($1); }
|
||||
| lit_u64 { $$ = parse_numeric_literal<std::uint64_t>($1); }
|
||||
| lit_f32 { $$ = parse_numeric_literal<float>($1); }
|
||||
| lit_f64 { $$ = parse_numeric_literal<double>($1); }
|
||||
: true { $$ = ast::literal(ast::bool_literal{true, ctx.location}); }
|
||||
| false { $$ = ast::literal(ast::bool_literal{false, ctx.location}); }
|
||||
| lit_i8 { $$ = parse_numeric_literal<std::int8_t>($1, ctx.location); }
|
||||
| lit_u8 { $$ = parse_numeric_literal<std::uint8_t>($1, ctx.location); }
|
||||
| lit_i16 { $$ = parse_numeric_literal<std::int16_t>($1, ctx.location); }
|
||||
| lit_u16 { $$ = parse_numeric_literal<std::uint16_t>($1, ctx.location); }
|
||||
| lit_i32 { $$ = parse_numeric_literal<std::int32_t>($1, ctx.location); }
|
||||
| lit_u32 { $$ = parse_numeric_literal<std::uint32_t>($1, ctx.location); }
|
||||
| lit_i64 { $$ = parse_numeric_literal<std::int64_t>($1, ctx.location); }
|
||||
| lit_u64 { $$ = parse_numeric_literal<std::uint64_t>($1, ctx.location); }
|
||||
| lit_f32 { $$ = parse_numeric_literal<float>($1, ctx.location); }
|
||||
| lit_f64 { $$ = parse_numeric_literal<double>($1, ctx.location); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <pslang/parser/indented_statement.hpp>
|
||||
#include <pslang/parser/error.hpp>
|
||||
#include <pslang/ast/statement.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
|
@ -93,18 +94,18 @@ namespace pslang::parser
|
|||
stack.push_back(result.get());
|
||||
std::size_t current_indent = 0;
|
||||
|
||||
auto current_statement_list = [&]() -> ast::statement_list *
|
||||
auto current_statement_list = [&](ast::location const & location) -> ast::statement_list *
|
||||
{
|
||||
if (stack.empty())
|
||||
throw std::runtime_error("Internal error: empty finilization stack");
|
||||
throw internal_error("empty finilization stack");
|
||||
|
||||
if (auto list = std::get_if<ast::statement_list *>(&stack.back()))
|
||||
return *list;
|
||||
|
||||
throw std::runtime_error("Unexpected statement inside struct definition");
|
||||
throw parse_error("unexpected statement inside struct definition", location);
|
||||
};
|
||||
|
||||
auto current_struct_definition = [&]() -> ast::struct_definition *
|
||||
auto current_struct_definition = [&](ast::location const & location) -> ast::struct_definition *
|
||||
{
|
||||
if (stack.empty())
|
||||
throw std::runtime_error("Internal error: empty finilization stack");
|
||||
|
|
@ -112,15 +113,15 @@ namespace pslang::parser
|
|||
if (auto list = std::get_if<ast::struct_definition *>(&stack.back()))
|
||||
return *list;
|
||||
|
||||
throw std::runtime_error("Unexpected statement outside struct definition");
|
||||
throw parse_error("unexpected statement outside struct definition", location);
|
||||
};
|
||||
|
||||
for (auto & statement : statements.statements)
|
||||
{
|
||||
auto location = ast::get_location(*statement.statement);
|
||||
|
||||
if (statement.indentation > current_indent)
|
||||
{
|
||||
throw std::runtime_error("Unexpected indent");
|
||||
}
|
||||
throw parse_error("unexpected indent", location);
|
||||
|
||||
while (statement.indentation < current_indent)
|
||||
{
|
||||
|
|
@ -136,41 +137,41 @@ namespace pslang::parser
|
|||
{
|
||||
ast::if_chain chain;
|
||||
chain.blocks.push_back({.condition = std::move(if_block->condition), .statements = std::move(if_block->statements)});
|
||||
current_statement_list()->statements.push_back(std::make_unique<ast::statement>(std::move(chain)));
|
||||
current_statement_list(location)->statements.push_back(std::make_unique<ast::statement>(std::move(chain)));
|
||||
}
|
||||
else if (auto else_block = std::get_if<ast::else_block>(statement.statement.get()))
|
||||
{
|
||||
if (current_statement_list()->statements.empty())
|
||||
throw std::runtime_error("Unexpected else block");
|
||||
auto chain = std::get_if<ast::if_chain>(current_statement_list()->statements.back().get());
|
||||
if (current_statement_list(location)->statements.empty())
|
||||
throw parse_error("unexpected else block", location);
|
||||
auto chain = std::get_if<ast::if_chain>(current_statement_list(location)->statements.back().get());
|
||||
if (!chain || chain->blocks.empty() || !chain->blocks.back().condition)
|
||||
throw std::runtime_error("Unexpected else block");
|
||||
throw parse_error("unexpected else block", location);
|
||||
|
||||
chain->blocks.push_back({.condition = nullptr, .statements = std::move(else_block->statements)});
|
||||
}
|
||||
else if (auto else_if_block = std::get_if<ast::else_if_block>(statement.statement.get()))
|
||||
{
|
||||
if (current_statement_list()->statements.empty())
|
||||
throw std::runtime_error("Unexpected else if block");
|
||||
auto chain = std::get_if<ast::if_chain>(current_statement_list()->statements.back().get());
|
||||
if (current_statement_list(location)->statements.empty())
|
||||
throw parse_error("unexpected else if block", location);
|
||||
auto chain = std::get_if<ast::if_chain>(current_statement_list(location)->statements.back().get());
|
||||
if (!chain || chain->blocks.empty() || !chain->blocks.back().condition)
|
||||
throw std::runtime_error("Unexpected else if block");
|
||||
throw parse_error("unexpected else if block", location);
|
||||
|
||||
chain->blocks.push_back({.condition = std::move(else_if_block->condition), .statements = std::move(else_if_block->statements)});
|
||||
}
|
||||
else if (auto field_definition = std::get_if<ast::field_definition>(statement.statement.get()))
|
||||
{
|
||||
current_struct_definition()->fields.push_back(*field_definition);
|
||||
current_struct_definition(location)->fields.push_back(*field_definition);
|
||||
}
|
||||
else if (std::get_if<ast::struct_definition>(statement.statement.get()))
|
||||
{
|
||||
current_statement_list()->statements.push_back(std::move(statement.statement));
|
||||
stack.push_back(std::get_if<ast::struct_definition>(current_statement_list()->statements.back().get()));
|
||||
current_statement_list(location)->statements.push_back(std::move(statement.statement));
|
||||
stack.push_back(std::get_if<ast::struct_definition>(current_statement_list(location)->statements.back().get()));
|
||||
++current_indent;
|
||||
}
|
||||
else
|
||||
{
|
||||
current_statement_list()->statements.push_back(std::move(statement.statement));
|
||||
current_statement_list(location)->statements.push_back(std::move(statement.statement));
|
||||
}
|
||||
|
||||
if (list)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue