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));
230 char const *
a_name =
a->non_terminal_->GetName();
231 char const *
b_name =
b->non_terminal_->GetName();
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->indices_[
i], this->store_};
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);
610 this->sequence_.push_back(&
rhs);
617 this->sequence_.push_back(&
rhs);
630 this->
mod_.short_circuit.insert(&lookahead);
645 if(this->non_terminal_ !=
other.non_terminal_)
650 if (this->
mod_ != other.mod_)
656 if(this->sequence_.size() !=
other.sequence_.size())
return false;
657 for(
auto const &[
first,
second] : std::views::zip(this->sequence_,
other.sequence_))
667 if(this->transductor_)
672 else if (this->sequence_.size() > 0)
695 std::vector<ProductionRule<G>>
rules;
699 this->rules.push_back(rule);
719 std::unique_ptr<Terminal<G>>
EOS;
724 std::map<NonTerminal<G>*, std::set<Terminal<G>*>>
first_;
725 std::map<NonTerminal<G>*, std::set<Terminal<G>*>>
follow_;
740 return this->follow_.at(&
non_terminal).contains(&terminal);
745 return this->first_.at(&
non_terminal).contains(&terminal);
761 if(rule.sequence_.empty())
continue;
784 }, rule.sequence_[0]);
795 this->follow_[&
root] = { this->EOS.get() };
804 for(
int i = 0;
i < rule.sequence_.size();
i++)
807 if(std::holds_alternative<
Terminal<G>*>(rule.sequence_[
i]))
continue;
810 auto symbol = std::get<NonTerminal<G>*>(rule.sequence_[
i]);
813 if(
i == rule.sequence_.size() - 1)
826 auto follow = rule.sequence_[
i + 1];
859 this->production_rules_.push_back({
nonterminal, rule});
861 for(
auto &
symbol : rule.sequence_)
867 this->terminals_.insert(terminal);
889 this->terminals_.insert(this->EOS.get());
946 return this->position >= this->rule->
sequence_.size();
951 return LRItem(this->rule, this->position + 1);
961 return *this->rule == *
other.rule && this->mod ==
other.mod && this->position ==
other.position;
993 if (
closure[
i].mod.short_circuit.contains(terminal))
1023 if (
item.Complete())
continue;
1025 transitions[
item.NextSymbol()].kernel_items.push_back(
item.Advance());
1038 if(this->kernel_items.size() !=
other.kernel_items.size())
return false;
1040 for(
int i = 0;
i < this->kernel_items.size();
i++)
1042 if(this->kernel_items[
i] !=
other.kernel_items[
i])
return false;
1050 for(
auto const &rule :
start->rules_)
1052 this->kernel_items.emplace_back(&rule);
1074 template<IGrammar G>
1090 template<IGrammar G>
1094 virtual std::expected<ValueTokenReference<G>,
Error>
Parse(std::string_view input)
const = 0;
1103 template<IGrammar G>
1108 std::map<lrstate_id_t, std::map<Terminal<G>*,
LRAction<G>>> action_;
1109 std::map<lrstate_id_t, std::map<NonTerminal<G>*,
lrstate_id_t>> goto_;
1113 return this->action_.at(state).at(
lookahead);
1124 std::string_view input;
1125 std::size_t index = 0;
1131 for(
auto terminal : this->parser.action_.at(state) | std::views::keys)
1133 auto token = terminal->Lex(this->input.substr(
this->index));
1136 token->location.begin += this->index;
1137 token->location.end += this->index;
1139 this->index +=
token->Size();
1145 return std::nullopt;
1148 Tokenizer(
SLRParser<G> const &parser, std::string_view input) : parser(parser), input(input) {}
1175 std::optional<Error> BuildParsingTables()
1177 std::vector<LRState<G>>
states{};
1178 states.emplace_back(&this->grammar_.root);
1196 this->action_[
i][terminal] = {
1213 if(!
item.Complete())
continue;
1274 this->action_[0][this->grammar_.EOS.get()] = {
1278 this->goto_[0][&this->grammar_.root] = 0;
1280 return std::nullopt;
1295 return this->grammar_;
1298 std::expected<ValueTokenReference<G>,
Error>
Parse(std::string_view input)
const override
1304 std::vector<lrstate_id_t>
stack;
1311 auto store = std::make_shared<ValueTokenStore<G>>();
1323 return std::unexpected(
ParsingError{location,
"Unexpected Token!"});
1349 stack.push_back(this->LookupGoto(
stack.back(),
action.rule->non_terminal_));
1365 auto error = parser.BuildParsingTables();
1368 return std::unexpected(*
error);
1371 return std::move(parser);
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")
void(*)(ValueTokenAccessor< G > &) TransductorType
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_
std::set< Terminal< G > * > short_circuit_
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_
NonTerminal< G > * non_terminal_
struct bf::ProductionRule::@0 attr_
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
Short(Terminal< G > *terminal)
std::set< Terminal< G > * > terminals
constexpr void operator()(T) const