Skip to content

Commit ffe4aa9

Browse files
committed
Extend parser to support property indexing and key words arguments
NP-1311
1 parent fd7cd2f commit ffe4aa9

22 files changed

Lines changed: 956 additions & 67 deletions

CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
cmake_minimum_required(VERSION 3.26)
22
project(cura-formulae-engine)
33

4+
include(CTest)
5+
46
find_package(standardprojectsettings REQUIRED)
57
option(ENABLE_TESTS "Build with unit test" ON)
68
option(EXTENSIVE_WARNINGS "Build with all warnings" ON)
79
option(ENABLE_APPS "Build apps example" ON)
810

11+
if (ENABLE_TESTS AND NOT BUILD_TESTING)
12+
message(STATUS "ENABLE_TESTS is ON, forcing BUILD_TESTING=ON so CTest can discover tests")
13+
set(BUILD_TESTING ON CACHE BOOL "Enable CTest" FORCE)
14+
endif ()
15+
916
find_package(spdlog REQUIRED)
1017
find_package(lexy REQUIRED)
1118
find_package(zeus_expected REQUIRED)
@@ -59,6 +66,7 @@ set(CURA_FORMULAE_ENGINE__SRC
5966
src/ast/slice_expr.cpp
6067
src/ast/tuple_expr.cpp
6168
src/ast/variable_expr.cpp
69+
src/ast/property_access_expr.cpp
6270
src/parser/parser.cpp
6371
src/ast/binary_expr/binary_expr.cpp
6472
src/ast/binary_expr/add_expr.cpp

include/cura-formulae-engine/ast/fn_application_expr.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,25 @@ namespace CuraFormulaeEngine::ast
88

99
struct FnApplicationExpr final : Expr
1010
{
11+
struct KeywordArg
12+
{
13+
std::string name;
14+
ExprPtr value;
15+
16+
[[nodiscard]] bool deepEq(const KeywordArg& other) const noexcept
17+
{
18+
return name == other.name && value.deepEq(other.value);
19+
}
20+
};
21+
1122
ExprPtr fn;
1223
std::vector<ExprPtr> args;
24+
std::vector<KeywordArg> kwargs;
1325

14-
FnApplicationExpr(ExprPtr fn, std::vector<ExprPtr> args)
26+
FnApplicationExpr(ExprPtr fn, std::vector<ExprPtr> args, std::vector<KeywordArg> kwargs = {})
1527
: fn(std::move(fn))
1628
, args(std::move(args))
29+
, kwargs(std::move(kwargs))
1730
{
1831
}
1932

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#pragma once
2+
3+
#include "cura-formulae-engine/ast/ast.h"
4+
#include "expr_ptr.h"
5+
6+
#include <string>
7+
8+
namespace CuraFormulaeEngine::ast
9+
{
10+
11+
struct PropertyAccessExpr final : Expr
12+
{
13+
ExprPtr object;
14+
std::string property;
15+
16+
PropertyAccessExpr(ExprPtr object, std::string property)
17+
: object(std::move(object))
18+
, property(std::move(property))
19+
{
20+
}
21+
22+
[[nodiscard]] std::string toString() const noexcept final;
23+
24+
[[nodiscard]] eval::Result evaluate(const env::Environment* environment) const noexcept final;
25+
26+
[[nodiscard]] std::unordered_set<std::string> freeVariables() const noexcept final;
27+
28+
[[nodiscard]] bool deepEq(const Expr& other) const noexcept final;
29+
30+
void visitAll(std::function<void(const Expr&)> visitor) const noexcept final;
31+
};
32+
33+
} // namespace CuraFormulaeEngine::ast

include/cura-formulae-engine/env/int_fn.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
#include "cura-formulae-engine/eval.h"
44

5+
#include <string>
6+
#include <vector>
7+
58
namespace CuraFormulaeEngine::env
69
{
710

11+
struct IntFunction
12+
{
13+
[[nodiscard]] eval::Result operator()(const std::vector<eval::Value>& args) const noexcept;
14+
[[nodiscard]] std::vector<std::string> getSignature() const noexcept;
15+
};
16+
17+
extern const IntFunction int_function;
818
extern const eval::Value::fn_t int_fn;
919

1020
} // namespace CuraFormulaeEngine::env

include/cura-formulae-engine/env/math_log.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
#include "cura-formulae-engine/eval.h"
44

5+
#include <string>
6+
#include <vector>
7+
58
namespace CuraFormulaeEngine::env
69
{
710

11+
struct MathLogFunction
12+
{
13+
[[nodiscard]] eval::Result operator()(const std::vector<eval::Value>& args) const noexcept;
14+
[[nodiscard]] std::vector<std::string> getSignature() const noexcept;
15+
};
16+
17+
extern const MathLogFunction math_log_function;
818
extern const eval::Value::fn_t math_log;
919

1020
} // namespace CuraFormulaeEngine::env

include/cura-formulae-engine/env/min.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
#include "cura-formulae-engine/eval.h"
44

5+
#include <string>
6+
#include <vector>
7+
58
namespace CuraFormulaeEngine::env
69
{
710

11+
struct MinFunction
12+
{
13+
[[nodiscard]] eval::Result operator()(const std::vector<eval::Value>& args) const noexcept;
14+
[[nodiscard]] std::vector<std::string> getSignature() const noexcept;
15+
};
16+
17+
extern const MinFunction min_function;
818
extern const eval::Value::fn_t min;
919

1020
} // namespace CuraFormulaeEngine::env

include/cura-formulae-engine/env/round.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,19 @@
22

33
#include "cura-formulae-engine/eval.h"
44

5+
#include <string>
6+
#include <vector>
7+
58
namespace CuraFormulaeEngine::env
69
{
710

11+
struct RoundFunction
12+
{
13+
[[nodiscard]] eval::Result operator()(const std::vector<eval::Value>& args) const noexcept;
14+
[[nodiscard]] std::vector<std::string> getSignature() const noexcept;
15+
};
16+
17+
extern const RoundFunction round_function;
818
extern const eval::Value::fn_t round;
919

1020
} // namespace CuraFormulaeEngine::env

include/cura-formulae-engine/eval.h

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <cstddef>
1919
#include <functional>
2020
#include <string>
21+
#include <unordered_map>
2122
#include <variant>
2223
#include <vector>
2324
#include <zeus/expected.hpp>
@@ -44,7 +45,31 @@ struct Value
4445
{
4546
using fn_t = std::function<Result(const std::vector<Value>&)>;
4647

47-
std::variant<bool, double, std::int64_t, std::string, std::vector<Value>, fn_t, std::nullptr_t> value = nullptr;
48+
struct rich_fn_t
49+
{
50+
fn_t operation;
51+
std::vector<std::string> signature;
52+
53+
[[nodiscard]] Result operator()(const std::vector<Value>& args) const noexcept
54+
{
55+
if (! operation)
56+
{
57+
return zeus::unexpected(Error::TypeMismatch);
58+
}
59+
return operation(args);
60+
}
61+
62+
[[nodiscard]] std::optional<std::vector<std::string>> getSignature() const noexcept
63+
{
64+
if (signature.empty())
65+
{
66+
return std::nullopt;
67+
}
68+
return signature;
69+
}
70+
};
71+
72+
std::variant<bool, double, std::int64_t, std::string, std::vector<Value>, fn_t, rich_fn_t, std::unordered_map<std::string, Value>, std::nullptr_t> value = nullptr;
4873

4974
Value() noexcept = default;
5075

@@ -78,6 +103,16 @@ struct Value
78103
{
79104
}
80105

106+
Value(const rich_fn_t& value) noexcept
107+
: value{ value }
108+
{
109+
}
110+
111+
Value(const std::unordered_map<std::string, Value>& value) noexcept
112+
: value{ value }
113+
{
114+
}
115+
81116
Value(const std::nullptr_t& value) noexcept
82117
: value{ value }
83118
{

include/cura-formulae-engine/formula.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ parsing parts. For instance, function application and array indexing. The gramma
3333
similar.
3434

3535
```
36-
FN APPLICATION : { variable } '(' { expression } ')'
36+
FN APPLICATION : { variable } '(' { expression | identifier '=' expression } ')'
3737
ARRAY INDEXING : { variable } '[' { expression } ']'
3838
```
3939

include/cura-formulae-engine/parser/math_expr_grammar.h

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,6 @@
1212
#include "cura-formulae-engine/ast/expr_ptr.h"
1313
#include "cura-formulae-engine/ast/unary_expr/neg_expr.h"
1414
#include "cura-formulae-engine/ast/unary_expr/not_expr.h"
15-
#include "bool_grammar.h"
16-
#include "list_grammar.h"
17-
#include "none_grammar.h"
18-
#include "number_grammar.h"
19-
#include "parens_grammar.h"
20-
#include "string_grammar.h"
2115
#include "variable_or_fn_application_grammar_or_array_indexing_grammar.h"
2216

2317
#include <lexy/callback/adapter.hpp>
@@ -35,13 +29,7 @@ struct MathExprGrammar : lexy::expression_production
3529

3630
// clang-format off
3731
static constexpr auto atom
38-
= lexy::dsl::p<BoolGrammar>
39-
| lexy::dsl::p<NoneGrammar>
40-
| lexy::dsl::p<NumberGrammar>
41-
| lexy::dsl::p<ParensGrammar>
42-
| lexy::dsl::p<StringGrammar>
43-
| lexy::dsl::p<ListGrammar>
44-
| lexy::dsl::p<VariableOrFnApplicationGrammarOrArrayIndexingGrammar>;
32+
= lexy::dsl::p<VariableOrFnApplicationGrammarOrArrayIndexingGrammar>;
4533
// clang-format on
4634

4735
static constexpr auto op_pow = lexy::dsl::op(LEXY_LIT("**"));

0 commit comments

Comments
 (0)