Parsodus/include/Parsodus/grammar.h

74 lines
2.7 KiB
C++

#pragma once
#ifndef PARSODUS_GRAMMAR_H
#include "Parsodus/util/firstset.h"
#include "Parsodus/util/followset.h"
#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() : head(""), tail(), name("") {}
Rule(const std::string& h, const std::vector<std::string>& t) : head(h), tail(t), name("") {}
Rule(const std::string& h, const std::vector<std::string>& t, const std::string& name) : head(h), tail(t), name(name) {}
Rule(const std::string& h, const std::vector<std::string>& t, const std::string& name, std::pair<bool, std::pair<int, PrecedenceType>> precedence) :
head(h), tail(t), name(name), precedence(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::vector<std::shared_ptr<Rule>> rules; ///< the replacement rules
std::map<std::string, std::pair<int, PrecedenceType> > precedence; ///< lower value -> higher precedence
std::unique_ptr<util::FirstSet> first;
std::unique_ptr<util::FollowSet> follow;
Grammar() : start(""), variables(), terminals(), rules(), 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