buffalo
Loading...
Searching...
No Matches
buffalo.h
Go to the documentation of this file.
1#ifndef BUFFALO2_H
2#define BUFFALO2_H
3
4#include <memory>
5#include <algorithm>
6#include <cctype>
7#include <expected>
8#include <map>
9#include <optional>
10#include <ranges>
11#include <set>
12#include <stack>
13#include <stdexcept>
14#include <variant>
15#include <vector>
16#include <ctre.hpp>
17#include <ctll.hpp>
18
19namespace bf
20{
21 /*
22 * Helper for std::visit provided by Andreas Fertig.
23 * Apple-Clang 15 isn't C++23 compliant enough for the prettier solution, so C++17 style it is.
24 * https://andreasfertig.blog/2023/07/visiting-a-stdvariant-safely/
25 */
26 template<class...>
27 constexpr bool always_false_v = false;
28
29 template<class... Ts>
30 struct overload : Ts...
31 {
32 using Ts::operator()...;
33
34 template<typename T>
35 constexpr void operator()(T) const
36 {
37 static_assert(always_false_v<T>, "Unsupported type");
38 }
39 };
40
41 template<class... Ts>
42 overload(Ts...) -> overload<Ts...>;
43
44 /*
45 * GRAMMAR DEFINITION
46 */
47 template<typename T>
48 concept IGrammar = requires(T)
49 {
50 typename T::ValueType;
51 typename T::UserDataType;
52 };
53
54 /*
55 * FORWARD-DECLS
56 */
57 template<IGrammar G>
58 class Grammar;
59
60 template<IGrammar G>
61 class ProductionRule;
62
63 template<IGrammar G>
64 class Terminal;
65
66 template<IGrammar G, ctll::fixed_string regex, typename SemanticType>
67 class DefineTerminal;
68
69 template<IGrammar G>
70 class NonTerminal;
71
72 template<IGrammar G, typename SemanticType>
74
75 template<IGrammar G>
76 struct LRItem;
77
78 template<IGrammar G>
79 struct LRState;
80
81 template<IGrammar G>
82 class Parser;
83
84 template<IGrammar G>
85 class SLRParser;
86
92 struct Location
93 {
94 std::string_view buffer;
95 std::size_t begin;
96 std::size_t end;
97
103 std::string SnippetString(std::size_t padding = 10)
104 {
105 return "";
106 }
107 };
108
109 struct Error
110 {
111 std::string message;
112
113 Error(std::string message) : message(std::move(message)) {}
114 };
115
120
127
132 template<IGrammar G>
134 {
135 std::vector<ProductionRule<G>> rules;
136
138 {
139 this->rules.push_back(rule);
140
141 return *this;
142 }
143 };
144
148 template<IGrammar G>
149 struct Token
150 {
152 std::string_view raw;
154
155 std::size_t Size() const
156 {
157 return this->location.end - this->location.begin;
158 }
159 };
160
164 struct Dummy {};
165
170 template<typename GValueType, typename GUserDataType = Dummy>
171 requires std::constructible_from<GValueType>
173 {
174 public:
175 /*
176 * TYPES
177 */
180 };
181
186 {
187 char const *debug_name = "Generic Symbol";
188 };
189
199
203 template<IGrammar G>
204 class Terminal : public DebugSymbol
205 {
206 friend class Grammar<G>;
207
208 public:
209 using ReasonerType = typename G::ValueType(*)(Token<G> const&);
210
211 protected:
212 inline static std::size_t counter = 0;
213
215
216 Terminal() = default;
217
218 public:
222
223 std::optional<typename G::ValueType> Reason(Token<G> const &token) const
224 {
225 if(this->reasoner_)
226 {
227 return this->reasoner_(token);
228 }
229
230 return std::nullopt;
231 }
232
233 virtual std::optional<Token<G>> Lex(std::string_view input) const
234 {
235 return std::nullopt;
236 }
237
238 Terminal(Terminal<G> &&) = delete;
239 Terminal(Terminal<G> const &) = delete;
240 };
241
246 template<IGrammar G, ctll::fixed_string regex, typename SemanticType = void>
247 class DefineTerminal : public Terminal<G>
248 {
249 public:
251 {
252 if constexpr(std::variant_size<typename G::ValueType>::value != 0)
253 {
254 if(!std::holds_alternative<SemanticType>(value))
255 {
256 throw std::runtime_error("failed to convert type");
257 }
258
259 return std::move(std::get<SemanticType>(value));
260 }
261 else
262 {
263 return std::move(reinterpret_cast<SemanticType>(value));
264 }
265 }
266
267 std::optional<Token<G>> Lex(std::string_view input) const override
268 {
269 auto match = ctre::starts_with<regex>(input);
270
271 if(!match)
272 {
273 return std::nullopt;
274 }
275
276 return Token<G> {
277 .terminal = (Terminal<G>*)this,
278 .raw = match.view(),
279 .location = {
280 .begin = 0,
281 .end = match.size(),
282 },
283 };
284 }
285
287 {
288 this->associativity = assoc;
289 this->user_data = user_data;
290 this->reasoner_ = reasoner;
291 }
292
294
297
299 };
300
304 template<IGrammar G>
306 {
307 friend class Grammar<G>;
308 friend struct LRState<G>;
309
310 public:
311 using TransductorType = typename G::ValueType(*)(std::vector<typename G::ValueType> &);
312
313 protected:
314 std::vector<ProductionRule<G>> rules_;
315
316 public:
319
320 NonTerminal() = default;
321
322 NonTerminal(ProductionRule<G> const &rule) : rules_({rule}) {}
324 };
325
329 template<IGrammar G, typename SemanticValue = void>
331 {
332 public:
334 {
335 if constexpr(std::variant_size<typename G::ValueType>::value != 0)
336 {
337 if(!std::holds_alternative<SemanticValue>(value))
338 {
339 throw std::runtime_error("failed to convert type");
340 }
341
342 return std::move(std::get<SemanticValue>(value));
343 }
344 else
345 {
346 return std::move(reinterpret_cast<SemanticValue>(value));
347 }
348 }
349
351
354 };
355
359 template<IGrammar G>
360 using Symbol = std::variant<Terminal<G>*, NonTerminal<G>*>;
361
362 /*
363 * PRODUCTION RULES
364 */
365 template<IGrammar G>
367 {
368 friend class Grammar<G>;
369 friend struct LRItem<G>;
370 friend class Parser<G>;
371 friend class SLRParser<G>;
372
373 protected:
375 std::vector<Symbol<G>> sequence_;
376 std::size_t precedence = -1;
377
379
380 public:
382 {
383 this->sequence_.push_back(&rhs);
384
385 return *this;
386 }
387
389 {
390 this->sequence_.push_back(&rhs);
391
392 return *this;
393 }
394
396 {
397 this->transductor_ = tranductor;
398
399 return *this;
400 }
401
403 {
404 if(this->non_terminal_ && other.non_terminal_)
405 {
406 if(this->non_terminal_ != other.non_terminal_) return false;
407 }
408 else if(this->non_terminal_ != other.non_terminal_)
409 {
410 return false;
411 }
412
413 if(this->sequence_.size() != other.sequence_.size()) return false;
414
415 for(auto const &[first, second] : std::views::zip(this->sequence_, other.sequence_))
416 {
417 if(first != second) return false;
418 }
419
420 return true;
421 }
422
423 std::optional<typename G::ValueType> Transduce(std::vector<typename G::ValueType> &args) const
424 {
425 if(this->transductor_)
426 {
427 return std::move(this->transductor_(args));
428 }
429
430 return std::nullopt;
431 }
432
433 ProductionRule(Terminal<G> &terminal) : sequence_({ &terminal }) {}
435 };
436
437 template<IGrammar G>
439
440 /*
441 * GRAMMAR
442 */
443 template<IGrammar G>
445 {
446 friend class Parser<G>;
447 friend class SLRParser<G>;
448
449 protected:
454 std::unique_ptr<Terminal<G>> EOS;
455
456 std::set<NonTerminal<G>*> nonterminals_;
457 std::set<Terminal<G>*> terminals_;
458
459 std::map<NonTerminal<G>*, std::set<Terminal<G>*>> first_;
460 std::map<NonTerminal<G>*, std::set<Terminal<G>*>> follow_;
461
463 std::vector<std::pair<NonTerminal<G>*, ProductionRule<G>>> production_rules_;
464
465 public:
467
469 {
470 return this->nonterminals_.contains(&non_terminal);
471 }
472
474 {
475 return this->follow_.at(&non_terminal).contains(&terminal);
476 }
477
479 {
480 return this->first_.at(&non_terminal).contains(&terminal);
481 }
482
488 {
489 bool has_change;
490 do
491 {
492 has_change = false;
493
494 for(auto const &[nonterminal, rule] : this->production_rules_)
495 {
496 if(rule.sequence_.empty()) continue;
497
498 has_change |= std::visit(overload{
499 [&](Terminal<G> *terminal)
500 {
501 auto [it, inserted] = this->first_[nonterminal].insert(terminal);
502 return inserted;
503 },
505 {
507 {
508 return false;
509 }
510
511 auto &parent_first = this->first_[nonterminal];
512 auto &child_first = this->first_[child_nonterminal];
513
514 std::size_t parent_size = parent_first.size();
515 parent_first.insert(child_first.begin(), child_first.end());
516
517 return parent_size != parent_first.size();
518 }
519 }, rule.sequence_[0]);
520 }
521 } while(has_change);
522 }
523
529 {
530 this->follow_[&root] = { this->EOS.get() };
531
532 bool has_change;
533 do
534 {
535 has_change = false;
536
537 for(auto &[nonterminal, rule] : this->production_rules_)
538 {
539 for(int i = 0; i < rule.sequence_.size(); i++)
540 {
541 // Skip over Terminals
542 if(std::holds_alternative<Terminal<G>*>(rule.sequence_[i])) continue;
543
544 // Process NonTerminal
545 auto symbol = std::get<NonTerminal<G>*>(rule.sequence_[i]);
546
547 // If this is the last NonTerminal in the sequence, then it gets all of the FOLLOW of parent.
548 if(i == rule.sequence_.size() - 1)
549 {
550 auto &parent_follow = this->follow_[nonterminal];
551 auto &child_follow = this->follow_[symbol];
552
553 std::size_t child_size = child_follow.size();
554 child_follow.insert(parent_follow.begin(), parent_follow.end());
555
557 continue;
558 }
559
560 // ELSE process the next token
561 auto follow = rule.sequence_[i + 1];
562
563 has_change |= std::visit(overload{
564 [&](Terminal<G> *terminal)
565 {
566 auto [it, inserted] = this->follow_[symbol].insert(terminal);
567 return inserted;
568 },
570 {
571 auto &symbol_follow = this->follow_[symbol];
572 auto &follow_first = this->first_[follow_nonterminal];
573
574 std::size_t symbol_size = symbol_follow.size();
575 symbol_follow.insert(follow_first.begin(), follow_first.end());
576
577 return symbol_size != symbol_follow.size();
578 }
579 }, follow);
580 }
581 }
582 } while(has_change);
583 }
584
586 {
587 this->nonterminals_.insert(nonterminal);
588
589 for(auto &rule : nonterminal->rules_)
590 {
592 Terminal<G> *last_terminal = nullptr;
593
594 this->production_rules_.push_back({nonterminal, rule});
595
596 for(auto &symbol : rule.sequence_)
597 {
598 std::visit(overload{
599 [&](Terminal<G> *terminal)
600 {
601 last_terminal = terminal;
602 this->terminals_.insert(terminal);
603 },
605 {
606 if(this->nonterminals_.contains(child_nonterminal)) return;
607
609 }
610 }, symbol);
611 }
612
613 // Rule precedence defaults to the precedence of the LAST terminal in sequence.
614 if(last_terminal)
615 {
617 }
618 }
619 }
620
622 {
623 this->EOS = std::make_unique<DefineTerminal<G, R"(\Z)">>();
624 this->terminals_.insert(this->EOS.get());
625
626 this->RegisterSymbols(&start);
627
628 this->GenerateFirstSet();
629 this->GenerateFollowSet();
630 }
631
632 Grammar() = delete;
633 };
634
635 /*
636 * PRODUCTION RULE COMPOSITION FUNCTIONS
637 */
638 template<IGrammar G>
643
644 template<IGrammar G>
649
650 template<IGrammar G>
655
656 template<IGrammar G>
661
662 template<IGrammar G>
667
672 template<IGrammar G>
673 struct LRItem
674 {
676 std::size_t position;
677
678 [[nodiscard]] bool Complete() const
679 {
680 return this->position >= this->rule->sequence_.size();
681 }
682
684 {
685 return LRItem(this->rule, this->position + 1);
686 }
687
689 {
690 return this->rule->sequence_[this->position];
691 }
692
693 bool operator==(LRItem const &other) const
694 {
695 return *this->rule == *other.rule && this->position == other.position;
696 }
697
699
700 LRItem() = delete;
701 };
702
703 using lrstate_id_t = std::size_t;
704
709 template<IGrammar G>
710 struct LRState
711 {
712 std::vector<LRItem<G>> kernel_items;
713
714 std::vector<LRItem<G>> GenerateClosure() const
715 {
716 std::vector<LRItem<G>> closure = this->kernel_items;
717 std::set<NonTerminal<G>*> closed_nonterminals;
718
719 for(int i = 0; i < closure.size(); i++)
720 {
721 if(closure[i].Complete()) continue;
722
723 std::visit(overload{
724 [](Terminal<G> *terminal) { /* Do Nothing */ },
726 {
727 if(closed_nonterminals.contains(non_terminal)) return;
729
730 for(auto const &rule : non_terminal->rules_)
731 {
732 closure.emplace_back(&rule);
733 }
734 }
735 }, closure[i].NextSymbol());
736 }
737
738 return closure;
739 }
740
741 std::map<Symbol<G>, LRState<G>> GenerateTransitions() const
742 {
743 std::map<Symbol<G>, LRState<G>> transitions;
744
745 auto closure = this->GenerateClosure();
746
747 for(auto const &item : closure)
748 {
749 if(item.Complete()) continue;
750
751 transitions[item.NextSymbol()].kernel_items.push_back(item.Advance());
752 }
753
754 return transitions;
755 }
756
762 bool operator==(LRState const &other) const
763 {
764 if(this->kernel_items.size() != other.kernel_items.size()) return false;
765
766 for(int i = 0; i < this->kernel_items.size(); i++)
767 {
768 if(this->kernel_items[i] != other.kernel_items[i]) return false;
769 }
770
771 return true;
772 }
773
775 {
776 for(auto const &rule : start->rules_)
777 {
778 this->kernel_items.emplace_back(&rule);
779 }
780 }
781
782 LRState() = default;
783 };
784
788 enum class LRActionType
789 {
790 kError,
791 kAccept,
792 kShift,
793 kReduce,
794 };
795
800 template<IGrammar G>
801 struct LRAction
802 {
804
805 union
806 {
809 };
810 };
811
816 template<IGrammar G>
817 class Parser
818 {
819 public:
820 virtual std::expected<typename G::ValueType, Error> Parse(std::string_view input, std::vector<Token<G>> *tokens) = 0;
821
822 virtual ~Parser() = default;
823 };
824
829 template<IGrammar G>
830 class SLRParser final : public Parser<G>
831 {
832 Grammar<G> grammar_;
833
834 std::map<lrstate_id_t, std::map<Terminal<G>*, LRAction<G>>> action_;
835 std::map<lrstate_id_t, std::map<NonTerminal<G>*, lrstate_id_t>> goto_;
836
837 struct ParseStackItem
838 {
839 lrstate_id_t state;
840 typename G::ValueType value;
841
842 ParseStackItem(lrstate_id_t state) : state(state) {}
843 ParseStackItem(lrstate_id_t state, typename G::ValueType value) : state(state), value(std::move(value)) {}
844 };
845
846 struct Tokenizer
847 {
848 SLRParser<G> const &parser;
849 std::string_view input;
850 std::size_t index = 0;
851
852 std::vector<Token<G>> *tokens;
853
854 std::optional<Token<G>> Peek(lrstate_id_t state = 0, bool permissive = false)
855 {
856 while(this->index < this->input.size() && std::isspace(this->input[this->index])) this->index++;
857
858 // IMPORTANT: No need to check for EOF, because it is checked for by special EOF terminal!
859
860 if(permissive)
861 {
862 for(auto terminal : this->parser.grammar_.terminals_)
863 {
864 auto token = terminal->Lex(this->input.substr(this->index));
865 if(token)
866 {
867 token->location.begin += this->index;
868 token->location.end += this->index;
869
870 return token;
871 }
872 }
873
874 // No token was matched. So we increment the index to skip this character.
875 index++;
876 }
877 else
878 {
879 for(auto terminal : this->parser.action_.at(state) | std::views::keys)
880 {
881 auto token = terminal->Lex(this->input.substr(this->index));
882 if(token)
883 {
884 token->location.begin += this->index;
885 token->location.end += this->index;
886
887 return token;
888 }
889 }
890 }
891
892 return std::nullopt;
893 }
894
895 void Consume(Token<G> const &token)
896 {
897 this->index += token.Size();
898 if(tokens)
899 {
900 tokens->push_back(token);
901 }
902 }
903
904 Tokenizer(SLRParser<G> const &parser, std::string_view input, std::vector<Token<G>> *tokens = nullptr) : parser(parser), input(input), tokens(tokens) {}
905 };
906
913 lrstate_id_t FindOrInsertLRState(std::vector<LRState<G>> &state_list, LRState<G> const &state)
914 {
915 auto it = std::ranges::find(state_list, state);
916
917 // Does not exist, add it in.
918 if(it == state_list.end())
919 {
920 state_list.push_back(state);
921 return state_list.size() - 1;
922 }
923
924 // Otherwise return index.
925 return std::distance(state_list.begin(), it);
926 }
927
931 std::optional<Error> BuildParsingTables()
932 {
933 std::vector<LRState<G>> states;
934
935 // Generate first state
936 states.clear();
937 states.emplace_back(&this->grammar_.root);
938
939 // Finite State Machine
940 std::map<lrstate_id_t, std::map<Symbol<G>, lrstate_id_t>> fsm;
941
942 for(lrstate_id_t i = 0; i < states.size(); i++)
943 {
944 // Process all transitions
945 for(auto const &[symbol, new_state] : states[i].GenerateTransitions())
946 {
947 lrstate_id_t new_state_id = this->FindOrInsertLRState(states, new_state);
949
950 // Create SHIFT/GOTO entries in parsing tables
951 std::visit(overload{
952 // Create ACTION
953 [&](Terminal<G> *terminal)
954 {
955 this->action_[i][terminal] = {
956 .type = LRActionType::kShift,
957 .state = new_state_id,
958 };
959 },
960
961 // Create GOTO
963 {
964 this->goto_[i][non_terminal] = new_state_id;
965 },
966 }, symbol);
967 }
968
969 // Create REDUCE/ACCEPT entries in parsing tables
970 for(auto const &item : states[i].kernel_items)
971 {
972 if(item.Complete())
973 {
974 for(auto follow_terminal : this->grammar_.follow_[item.rule->non_terminal_])
975 {
976 switch(this->action_[i][follow_terminal].type)
977 {
978 /* SHIFT-REDUCE CONFLICT */
980 {
981 // Reduce due to higher precedence
983 {
984 this->action_[i][follow_terminal] = {
985 .type = LRActionType::kReduce,
986 .rule = item.rule,
987 };
988 break;
989 }
990
991 // Shift due to lower precedence
993 {
994 break;
995 }
996
997 // Reduce due to associativity rule
998 if(follow_terminal->associativity == Associativity::Left)
999 {
1000 this->action_[i][follow_terminal] = {
1001 .type = LRActionType::kReduce,
1002 .rule = item.rule,
1003 };
1004 break;
1005 }
1006
1007 // Shift due to associativity rule
1008 if(follow_terminal->associativity == Right)
1009 {
1010 break;
1011 }
1012
1013 // Unable to resolve conflict
1014 return GrammarDefinitionError("ShiftReduce");
1015 }
1016
1018 {
1019 return GrammarDefinitionError("ReduceReduce");
1020 }
1021
1022 default:
1023 {
1024 this->action_[i][follow_terminal] = {
1025 .type = LRActionType::kReduce,
1026 .rule = item.rule,
1027 };
1028 }
1029 }
1030 }
1031 }
1032 }
1033 }
1034
1035 this->action_[0][this->grammar_.EOS.get()] = {
1036 .type = LRActionType::kAccept,
1037 };
1038
1039 return std::nullopt;
1040 }
1041
1042 protected:
1050
1051 public:
1052 Grammar<G> const &GetGrammar() const
1053 {
1054 return this->grammar_;
1055 }
1056
1057 std::expected<typename G::ValueType, Error> Parse(std::string_view input, std::vector<Token<G>> *tokens = nullptr) override
1058 {
1059 Tokenizer tokenizer(*this, input, tokens);
1060
1061 std::stack<ParseStackItem> parse_stack;
1062 parse_stack.emplace(0);
1063
1064 while(true)
1065 {
1066 lrstate_id_t state = parse_stack.top().state;
1067
1068 std::optional<Token<G>> lookahead = tokenizer.Peek(state);
1069 if(!lookahead)
1070 {
1071 // Permissively consume rest of tokens
1072 if(tokens)
1073 {
1074 while(true)
1075 {
1076 lookahead = tokenizer.Peek(0, true);
1077 if(!lookahead) continue;
1078 if(lookahead->terminal == this->grammar_.EOS.get())
1079 {
1080 break;
1081 }
1082 tokenizer.Consume(*lookahead);
1083 }
1084 }
1085
1086 return std::unexpected(Error{"Unexpected Token!"});
1087 }
1088
1089 LRAction<G> action = this->action_[parse_stack.top().state][lookahead->terminal];
1090 switch(action.type)
1091 {
1093 {
1094 return std::move(parse_stack.top().value);
1095 }
1096
1098 {
1099 std::optional<typename G::ValueType> value = std::move(lookahead->terminal->Reason(*lookahead));
1100
1101 if(value)
1102 {
1103 parse_stack.emplace(action.state, std::move(*value));
1104 }
1105 else
1106 {
1107 parse_stack.emplace(action.state);
1108 }
1109
1110 tokenizer.Consume(*lookahead);
1111 break;
1112 }
1113
1115 {
1116 std::vector<typename G::ValueType> args(action.rule->sequence_.size());
1117
1118 for(int i = action.rule->sequence_.size() - 1; i >= 0; i--)
1119 {
1120 auto &top = parse_stack.top();
1121
1122 args[i] = std::move(top.value);
1123
1124 parse_stack.pop();
1125 }
1126
1127 std::optional<typename G::ValueType> value = std::move(action.rule->Transduce(args));
1128 if(value)
1129 {
1130 parse_stack.emplace(this->goto_[parse_stack.top().state][action.rule->non_terminal_], std::move(*value));
1131 }
1132 else
1133 {
1134 parse_stack.emplace(this->goto_[parse_stack.top().state][action.rule->non_terminal_]);
1135 }
1136 break;
1137 }
1138
1139 default:
1140 {
1141 return std::unexpected(ParsingError(lookahead->location, "Unexpected Token"));
1142 }
1143 }
1144 }
1145 }
1146
1147 static std::expected<SLRParser, Error> Build(NonTerminal<G> &start)
1148 {
1149 SLRParser parser(start);
1150
1151 auto error = parser.BuildParsingTables();
1152 if(error)
1153 {
1154 return std::unexpected(*error);
1155 }
1156
1157 return std::move(parser);
1158 }
1159
1163 SLRParser() = delete;
1164 };
1165}
1166
1167#endif //BUFFALO2_H
bf::GrammarDefinition< double > G
Definition calculator.cpp:8
DefineNonTerminal(ProductionRuleList< G > const &rule_list)
Definition buffalo.h:353
SemanticValue operator()(typename G::ValueType &value)
Definition buffalo.h:333
DefineNonTerminal(ProductionRule< G > const &rule)
Definition buffalo.h:352
constexpr DefineTerminal(typename G::UserDataType user_data)
Definition buffalo.h:295
constexpr DefineTerminal(Associativity assoc=bf::None, typename G::UserDataType user_data={}, typename Terminal< G >::ReasonerType reasoner=nullptr)
Definition buffalo.h:286
SemanticType operator()(typename G::ValueType &value)
Definition buffalo.h:250
constexpr DefineTerminal(Associativity assoc, typename Terminal< G >::ReasonerType reasoner)
Definition buffalo.h:293
constexpr DefineTerminal(typename G::UserDataType user_data, typename Terminal< G >::ReasonerType reasoner)
Definition buffalo.h:296
std::optional< Token< G > > Lex(std::string_view input) const override
Definition buffalo.h:267
constexpr DefineTerminal(typename Terminal< G >::ReasonerType reasoner)
Definition buffalo.h:298
GUserDataType UserDataType
Definition buffalo.h:179
GValueType ValueType
Definition buffalo.h:178
std::map< NonTerminal< G > *, std::set< Terminal< G > * > > follow_
Definition buffalo.h:460
Grammar()=delete
std::unique_ptr< Terminal< G > > EOS
Definition buffalo.h:454
void GenerateFirstSet()
Definition buffalo.h:487
bool NonTerminalHasFollow(NonTerminal< G > &non_terminal, Terminal< G > &terminal) const
Definition buffalo.h:473
bool HasNonTerminal(NonTerminal< G > &non_terminal) const
Definition buffalo.h:468
std::set< NonTerminal< G > * > nonterminals_
Definition buffalo.h:456
Grammar(NonTerminal< G > &start)
Definition buffalo.h:621
std::vector< std::pair< NonTerminal< G > *, ProductionRule< G > > > production_rules_
List of all production rules along with their respective NonTerminal.
Definition buffalo.h:463
bool NonTerminalHasFirst(NonTerminal< G > &non_terminal, Terminal< G > &terminal) const
Definition buffalo.h:478
std::set< Terminal< G > * > terminals_
Definition buffalo.h:457
std::map< NonTerminal< G > *, std::set< Terminal< G > * > > first_
Definition buffalo.h:459
void GenerateFollowSet()
Definition buffalo.h:528
void RegisterSymbols(NonTerminal< G > *nonterminal)
Definition buffalo.h:585
NonTerminal< G > & root
Definition buffalo.h:466
std::vector< ProductionRule< G > > rules_
Definition buffalo.h:314
NonTerminal(NonTerminal &)=delete
NonTerminal(ProductionRule< G > const &rule)
Definition buffalo.h:322
NonTerminal()=default
NonTerminal(ProductionRuleList< G > const &rule_list)
Definition buffalo.h:323
typename G::ValueType(*)(std::vector< typename G::ValueType > &) TransductorType
Definition buffalo.h:311
NonTerminal(NonTerminal &&)=delete
virtual ~Parser()=default
virtual std::expected< typename G::ValueType, Error > Parse(std::string_view input, std::vector< Token< G > > *tokens)=0
ProductionRule & operator<=>(typename NonTerminal< G >::TransductorType tranductor)
Definition buffalo.h:395
std::optional< typename G::ValueType > Transduce(std::vector< typename G::ValueType > &args) const
Definition buffalo.h:423
ProductionRule & operator+(NonTerminal< G > &rhs)
Definition buffalo.h:388
NonTerminal< G >::TransductorType transductor_
Definition buffalo.h:374
ProductionRule & operator+(Terminal< G > &rhs)
Definition buffalo.h:381
bool operator==(ProductionRule< G > const &other) const
Definition buffalo.h:402
ProductionRule(Terminal< G > &terminal)
Definition buffalo.h:433
std::vector< Symbol< G > > sequence_
Definition buffalo.h:375
std::size_t precedence
Definition buffalo.h:376
NonTerminal< G > * non_terminal_
Definition buffalo.h:378
Grammar< G > const & GetGrammar() const
Definition buffalo.h:1052
static std::expected< SLRParser, Error > Build(NonTerminal< G > &start)
Definition buffalo.h:1147
SLRParser(NonTerminal< G > &start)
Definition buffalo.h:1049
SLRParser()=delete
std::expected< typename G::ValueType, Error > Parse(std::string_view input, std::vector< Token< G > > *tokens=nullptr) override
Definition buffalo.h:1057
Associativity associativity
Definition buffalo.h:220
virtual std::optional< Token< G > > Lex(std::string_view input) const
Definition buffalo.h:233
Terminal(Terminal< G > const &)=delete
Terminal(Terminal< G > &&)=delete
G::UserDataType user_data
Definition buffalo.h:221
static std::size_t counter
Definition buffalo.h:212
std::optional< typename G::ValueType > Reason(Token< G > const &token) const
Definition buffalo.h:223
ReasonerType reasoner_
Definition buffalo.h:214
std::size_t precedence
Definition buffalo.h:219
Terminal()=default
typename G::ValueType(*)(Token< G > const &) ReasonerType
Definition buffalo.h:209
Definition buffalo.h:20
constexpr bool always_false_v
Definition buffalo.h:27
LRActionType
Definition buffalo.h:789
ProductionRuleList< G > operator|(ProductionRule< G > const &lhs, ProductionRule< G > const &rhs)
Definition buffalo.h:663
Associativity
Definition buffalo.h:194
@ Left
Definition buffalo.h:196
@ None
Definition buffalo.h:195
@ Right
Definition buffalo.h:197
std::variant< Terminal< G > *, NonTerminal< G > * > Symbol
Definition buffalo.h:360
ProductionRule< G > PR
Definition buffalo.h:438
ProductionRule< G > operator+(Terminal< G > &lhs, Terminal< G > &rhs)
Definition buffalo.h:639
std::size_t lrstate_id_t
Definition buffalo.h:703
char const * debug_name
Definition buffalo.h:187
Error(std::string message)
Definition buffalo.h:113
std::string message
Definition buffalo.h:111
GrammarDefinitionError(std::string message)
Definition buffalo.h:118
LRActionType type
Definition buffalo.h:803
ProductionRule< G > const * rule
Definition buffalo.h:808
lrstate_id_t state
Definition buffalo.h:807
Symbol< G > NextSymbol() const
Definition buffalo.h:688
LRItem()=delete
LRItem(ProductionRule< G > const *rule, int position=0)
Definition buffalo.h:698
LRItem Advance() const
Definition buffalo.h:683
std::size_t position
Definition buffalo.h:676
ProductionRule< G > const * rule
Definition buffalo.h:675
bool operator==(LRItem const &other) const
Definition buffalo.h:693
bool Complete() const
Definition buffalo.h:678
LRState()=default
LRState(NonTerminal< G > const *start)
Definition buffalo.h:774
bool operator==(LRState const &other) const
Definition buffalo.h:762
std::vector< LRItem< G > > GenerateClosure() const
Definition buffalo.h:714
std::vector< LRItem< G > > kernel_items
Definition buffalo.h:712
std::map< Symbol< G >, LRState< G > > GenerateTransitions() const
Definition buffalo.h:741
std::size_t begin
Definition buffalo.h:95
std::string_view buffer
Definition buffalo.h:94
std::string SnippetString(std::size_t padding=10)
Definition buffalo.h:103
std::size_t end
Definition buffalo.h:96
Location location
Definition buffalo.h:123
ParsingError(Location location, std::string message)
Definition buffalo.h:125
ProductionRuleList & operator|(ProductionRule< G > const &rule)
Definition buffalo.h:137
std::vector< ProductionRule< G > > rules
Definition buffalo.h:135
Location location
Definition buffalo.h:153
Terminal< G > * terminal
Definition buffalo.h:151
std::size_t Size() const
Definition buffalo.h:155
std::string_view raw
Definition buffalo.h:152
constexpr void operator()(T) const
Definition buffalo.h:35