88
99#include < limits>
1010
11- // this is disabling TRAMPOLINING for GCC9 which causes ICE
12- #if __GNUC__ == 9 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 0
13- #ifndef CTRE_ENABLE_TRAMPOLINING_ON_GCC9
14- #define CTRE_DISABLE_TRAMPOLINING 1
15- #endif
16- #endif
17-
1811namespace ctll {
1912
2013
@@ -28,43 +21,35 @@ struct placeholder { };
2821
2922template <size_t > using index_placeholder = placeholder;
3023
31- #ifdef CTRE_DISABLE_TRAMPOLINING
32- template <size_t , typename , typename Subject, decision Decision> struct results {
33- constexpr operator bool () const noexcept {
34- return Decision == decision::accept;
35- }
36- using output_type = Subject;
37- };
38- #endif
39-
40-
4124#if !__cpp_nontype_template_parameter_class
4225template <typename Grammar, const auto & input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser {
4326#else
4427template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser { // in c++20
4528#endif
29+ static constexpr auto _input = input; // workaround to GCC bug
30+
4631 using Actions = ctll::conditional<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
4732 using grammar = augment_grammar<Grammar>;
4833
49- #ifndef CTRE_DISABLE_TRAMPOLINING
5034 template <size_t Pos, typename Stack, typename Subject, decision Decision> struct results {
5135 constexpr inline CTLL_FORCE_INLINE operator bool () const noexcept {
5236 return Decision == decision::accept;
5337 }
38+
39+ static constexpr auto _input = input; // workaround to GCC bug
5440
5541 using output_type = Subject;
56-
42+
5743 constexpr auto operator +(placeholder) const noexcept {
5844 if constexpr (Decision == decision::undecided) {
5945 // parse for current char (RPos) with previous stack and subject :)
60- return decide<Pos, Stack, Subject>({}, {});
46+ return parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>:: template decide<Pos, Stack, Subject>({}, {});
6147 } else {
6248 // if there is decision already => just push it to the end of fold expression
6349 return *this ;
6450 }
6551 }
6652 };
67- #endif
6853
6954 template <size_t Pos> static constexpr auto get_current_term () noexcept {
7055 if constexpr (Pos < input.size ()) {
@@ -98,21 +83,17 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
9883 // if rule is accept => return true and subject
9984 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
10085 static constexpr auto move (ctll::accept, Terminal, Stack, Subject) noexcept {
101- return results<Pos, Stack, Subject, decision::accept>();
86+ return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>:: template results<Pos, Stack, Subject, decision::accept>();
10287 }
10388 // if rule is reject => return false and subject
10489 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
10590 static constexpr auto move (ctll::reject, Terminal, Stack, Subject) noexcept {
106- return results<Pos, Stack, Subject, decision::reject>();
91+ return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>:: template results<Pos, Stack, Subject, decision::reject>();
10792 }
10893 // if rule is pop_input => move to next character
10994 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
11095 static constexpr auto move (ctll::pop_input, Terminal, Stack, Subject) noexcept {
111- #ifdef CTRE_DISABLE_TRAMPOLINING
112- return decide<Pos+1 >(Stack (), Subject ());
113- #else
114- return results<Pos+1 , Stack, Subject, decision::undecided>();
115- #endif
96+ return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1 , Stack, Subject, decision::undecided>();
11697 }
11798 // if rule is string => push it to the front of stack
11899 template <size_t Pos, typename ... Content, typename Terminal, typename Stack, typename Subject>
@@ -128,21 +109,15 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
128109 // and push string without the character (quick LL(1))
129110 template <size_t Pos, auto V, typename ... Content, typename Stack, typename Subject>
130111 static constexpr auto move (push<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
131- #ifdef CTRE_DISABLE_TRAMPOLINING
132- return decide<Pos+1 >(push_front (list<Content...>(), stack), Subject ());
133- #else
134- return results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
135- #endif
112+ constexpr auto _input = input;
113+ return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
136114 }
137115 // if rule is string with any character at the beginning (compatible with current term<T>) => move to next character
138116 // and push string without the character (quick LL(1))
139117 template <size_t Pos, auto V, typename ... Content, auto T, typename Stack, typename Subject>
140118 static constexpr auto move (push<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
141- #ifdef CTRE_DISABLE_TRAMPOLINING
142- return decide<Pos+1 >(push_front (list<Content...>(), stack), Subject ());
143- #else
144- return results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
145- #endif
119+ constexpr auto _input = input;
120+ return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
146121 }
147122 // decide if we need to take action or move
148123 template <size_t Pos, typename Stack, typename Subject> static constexpr auto decide (Stack previous_stack, Subject previous_subject) noexcept {
@@ -157,11 +132,7 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
157132
158133 // in case that semantic action is error => reject input
159134 if constexpr (std::is_same_v<ctll::reject, decltype (subject)>) {
160- #ifndef CTRE_DISABLE_TRAMPOLINING
161- return results<Pos, Stack, Subject, decision::reject>();
162- #else
163- return results<Pos, Stack, Subject, decision::reject>();
164- #endif
135+ return typename parser<Grammar, _input, ActionSelector, IgnoreUnknownActions>::template results<Pos, Stack, Subject, decision::reject>();
165136 } else {
166137 return decide<Pos>(stack, subject);
167138 }
@@ -173,7 +144,6 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
173144 }
174145 }
175146
176- #ifndef CTRE_DISABLE_TRAMPOLINING
177147 // trampolines with folded expression
178148 template <typename Subject, size_t ... Pos> static constexpr auto trampoline_decide (Subject, std::index_sequence<Pos...>) noexcept {
179149 // parse everything for first char and than for next and next ...
@@ -188,13 +158,7 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
188158 }
189159
190160 template <typename Subject = empty_subject> using output = decltype (trampoline_decide<Subject>());
191- static inline constexpr bool correct = trampoline_decide<empty_subject>();
192161 template <typename Subject = empty_subject> static inline constexpr bool correct_with = trampoline_decide<Subject>();
193- #else
194- template <typename Subject = empty_subject> using output = decltype (decide<0 , typename grammar::start_stack, Subject>({}, {}));
195- static inline constexpr bool correct = decide<0 , typename grammar::start_stack, empty_subject>({}, {});
196- template <typename Subject = empty_subject> static inline constexpr bool correct_with = decide<0 , typename grammar::start_stack, Subject>({}, {});
197- #endif
198162
199163};
200164
0 commit comments