5
5
#include " list.hpp"
6
6
#include " grammars.hpp"
7
7
#include " actions.hpp"
8
+
8
9
#include < limits>
9
10
10
11
namespace ctll {
@@ -16,19 +17,47 @@ enum class decision {
16
17
undecided
17
18
};
18
19
19
- template <typename T> void id (T);
20
-
21
20
struct placeholder { };
22
21
22
+ template <size_t > using index_placeholder = placeholder;
23
+
24
+ #ifdef EXPERIMENTAL_GCC_9
25
+ template <size_t , typename , typename Subject, decision Decision> struct results {
26
+ constexpr operator bool () const noexcept {
27
+ return Decision == decision::accept;
28
+ }
29
+ using output_type = Subject;
30
+ };
31
+ #endif
32
+
33
+
23
34
#if !__cpp_nontype_template_parameter_class
24
35
template <typename Grammar, const auto & input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser {
25
36
#else
26
- template <typename Grammar, basic_fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = true > struct parser { // in c++20
37
+ template <typename Grammar, ctll:: basic_fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser { // in c++20
27
38
#endif
28
39
using Actions = ctll::conditional<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
29
- static inline constexpr auto grammar = augment_grammar<Grammar>() ;
40
+ using grammar = augment_grammar<Grammar>;
30
41
31
- template <size_t Pos, typename Stack = void , typename Subject = void , decision Decision = decision::undecided> struct seed ;
42
+ #ifndef EXPERIMENTAL_GCC_9
43
+ template <size_t Pos, typename Stack, typename Subject, decision Decision> struct results {
44
+ constexpr inline CTLL_FORCE_INLINE operator bool () const noexcept {
45
+ return Decision == decision::accept;
46
+ }
47
+
48
+ using output_type = Subject;
49
+
50
+ constexpr auto operator +(placeholder) const noexcept {
51
+ if constexpr (Decision == decision::undecided) {
52
+ // parse for current char (RPos) with previous stack and subject :)
53
+ return decide<Pos, Stack, Subject>({}, {});
54
+ } else {
55
+ // if there is decision already => just push it to the end of fold expression
56
+ return *this ;
57
+ }
58
+ }
59
+ };
60
+ #endif
32
61
33
62
template <size_t Pos> static constexpr auto get_current_term () noexcept {
34
63
if constexpr (Pos < input.size ()) {
@@ -38,6 +67,7 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
38
67
} else {
39
68
return term<input[Pos]>{};
40
69
}
70
+
41
71
} else {
42
72
// return epsilon if we are past the input
43
73
return epsilon{};
@@ -48,29 +78,38 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
48
78
// there is no previous character on input if we are on start
49
79
return epsilon{};
50
80
} else if constexpr ((Pos-1 ) < input.size ()) {
51
- return term<input[Pos-1 ]>{};
81
+ constexpr auto value = input[Pos-1 ];
82
+ if constexpr (value <= std::numeric_limits<char >::max ()) {
83
+ return term<static_cast <char >(value)>{};
84
+ } else {
85
+ return term<input[Pos]>{};
86
+ }
52
87
} else {
53
88
return epsilon{};
54
89
}
55
90
}
56
91
// if rule is accept => return true and subject
57
92
template <size_t Pos, typename Terminal, typename Stack, typename Subject>
58
93
static constexpr auto move (ctll::accept, Terminal, Stack, Subject) noexcept {
59
- return seed <Pos, Stack, Subject, decision::accept>();
94
+ return results <Pos, Stack, Subject, decision::accept>();
60
95
}
61
96
// if rule is reject => return false and subject
62
97
template <size_t Pos, typename Terminal, typename Stack, typename Subject>
63
98
static constexpr auto move (ctll::reject, Terminal, Stack, Subject) noexcept {
64
- return seed <Pos, Stack, Subject, decision::reject>();
99
+ return results <Pos, Stack, Subject, decision::reject>();
65
100
}
66
101
// if rule is pop_input => move to next character
67
102
template <size_t Pos, typename Terminal, typename Stack, typename Subject>
68
103
static constexpr auto move (ctll::pop_input, Terminal, Stack, Subject) noexcept {
69
- return seed<Pos+1 , Stack, Subject, decision::undecided>();
104
+ #ifdef EXPERIMENTAL_GCC_9
105
+ return decide<Pos+1 >(Stack (), Subject ());
106
+ #else
107
+ return results<Pos+1 , Stack, Subject, decision::undecided>();
108
+ #endif
70
109
}
71
110
// if rule is string => push it to the front of stack
72
111
template <size_t Pos, typename ... Content, typename Terminal, typename Stack, typename Subject>
73
- static constexpr auto move (ctll:: push<Content...> string, Terminal, Stack stack, Subject subject) noexcept {
112
+ static constexpr auto move (push<Content...> string, Terminal, Stack stack, Subject subject) noexcept {
74
113
return decide<Pos>(push_front (string, stack), subject);
75
114
}
76
115
// if rule is epsilon (empty string) => continue
@@ -81,14 +120,22 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
81
120
// if rule is string with current character at the beginning (term<V>) => move to next character
82
121
// and push string without the character (quick LL(1))
83
122
template <size_t Pos, auto V, typename ... Content, typename Stack, typename Subject>
84
- static constexpr auto move (ctll::push<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
85
- return seed<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
123
+ static constexpr auto move (push<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
124
+ #ifdef EXPERIMENTAL_GCC_9
125
+ return decide<Pos+1 >(push_front (list<Content...>(), stack), Subject ());
126
+ #else
127
+ return results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
128
+ #endif
86
129
}
87
130
// if rule is string with any character at the beginning (compatible with current term<T>) => move to next character
88
131
// and push string without the character (quick LL(1))
89
132
template <size_t Pos, auto V, typename ... Content, auto T, typename Stack, typename Subject>
90
- static constexpr auto move (ctll::push<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
91
- return seed<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
133
+ static constexpr auto move (push<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
134
+ #ifdef EXPERIMENTAL_GCC_9
135
+ return decide<Pos+1 >(push_front (list<Content...>(), stack), Subject ());
136
+ #else
137
+ return results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
138
+ #endif
92
139
}
93
140
// decide if we need to take action or move
94
141
template <size_t Pos, typename Stack, typename Subject> static constexpr auto decide (Stack previous_stack, Subject previous_subject) noexcept {
@@ -103,50 +150,28 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
103
150
104
151
// in case that semantic action is error => reject input
105
152
if constexpr (std::is_same_v<ctll::reject, decltype (subject)>) {
106
- return seed<Pos, Stack, Subject, decision::reject>();
153
+ #ifndef EXPERIMENTAL_GCC_9
154
+ return results<Pos, Stack, Subject, decision::reject>();
155
+ #else
156
+ return results<Pos, Stack, Subject, decision::reject>();
157
+ #endif
107
158
} else {
108
159
return decide<Pos>(stack, subject);
109
160
}
110
161
} else {
111
162
// all other cases are ordinary for LL(1) parser
112
163
auto current_term = get_current_term<Pos>();
113
- auto rule = decltype (grammar. rule (top_symbol,current_term))();
164
+ auto rule = decltype (grammar:: rule (top_symbol,current_term))();
114
165
return move<Pos>(rule, current_term, stack, previous_subject);
115
166
}
116
167
}
117
- // helper type for trampoline
118
-
119
- template <size_t Pos, typename Stack, typename Subject, decision Decision> struct seed {
120
- constexpr inline CTLL_FORCE_INLINE operator bool () const noexcept {
121
- return Decision == decision::accept;
122
- }
123
-
124
- using output_type = Subject;
125
-
126
- static constexpr auto parse () noexcept {
127
- // push current position to decide function with current stack and subject
128
- return decide<Pos>(Stack{}, Subject{});
129
- }
130
-
131
- constexpr auto operator +(placeholder) const noexcept {
132
- if constexpr (Decision == decision::undecided) {
133
- // parse for current char (RPos) with previous stack and subject :)
134
- return decltype (seed<Pos, Stack, Subject, Decision>::parse ()){};
135
- } else {
136
- // if there is decision already => just push it to the end of fold expression
137
- return *this ;
138
- }
139
- }
140
- };
141
-
142
- template <size_t > using index_placeholder = placeholder;
143
168
169
+ #ifndef EXPERIMENTAL_GCC_9
144
170
// trampolines with folded expression
145
171
template <typename Subject, size_t ... Pos> static constexpr auto trampoline_decide (Subject, std::index_sequence<Pos...>) noexcept {
146
172
// parse everything for first char and than for next and next ...
147
173
// Pos+1 is needed as we want to finish calculation with epsilons on stack
148
- auto v = (seed<0 , decltype (grammar.start_stack ), Subject, decision::undecided>::parse () + ... + index_placeholder<Pos+1 >());
149
- // id(v);
174
+ auto v = (decide<0 , typename grammar::start_stack, Subject>({}, {}) + ... + index_placeholder<Pos+1 >());
150
175
return v;
151
176
}
152
177
@@ -156,8 +181,14 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
156
181
}
157
182
158
183
template <typename Subject = empty_subject> using output = decltype(trampoline_decide<Subject>());
159
- static inline constexpr bool correct = trampoline_decide( empty_subject() );
184
+ static inline constexpr bool correct = trampoline_decide< empty_subject>( );
160
185
template <typename Subject = empty_subject> static inline constexpr bool correct_with = trampoline_decide<Subject>();
186
+ #else
187
+ template <typename Subject = empty_subject> using output = decltype(decide<0 , typename grammar::start_stack, Subject>({}, {}));
188
+ static inline constexpr bool correct = decide<0 , typename grammar::start_stack, empty_subject>({}, {});
189
+ template <typename Subject = empty_subject> static inline constexpr bool correct_with = decide<0 , typename grammar::start_stack, Subject>({}, {});
190
+ #endif
191
+
161
192
};
162
193
163
194
} // end of ctll namespace
0 commit comments