74 lines
2.8 KiB
C++
74 lines
2.8 KiB
C++
#pragma once
|
|
#ifndef PARSODUS_GRAMMAR_H
|
|
|
|
#include "Parsodus/util/firstset.h"
|
|
#include "Parsodus/util/followset.h"
|
|
|
|
#include <deque>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <set>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace pds {
|
|
enum class PrecedenceType {
|
|
LEFT,
|
|
RIGHT,
|
|
NONASSOC
|
|
};
|
|
|
|
/**
|
|
* Represents a grammar rule
|
|
* head -> tail[0] tail[1] ... tail[tail.size() - 1]
|
|
*/
|
|
struct Rule {
|
|
std::string head; ///< The replaced variable
|
|
std::vector<std::string> tail; ///< The replacement rule
|
|
const std::string name; ///< An optional name for this rule, if it's empty, there's no name
|
|
std::pair<bool, std::pair<int, PrecedenceType>> precedence; ///< precedence for this rule, the bool indicates whether it's valid (invalid if there is no rightmost terminal and no explicit precedence)
|
|
bool operator<(const Rule& other) const {
|
|
if(head != other.head){
|
|
return head < other.head;
|
|
} else {
|
|
return tail < other.tail;
|
|
}
|
|
}
|
|
|
|
Rule() : Rule("", {}, ""){}
|
|
Rule(const std::string& h, const std::vector<std::string>& t) : Rule(h, t, "") {}
|
|
Rule(const std::string& h, const std::vector<std::string>& t, const std::string& name) : head(h), tail(t), name(name), precedence{false, {0, PrecedenceType::RIGHT}} {}
|
|
Rule(const std::string& h, const std::vector<std::string>& t, const std::string& name, std::pair<int, PrecedenceType> precedence) :
|
|
head(h), tail(t), name(name), precedence{true, precedence} {}
|
|
};
|
|
|
|
/**
|
|
* A context free grammar
|
|
* Keeps track of variables, terminals and replacement rules
|
|
*/
|
|
struct Grammar {
|
|
std::string start; ///< the starting variable
|
|
std::set<std::string> variables; ///< the variables
|
|
std::set<std::string> terminals; ///< the terminals
|
|
std::deque<std::shared_ptr<Rule>> rules; ///< the replacement rules
|
|
std::map<std::string, std::pair<int, PrecedenceType> > precedence; ///< higher value -> higher precedence
|
|
|
|
std::unique_ptr<util::FirstSet> first;
|
|
std::unique_ptr<util::FollowSet> follow;
|
|
|
|
Grammar() : start(""), variables(), terminals(), rules(), precedence(), first(nullptr), follow(nullptr)
|
|
{}
|
|
|
|
Grammar(const Grammar& rhs)
|
|
: start(rhs.start), variables(rhs.variables), terminals(rhs.terminals)
|
|
, rules(rhs.rules), precedence(rhs.precedence), first(nullptr), follow(nullptr) {
|
|
if (rhs.first)
|
|
first = std::make_unique<util::FirstSet>(*rhs.first);
|
|
if (rhs.follow)
|
|
follow = std::make_unique<util::FollowSet>(*rhs.follow);
|
|
}
|
|
};
|
|
}
|
|
|
|
#endif //PARSODUS_GRAMMAR_H
|