33 using Ts::operator()...;
58 std::string buffer(
size,
'0');
60 for (std::size_t
i = 0;
i <
size;
i++)
62 buffer[
i] =
static_cast<char>(
utf32[
i]);
65 return std::move(buffer);
74 typename T::ValueType;
75 typename T::UserDataType;
99 template<IGrammar G, ctll::fixed_
string regex,
typename SemanticType>
105 template<IGrammar G, ctll::fixed_
string DebugName,
typename SemanticType>
138 std::size_t
start = std::max(
static_cast<std::size_t
>(0), this->begin -
padding);
139 std::size_t
n = this->end - this->begin + (
padding * 2);
153 return this->message_.c_str();
177 return terminal->GetName();
204 message <<
"Shift-reduce conflicts can be solved by:\n";
205 message <<
"\t1. Refactoring your grammar.\n";
206 message <<
"\t2. Adding precedence to your terminals.\n";
207 message <<
"\t3. Adding Associativity to your terminals.\n\n";
208 message <<
"The conflict arose in the following state with the following closure:\n";
212 GrammarDefinitionError::AppendRule(
message,
item.rule,
static_cast<int>(
item.position));
215 message <<
"When deciding to reduce the following rule:\n";
222 GrammarDefinitionError::AppendRule(
message,
item.rule,
static_cast<int>(
item.position));
234 message <<
"Grammar contains an irreconcilable reduce-reduce conflict between " <<
a_name <<
"/" <<
b_name <<
".\n";
235 message <<
"Reduce-reduce conflicts are normally solved by refactoring your grammar.\n";
236 message <<
"The conflict arose in the following two rules:\n\n";
238 for (
auto const rule : {
a,
b})
240 GrammarDefinitionError::AppendRule(
message, rule);
245 message <<
"In the state with the following closure:\n";
248 GrammarDefinitionError::AppendRule(
message,
item.rule,
static_cast<int>(
item.position));
268 mstream <<
"\t" << std::string(10,
' ') <<
'^' << std::string(location.
end - location.
begin,
'~') <<
"\n";
287 return this->location.
end - this->location.
begin;
317 std::vector<ValueToken<G>> values_;
322 this->values_.reserve(100);
330 std::shared_ptr<ValueTokenStore<G>> store_;
335 return this->store_->values_[this->index_];
340 return this->store_->values_[this->index_].value;
349 std::span<std::size_t> indices_;
350 std::shared_ptr<ValueTokenStore<G>> store_;
352 std::string_view raw_;
358 return this->store_->values_[this->indices_[
i]].value;
363 return this->store_->values_[this->indices_[
i]];
368 this->store_->values_.emplace_back(this->raw_, this->location_, std::move(value));
380 template<
typename GValueType,
typename GUserDataType = Dummy>
381 requires std::constructible_from<GValueType>
442 virtual std::optional<Token<G>>
Lex(std::string_view input)
const
449 return this->name_.c_str();
460 template<IGrammar G, ctll::fixed_
string regex,
typename SemanticType = Dummy>
466 return std::get<SemanticType>(value);
469 std::optional<Token<G>>
Lex(std::string_view input)
const override
471 auto match = ctre::starts_with<regex>(input);
523 return this->name_.c_str();
544 return std::get<SemanticValue>(value);
604 this->sequence_.push_back(&
rhs);
611 this->sequence_.push_back(&
rhs);
624 this->
mod_.short_circuit.insert(&lookahead);
650 if(this->sequence_.size() !=
other.
sequence_.size())
return false;
661 if(this->transductor_)
666 else if (this->sequence_.size() > 0)
689 std::vector<ProductionRule<G>>
rules;
693 this->rules.push_back(rule);
713 std::unique_ptr<Terminal<G>>
EOS;
718 std::map<NonTerminal<G>*, std::set<Terminal<G>*>>
first_;
719 std::map<NonTerminal<G>*, std::set<Terminal<G>*>>
follow_;
734 return this->follow_.at(&
non_terminal).contains(&terminal);
739 return this->first_.at(&
non_terminal).contains(&terminal);
755 if(rule.sequence_.empty())
continue;
789 this->follow_[&
root] = { this->EOS.get() };
801 if(std::holds_alternative<
Terminal<G>*>(rule.sequence_[
i]))
continue;
804 auto symbol = std::get<NonTerminal<G>*>(rule.sequence_[
i]);
853 this->production_rules_.push_back({
nonterminal, rule});
855 for(
auto &
symbol : rule.sequence_)
861 this->terminals_.insert(terminal);
883 this->terminals_.insert(this->EOS.get());
940 return this->position >= this->rule->
sequence_.size();
945 return LRItem(this->rule, this->position + 1);
955 return *this->rule == *
other.rule && this->mod ==
other.mod && this->position ==
other.position;
987 if (
closure[
i].mod.short_circuit.contains(terminal))
1017 if (
item.Complete())
continue;
1032 if(this->kernel_items.size() !=
other.kernel_items.size())
return false;
1034 for(
int i = 0;
i < this->kernel_items.size();
i++)
1036 if(this->kernel_items[
i] !=
other.kernel_items[
i])
return false;
1044 for(
auto const &rule :
start->rules_)
1046 this->kernel_items.emplace_back(&rule);
1068 template<IGrammar G>
1084 template<IGrammar G>
1088 virtual std::expected<ValueTokenReference<G>,
Error>
Parse(std::string_view input)
const = 0;
1097 template<IGrammar G>
1102 std::map<lrstate_id_t, std::map<Terminal<G>*,
LRAction<G>>> action_;
1103 std::map<lrstate_id_t, std::map<NonTerminal<G>*,
lrstate_id_t>> goto_;
1107 return this->action_.at(state).at(
lookahead);
1118 std::string_view input;
1119 std::size_t index = 0;
1125 for(
auto terminal : this->parser.action_.at(state) | std::views::keys)
1127 auto token = terminal->Lex(this->input.substr(
this->index));
1130 token->location.begin += this->index;
1131 token->location.end += this->index;
1133 this->index +=
token->Size();
1139 return std::nullopt;
1142 Tokenizer(
SLRParser<G> const &parser, std::string_view input) : parser(parser), input(input) {}
1169 std::optional<Error> BuildParsingTables()
1171 std::vector<LRState<G>>
states{};
1172 states.emplace_back(&this->grammar_.root);
1190 this->action_[
i][terminal] = {
1207 if(!
item.Complete())
continue;
1268 this->action_[0][this->grammar_.EOS.get()] = {
1272 this->goto_[0][&this->grammar_.root] = 0;
1274 return std::nullopt;
1289 return this->grammar_;
1292 std::expected<ValueTokenReference<G>,
Error>
Parse(std::string_view input)
const override
1298 std::vector<lrstate_id_t>
stack;
1305 auto store = std::make_shared<ValueTokenStore<G>>();
1317 return std::unexpected(
ParsingError{location,
"Unexpected Token!"});
1359 auto error = parser.BuildParsingTables();
1362 return std::unexpected(*
error);
1365 return std::move(parser);
bf::GrammarDefinition< double > G
DefineNonTerminal()=delete
DefineNonTerminal(ProductionRule< G > const &rule)
DefineNonTerminal(NonTerminal< G > &single_non_terminal)
DefineNonTerminal(ProductionRuleList< G > const &rule_list)
DefineNonTerminal(Terminal< G > &single_terminal)
SemanticValue & operator()(typename G::ValueType &value)
constexpr DefineTerminal(typename G::UserDataType user_data)
SemanticType & operator()(typename G::ValueType &value)
constexpr DefineTerminal(Associativity assoc=bf::None, typename G::UserDataType user_data={}, typename Terminal< G >::ReasonerType reasoner=nullptr)
constexpr DefineTerminal(Associativity assoc, typename Terminal< G >::ReasonerType reasoner)
constexpr DefineTerminal(typename G::UserDataType user_data, typename Terminal< G >::ReasonerType reasoner)
std::optional< Token< G > > Lex(std::string_view input) const override
constexpr DefineTerminal(typename Terminal< G >::ReasonerType reasoner)
Error(std::string message)
char const * what() const noexcept override
static GrammarDefinitionError ReduceReduce(LRState< G > &state, ProductionRule< G > const *a, ProductionRule< G > const *b, Terminal< G > *lookahead)
static GrammarDefinitionError ShiftReduce(LRState< G > &state, LRState< G > &shift, ProductionRule< G > const *reduce, Terminal< G > *lookahead)
GrammarDefinitionError(std::string message)
GUserDataType UserDataType
std::map< NonTerminal< G > *, std::set< Terminal< G > * > > follow_
std::unique_ptr< Terminal< G > > EOS
bool NonTerminalHasFollow(NonTerminal< G > &non_terminal, Terminal< G > &terminal) const
bool HasNonTerminal(NonTerminal< G > &non_terminal) const
std::set< NonTerminal< G > * > nonterminals_
Grammar(NonTerminal< G > &start)
std::vector< std::pair< NonTerminal< G > *, ProductionRule< G > > > production_rules_
List of all production rules along with their respective NonTerminal.
bool NonTerminalHasFirst(NonTerminal< G > &non_terminal, Terminal< G > &terminal) const
std::set< Terminal< G > * > terminals_
std::map< NonTerminal< G > *, std::set< Terminal< G > * > > first_
void RegisterSymbols(NonTerminal< G > *nonterminal)
std::vector< ProductionRule< G > > rules_
NonTerminal(NonTerminal &)=delete
char const * GetName() const noexcept
NonTerminal(ProductionRule< G > const &rule, std::string name="unknown")
NonTerminal(NonTerminal &&)=delete
NonTerminal(ProductionRuleList< G > const &rule_list, std::string name="unknown")
virtual std::expected< ValueTokenReference< G >, Error > Parse(std::string_view input) const =0
virtual ~Parser()=default
ParsingError(Location location, std::string_view message)
ProductionRuleList & operator|(ProductionRule< G > const &rule)
std::vector< ProductionRule< G > > rules
ProductionRule & operator<=>(typename NonTerminal< G >::TransductorType tranductor)
ProductionRule & operator+(NonTerminal< G > &rhs)
NonTerminal< G >::TransductorType transductor_
ProductionRule & operator+(Terminal< G > &rhs)
bool operator==(ProductionRule< G > const &other) const
ProductionRule(NonTerminal< G > &nonterminal)
void Transduce(ValueTokenAccessor< G > &$) const
ProductionRule(Terminal< G > &terminal)
std::vector< Symbol< G > > sequence_
ProductionRuleModifiers< G > mod_
NonTerminal< G > * non_terminal_
ProductionRule & Short(Terminal< G > &lookahead)
Grammar< G > const & GetGrammar() const
static std::expected< SLRParser, Error > Build(NonTerminal< G > &start)
SLRParser(NonTerminal< G > &start)
std::expected< ValueTokenReference< G >, Error > Parse(std::string_view input) const override
Associativity associativity
virtual std::optional< Token< G > > Lex(std::string_view input) const
Terminal(Terminal< G > const &)=delete
Terminal(Terminal< G > &&)=delete
char const * GetName() const noexcept
G::UserDataType user_data
static std::size_t counter_
G::ValueType Reason(Token< G > const &token) const
typename G::ValueType(*)(Token< G > const &) ReasonerType
G::ValueType & operator[](std::size_t i)
ValueTokenReference< G > operator()(std::size_t i)
ValueTokenAccessor & operator=(typename G::ValueType value)
ValueToken< G > & GetValueToken() const
G::ValueType & GetValue() const
ValueTokenReference(std::size_t index, std::shared_ptr< ValueTokenStore< G > > store)
constexpr bool always_false_v
ProductionRuleList< G > operator|(ProductionRule< G > const &lhs, ProductionRule< G > const &rhs)
std::variant< Terminal< G > *, NonTerminal< G > * > Symbol
ProductionRule< G > operator+(Terminal< G > &lhs, Terminal< G > &rhs)
std::string utf32_to_string(char32_t const *utf32, std::size_t size)
ProductionRule< G > const * rule
Symbol< G > NextSymbol() const
LRItem(ProductionRule< G > const *rule, int position=0)
ProductionRule< G > const * rule
ProductionRuleModifiers< G > mod
bool operator==(LRItem const &other) const
LRState(NonTerminal< G > const *start)
bool operator==(LRState const &other) const
std::vector< LRItem< G > > GenerateClosure() const
std::vector< LRItem< G > > kernel_items
std::map< Symbol< G >, LRState< G > > GenerateTransitions() const
std::string_view SnippetString(std::size_t padding=10) const
bool operator==(ProductionRuleModifiers const &other) const
std::set< Terminal< G > * > short_circuit
ProductionRuleModifiers & operator+=(ProductionRuleModifiers const &other)
constexpr void operator()(T) const