@@ -15,16 +15,19 @@ enum class decision {
1515 undecided
1616};
1717
18- template <typename T> void id (T);
19-
2018struct placeholder { };
2119
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 {
2324 constexpr operator bool () const noexcept {
24- return Correct ;
25+ return Decision == decision::accept ;
2526 }
2627 using output_type = Subject;
2728};
29+ #endif
30+
2831
2932#if !__cpp_nontype_template_parameter_class
3033template <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
3437 using Actions = ctll::conditional<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
3538 using grammar = augment_grammar<Grammar>;
3639
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
3759
3860 template <size_t Pos> static constexpr auto get_current_term () noexcept {
3961 if constexpr (Pos < input.size ()) {
@@ -56,17 +78,21 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
5678 // if rule is accept => return true and subject
5779 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
5880 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>() ;
6082 }
6183 // if rule is reject => return false and subject
6284 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
6385 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>() ;
6587 }
6688 // if rule is pop_input => move to next character
6789 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
7096 }
7197 // if rule is string => push it to the front of stack
7298 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
81107 // if rule is string with current character at the beginning (term<V>) => move to next character
82108 // and push string without the character (quick LL(1))
83109 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
87116 }
88117 // if rule is string with any character at the beginning (compatible with current term<T>) => move to next character
89118 // and push string without the character (quick LL(1))
90119 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
95126 }
96127 // decide if we need to take action or move
97128 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
106137
107138 // in case that semantic action is error => reject input
108139 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
110145 } else {
111146 return decide<Pos>(stack, subject);
112147 }
@@ -118,9 +153,7 @@ template <typename Grammar, ctll::basic_fixed_string input, typename ActionSelec
118153 }
119154 }
120155
121- template <size_t > using index_placeholder = placeholder;
122-
123- #if false
156+ #ifndef EXPERIMENTAL_GCC_9
124157 // trampolines with folded expression
125158 template <typename Subject, size_t ... Pos> static constexpr auto trampoline_decide (Subject, std::index_sequence<Pos...>) noexcept {
126159 // 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
133166 // there will be no recursion, just sequence long as the input
134167 return trampoline_decide (subject, std::make_index_sequence<input.size ()>());
135168 }
136- #endif
137169
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
138174 template <typename Subject = empty_subject> using output = decltype (decide<0 , typename grammar::start_stack, Subject>({}, {}));
139175 static inline constexpr bool correct = decide<0 , typename grammar::start_stack, empty_subject>({}, {});
140176 template <typename Subject = empty_subject> static inline constexpr bool correct_with = decide<0 , typename grammar::start_stack, Subject>({}, {});
177+ #endif
178+
141179};
142180
143181} // end of ctll namespace
0 commit comments