generator: move LR(0)-specific code to generator_lr0_t
This commit is contained in:
parent
5887ec38e1
commit
35c02202fd
6 changed files with 50 additions and 29 deletions
|
@ -62,7 +62,7 @@ void generator_t::close_set(std::set<item_t> *set) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void generator_t::generate_itemsets() {
|
void generator_t::generate() {
|
||||||
std::queue<std::pair<std::set<item_t>, size_t>> queue;
|
std::queue<std::pair<std::set<item_t>, size_t>> queue;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -136,8 +136,6 @@ generator_t::generator_t(const grammar_t &grammar0) : grammar(grammar0) {
|
||||||
|
|
||||||
rule_ids.insert(std::make_pair(rule, i));
|
rule_ids.insert(std::make_pair(rule, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
generate_itemsets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,11 +56,8 @@ private:
|
||||||
std::map<std::set<item_t>, size_t> itemsets;
|
std::map<std::set<item_t>, size_t> itemsets;
|
||||||
|
|
||||||
std::map<std::pair<size_t, symbol_t>, size_t> shifts;
|
std::map<std::pair<size_t, symbol_t>, size_t> shifts;
|
||||||
std::map<size_t, size_t> reductions;
|
|
||||||
std::map<std::pair<size_t, std::string>, size_t> gotos;
|
std::map<std::pair<size_t, std::string>, size_t> gotos;
|
||||||
|
|
||||||
std::set<size_t> shift_conflicts;
|
|
||||||
|
|
||||||
|
|
||||||
void close_set(std::set<item_t> *set);
|
void close_set(std::set<item_t> *set);
|
||||||
std::set<item_t> get_set(const std::string &nonterm);
|
std::set<item_t> get_set(const std::string &nonterm);
|
||||||
|
@ -69,20 +66,10 @@ private:
|
||||||
return itemsets.insert(std::make_pair(set, itemsets.size()));
|
return itemsets.insert(std::make_pair(set, itemsets.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_reduction(size_t from, size_t to) {
|
|
||||||
if (reductions.count(from))
|
|
||||||
throw conflict_error("reduce/reduce conflict");
|
|
||||||
if (shift_conflicts.count(from))
|
|
||||||
throw conflict_error("shift/reduce conflict");
|
|
||||||
|
|
||||||
reductions.insert(std::make_pair(from, to));
|
|
||||||
}
|
|
||||||
|
|
||||||
void add_shift(size_t from, const symbol_t &sym, size_t to) {
|
void add_shift(size_t from, const symbol_t &sym, size_t to) {
|
||||||
if (reductions.count(from))
|
if (has_reduce_conflict(from, sym))
|
||||||
throw conflict_error("shift/reduce conflict");
|
throw conflict_error("shift/reduce conflict");
|
||||||
|
|
||||||
shift_conflicts.insert(from);
|
|
||||||
shifts.insert(std::make_pair(std::make_pair(from, sym), to));
|
shifts.insert(std::make_pair(std::make_pair(from, sym), to));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +77,11 @@ private:
|
||||||
gotos.insert(std::make_pair(std::make_pair(from, nonterm), to));
|
gotos.insert(std::make_pair(std::make_pair(from, nonterm), to));
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_itemsets();
|
protected:
|
||||||
|
virtual bool has_reduce_conflict(size_t from, const symbol_t &sym) = 0;
|
||||||
|
virtual void add_reduction(size_t from, size_t to) = 0;
|
||||||
|
|
||||||
|
generator_t(const grammar_t &grammar0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
const grammar_t & get_grammar() const {
|
const grammar_t & get_grammar() const {
|
||||||
|
@ -109,10 +100,6 @@ public:
|
||||||
return itemsets.size();
|
return itemsets.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::map<size_t, size_t> & get_reductions() const {
|
|
||||||
return reductions;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::map<std::pair<size_t, symbol_t>, size_t> & get_shifts() const {
|
const std::map<std::pair<size_t, symbol_t>, size_t> & get_shifts() const {
|
||||||
return shifts;
|
return shifts;
|
||||||
}
|
}
|
||||||
|
@ -121,8 +108,9 @@ public:
|
||||||
return gotos;
|
return gotos;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
virtual ~generator_t() {}
|
||||||
generator_t(const grammar_t &grammar0);
|
|
||||||
|
void generate();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,3 +25,25 @@
|
||||||
|
|
||||||
|
|
||||||
#include "generator_lr0.hpp"
|
#include "generator_lr0.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace solar {
|
||||||
|
|
||||||
|
bool generator_lr0_t::has_reduce_conflict(size_t from, const symbol_t &sym) {
|
||||||
|
(void)sym;
|
||||||
|
return reductions.count(from);
|
||||||
|
}
|
||||||
|
|
||||||
|
void generator_lr0_t::add_reduction(size_t from, size_t to) {
|
||||||
|
if (reductions.count(from))
|
||||||
|
throw conflict_error("reduce/reduce conflict");
|
||||||
|
|
||||||
|
for (const symbol_t &sym : get_terminals()) {
|
||||||
|
if (get_shifts().count(std::make_pair(from, sym)))
|
||||||
|
throw conflict_error("shift/reduce conflict");
|
||||||
|
}
|
||||||
|
|
||||||
|
reductions.insert(std::make_pair(from, to));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -32,8 +32,21 @@
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
class generator_lr0_t : public generator_t {
|
class generator_lr0_t : public generator_t {
|
||||||
|
private:
|
||||||
|
std::map<size_t, size_t> reductions;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool has_reduce_conflict(size_t from, const symbol_t &sym);
|
||||||
|
virtual void add_reduction(size_t from, size_t to);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
generator_lr0_t(const grammar_t &grammar) : generator_t(grammar) {}
|
const std::map<size_t, size_t> & get_reductions() const {
|
||||||
|
return reductions;
|
||||||
|
}
|
||||||
|
|
||||||
|
generator_lr0_t(const grammar_t &grammar) : generator_t(grammar) {
|
||||||
|
generate();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
namespace solar {
|
namespace solar {
|
||||||
|
|
||||||
output_t::output_t(const generator_t *generator0, const char *header, const char *source)
|
output_t::output_t(const generator_lr0_t *generator0, const char *header, const char *source)
|
||||||
: prefix_str("parse_"),
|
: prefix_str("parse_"),
|
||||||
token_prefix_str("TOK_"),
|
token_prefix_str("TOK_"),
|
||||||
stack_size(100),
|
stack_size(100),
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "generator.hpp"
|
#include "generator_lr0.hpp"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ private:
|
||||||
std::string token_prefix_str;
|
std::string token_prefix_str;
|
||||||
unsigned stack_size;
|
unsigned stack_size;
|
||||||
|
|
||||||
const generator_t *generator;
|
const generator_lr0_t *generator;
|
||||||
|
|
||||||
std::string header_filename;
|
std::string header_filename;
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ private:
|
||||||
void emit_source();
|
void emit_source();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
output_t(const generator_t *generator0, const char *header, const char *source);
|
output_t(const generator_lr0_t *generator0, const char *header, const char *source);
|
||||||
~output_t();
|
~output_t();
|
||||||
|
|
||||||
void write();
|
void write();
|
||||||
|
|
Reference in a new issue