@@ -15,16 +15,19 @@ enum class decision {
15
15
undecided
16
16
};
17
17
18
- template <typename T> void id (T);
19
-
20
18
struct placeholder { };
21
19
22
- template <bool Correct, typename Subject> struct result_of_parsing {
20
+ template <size_t > using index_placeholder = placeholder;
21
+
22
+ #ifdef EXPERIMENTAL_GCC_9
23
+ template <size_t , typename , typename Subject, decision Decision> struct results {
23
24
constexpr operator bool () const noexcept {
24
- return Correct ;
25
+ return Decision == decision::accept ;
25
26
}
26
27
using output_type = Subject;
27
28
};
29
+ #endif
30
+
28
31
29
32
#if !__cpp_nontype_template_parameter_class
30
33
template <typename Grammar, const auto & input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser {
@@ -34,6 +37,25 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
34
37
using Actions = ctll::conditional<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
35
38
using grammar = augment_grammar<Grammar>;
36
39
40
+ #ifndef EXPERIMENTAL_GCC_9
41
+ template <size_t Pos, typename Stack, typename Subject, decision Decision> struct results {
42
+ constexpr inline CTLL_FORCE_INLINE operator bool () const noexcept {
43
+ return Decision == decision::accept;
44
+ }
45
+
46
+ using output_type = Subject;
47
+
48
+ constexpr auto operator +(placeholder) const noexcept {
49
+ if constexpr (Decision == decision::undecided) {
50
+ // parse for current char (RPos) with previous stack and subject :)
51
+ return decide<Pos, Stack, Subject>({}, {});
52
+ } else {
53
+ // if there is decision already => just push it to the end of fold expression
54
+ return *this ;
55
+ }
56
+ }
57
+ };
58
+ #endif
37
59
38
60
template <size_t Pos> static constexpr auto get_current_term () noexcept {
39
61
if constexpr (Pos < input.size ()) {
@@ -56,17 +78,21 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
56
78
// if rule is accept => return true and subject
57
79
template <size_t Pos, typename Terminal, typename Stack, typename Subject>
58
80
static constexpr auto move (ctll::accept, Terminal, Stack, Subject) noexcept {
59
- return result_of_parsing< true , Subject>{} ;
81
+ return results<Pos, Stack, Subject, decision::accept>() ;
60
82
}
61
83
// if rule is reject => return false and subject
62
84
template <size_t Pos, typename Terminal, typename Stack, typename Subject>
63
85
static constexpr auto move (ctll::reject, Terminal, Stack, Subject) noexcept {
64
- return result_of_parsing< false , Subject>{} ;
86
+ return results<Pos, Stack, Subject, decision::reject>() ;
65
87
}
66
88
// if rule is pop_input => move to next character
67
89
template <size_t Pos, typename Terminal, typename Stack, typename Subject>
68
- static constexpr auto move (ctll::pop_input, Terminal, Stack stack, Subject subject) noexcept {
69
- return decide<Pos+1 >(stack, subject);
90
+ static constexpr auto move (ctll::pop_input, Terminal, Stack, Subject) noexcept {
91
+ #ifdef EXPERIMENTAL_GCC_9
92
+ return decide<Pos+1 >(Stack (), Subject ());
93
+ #else
94
+ return results<Pos+1 , Stack, Subject, decision::undecided>();
95
+ #endif
70
96
}
71
97
// if rule is string => push it to the front of stack
72
98
template <size_t Pos, typename ... Content, typename Terminal, typename Stack, typename Subject>
@@ -81,17 +107,22 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
81
107
// if rule is string with current character at the beginning (term<V>) => move to next character
82
108
// and push string without the character (quick LL(1))
83
109
template <size_t Pos, auto V, typename ... Content, typename Stack, typename Subject>
84
- static constexpr auto move (ctll::list<term<V>, Content...>, term<V>, Stack stack, Subject subject) noexcept {
85
- return decide<Pos+1 >(push_front (list<Content...>(), stack), subject);
86
- // return seed<Pos+1, decltype(push_front(list<Content...>(), stack)), Subject, decision::undecided>();
110
+ static constexpr auto move (ctll::list<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
111
+ #ifdef EXPERIMENTAL_GCC_9
112
+ return decide<Pos+1 >(push_front (list<Content...>(), stack), Subject ());
113
+ #else
114
+ return results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
115
+ #endif
87
116
}
88
117
// if rule is string with any character at the beginning (compatible with current term<T>) => move to next character
89
118
// and push string without the character (quick LL(1))
90
119
template <size_t Pos, auto V, typename ... Content, auto T, typename Stack, typename Subject>
91
- static constexpr auto move (ctll::list<anything, Content...>, term<T>, Stack stack, Subject subject) noexcept {
92
- return decide<Pos+1 >(push_front (list<Content...>(), stack), subject);
93
-
94
- // return seed<Pos+1, decltype(push_front(list<Content...>(), stack)), Subject, decision::undecided>();
120
+ static constexpr auto move (ctll::list<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
121
+ #ifdef EXPERIMENTAL_GCC_9
122
+ return decide<Pos+1 >(push_front (list<Content...>(), stack), Subject ());
123
+ #else
124
+ return results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
125
+ #endif
95
126
}
96
127
// decide if we need to take action or move
97
128
template <size_t Pos, typename Stack, typename Subject> static constexpr auto decide (Stack previous_stack, Subject previous_subject) noexcept {
@@ -106,7 +137,11 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
106
137
107
138
// in case that semantic action is error => reject input
108
139
if constexpr (std::is_same_v<ctll::reject, decltype (subject)>) {
109
- return result_of_parsing<false , Subject>();
140
+ #ifndef EXPERIMENTAL_GCC_9
141
+ return results<Pos, Stack, Subject, decision::reject>();
142
+ #else
143
+ return results<Pos, Stack, Subject, decision::reject>();
144
+ #endif
110
145
} else {
111
146
return decide<Pos>(stack, subject);
112
147
}
@@ -118,9 +153,7 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
118
153
}
119
154
}
120
155
121
- template <size_t > using index_placeholder = placeholder;
122
-
123
- #if false
156
+ #ifndef EXPERIMENTAL_GCC_9
124
157
// trampolines with folded expression
125
158
template <typename Subject, size_t ... Pos> static constexpr auto trampoline_decide (Subject, std::index_sequence<Pos...>) noexcept {
126
159
// parse everything for first char and than for next and next ...
@@ -133,11 +166,16 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
133
166
// there will be no recursion, just sequence long as the input
134
167
return trampoline_decide (subject, std::make_index_sequence<input.size ()>());
135
168
}
136
- #endif
137
169
170
+ template <typename Subject = empty_subject> using output = decltype (trampoline_decide<Subject>());
171
+ static inline constexpr bool correct = trampoline_decide<empty_subject>();
172
+ template <typename Subject = empty_subject> static inline constexpr bool correct_with = trampoline_decide<Subject>();
173
+ #else
138
174
template <typename Subject = empty_subject> using output = decltype (decide<0 , typename grammar::start_stack, Subject>({}, {}));
139
175
static inline constexpr bool correct = decide<0 , typename grammar::start_stack, empty_subject>({}, {});
140
176
template <typename Subject = empty_subject> static inline constexpr bool correct_with = decide<0 , typename grammar::start_stack, Subject>({}, {});
177
+ #endif
178
+
141
179
};
142
180
143
181
} // end of ctll namespace
0 commit comments