@@ -19,15 +19,21 @@ template <typename T> void id(T);
1919
2020struct placeholder { };
2121
22+ template <bool Correct, typename Subject> struct result_of_parsing {
23+ constexpr operator bool () const noexcept {
24+ return Correct;
25+ }
26+ using output_type = Subject;
27+ };
28+
2229#if !__cpp_nontype_template_parameter_class
2330template <typename Grammar, const auto & input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser {
2431#else
25- template <typename Grammar, basic_fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = true > struct parser { // in c++20
32+ template <typename Grammar, ctll:: basic_fixed_string input, typename ActionSelector = empty_actions, bool IgnoreUnknownActions = false > struct parser { // in c++20
2633#endif
2734 using Actions = ctll::conditional<IgnoreUnknownActions, ignore_unknown<ActionSelector>, identity<ActionSelector>>;
28- static inline constexpr auto grammar = augment_grammar<Grammar>() ;
35+ using grammar = augment_grammar<Grammar>;
2936
30- template <size_t Pos, typename Stack = void , typename Subject = void , decision Decision = decision::undecided> struct seed ;
3137
3238 template <size_t Pos> static constexpr auto get_current_term () noexcept {
3339 if constexpr (Pos < input.size ()) {
@@ -50,17 +56,17 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
5056 // if rule is accept => return true and subject
5157 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
5258 static constexpr auto move (ctll::accept, Terminal, Stack, Subject) noexcept {
53- return seed<Pos, Stack, Subject, decision::accept>() ;
59+ return result_of_parsing< true , Subject>{} ;
5460 }
5561 // if rule is reject => return false and subject
5662 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
5763 static constexpr auto move (ctll::reject, Terminal, Stack, Subject) noexcept {
58- return seed<Pos, Stack, Subject, decision::reject>() ;
64+ return result_of_parsing< false , Subject>{} ;
5965 }
6066 // if rule is pop_input => move to next character
6167 template <size_t Pos, typename Terminal, typename Stack, typename Subject>
62- static constexpr auto move (ctll::pop_input, Terminal, Stack, Subject) noexcept {
63- return seed <Pos+1 , Stack, Subject, decision::undecided>( );
68+ static constexpr auto move (ctll::pop_input, Terminal, Stack stack , Subject subject ) noexcept {
69+ return decide <Pos+1 >(stack, subject );
6470 }
6571 // if rule is string => push it to the front of stack
6672 template <size_t Pos, typename ... Content, typename Terminal, typename Stack, typename Subject>
@@ -75,14 +81,17 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
7581 // if rule is string with current character at the beginning (term<V>) => move to next character
7682 // and push string without the character (quick LL(1))
7783 template <size_t Pos, auto V, typename ... Content, typename Stack, typename Subject>
78- static constexpr auto move (ctll::list<term<V>, Content...>, term<V>, Stack stack, Subject) noexcept {
79- return seed<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
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>();
8087 }
8188 // if rule is string with any character at the beginning (compatible with current term<T>) => move to next character
8289 // and push string without the character (quick LL(1))
8390 template <size_t Pos, auto V, typename ... Content, auto T, typename Stack, typename Subject>
84- static constexpr auto move (ctll::list<anything, Content...>, term<T>, Stack stack, Subject) noexcept {
85- return seed<Pos+1 , decltype (push_front (list<Content...>(), stack)), Subject, decision::undecided>();
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>();
8695 }
8796 // decide if we need to take action or move
8897 template <size_t Pos, typename Stack, typename Subject> static constexpr auto decide (Stack previous_stack, Subject previous_subject) noexcept {
@@ -97,49 +106,26 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
97106
98107 // in case that semantic action is error => reject input
99108 if constexpr (std::is_same_v<ctll::reject, decltype (subject)>) {
100- return seed<Pos, Stack, Subject, decision::reject >();
109+ return result_of_parsing< false , Subject>();
101110 } else {
102111 return decide<Pos>(stack, subject);
103112 }
104113 } else {
105114 // all other cases are ordinary for LL(1) parser
106115 auto current_term = get_current_term<Pos>();
107- auto rule = decltype (grammar. rule (top_symbol,current_term))();
116+ auto rule = decltype (grammar:: rule (top_symbol,current_term))();
108117 return move<Pos>(rule, current_term, stack, previous_subject);
109118 }
110119 }
111- // helper type for trampoline
112-
113- template <size_t Pos, typename Stack, typename Subject, decision Decision> struct seed {
114- constexpr inline CTLL_FORCE_INLINE operator bool () const noexcept {
115- return Decision == decision::accept;
116- }
117-
118- using output_type = Subject;
119-
120- static constexpr auto parse () noexcept {
121- // push current position to decide function with current stack and subject
122- return decide<Pos>(Stack{}, Subject{});
123- }
124-
125- constexpr auto operator +(placeholder) const noexcept {
126- if constexpr (Decision == decision::undecided) {
127- // parse for current char (RPos) with previous stack and subject :)
128- return decltype (seed<Pos, Stack, Subject, Decision>::parse ()){};
129- } else {
130- // if there is decision already => just push it to the end of fold expression
131- return *this ;
132- }
133- }
134- };
135120
136121 template <size_t > using index_placeholder = placeholder;
137122
123+ #if false
138124 // trampolines with folded expression
139125 template <typename Subject, size_t ... Pos> static constexpr auto trampoline_decide (Subject, std::index_sequence<Pos...>) noexcept {
140126 // parse everything for first char and than for next and next ...
141127 // Pos+1 is needed as we want to finish calculation with epsilons on stack
142- auto v = (seed<0 , decltype ( grammar. start_stack ) , Subject, decision::undecided>::parse () + ... + index_placeholder<Pos+1 >());
128+ auto v = (seed<0 , grammar:: start_stack, Subject, decision::undecided>::parse () + ... + index_placeholder<Pos+1 >());
143129 // id(v);
144130 return v;
145131 }
@@ -148,10 +134,11 @@ template <typename Grammar, basic_fixed_string input, typename ActionSelector =
148134 // there will be no recursion, just sequence long as the input
149135 return trampoline_decide (subject, std::make_index_sequence<input.size ()>());
150136 }
137+ #endif
151138
152- template <typename Subject = empty_subject> using output = decltype (trampoline_decide< Subject>());
153- static inline constexpr bool correct = trampoline_decide( empty_subject() );
154- template <typename Subject = empty_subject> static inline constexpr bool correct_with = trampoline_decide< Subject>();
139+ template <typename Subject = empty_subject> using output = decltype (decide< 0 , typename grammar::start_stack, Subject>({}, {} ));
140+ static inline constexpr bool correct = decide< 0 , typename grammar::start_stack, empty_subject>({}, {} );
141+ template <typename Subject = empty_subject> static inline constexpr bool correct_with = decide< 0 , typename grammar::start_stack, Subject>({}, {} );
155142};
156143
157144} // end of ctll namespace
0 commit comments