school/cs236/parser/parser.cpp

201 lines
4.4 KiB
C++

#include "parser.h"
string parser::get_token() {
string type = tokens[0].type;
return type;
}
void parser::check_datalog() {
match("SCHEMES");
match("COLON");
if(get_token() == "FACTS") {
error();
}
check_schemelist(get_token());
match("FACTS");
match("COLON");
check_factlist(get_token());
match("RULES");
match("COLON");
check_rulelist(get_token());
match("QUERIES");
match("COLON");
check_querylist(get_token());
out();
}
string parser::out() {
stringstream s;
s << "Success!" << endl;
s << "Schemes(" << schemelist.size() << "):" << endl;
for(unsigned int i = 0; i < schemelist.size(); i++) {
s << " " << schemelist[i].toString();
}
s << "Facts(" << factlist.size() << "):" << endl;
for(unsigned int i = 0; i < factlist.size(); i++) {
s << " " << factlist[i].toString(false);
}
s << "Rules(" << rulelist.size() << "):" << endl;
for(unsigned int i = 0; i < rulelist.size(); i++) {
s << " " << rulelist[i].toString();
}
s << "Queries(" << querylist.size() << "):" << endl;
double a = 0;
for(unsigned int i = 0; i < querylist.size(); i++) {
s << " " << querylist[i].toString(a);
}
s << "Domain(" << domain.size() << "):" << endl;
for (auto it=domain.cbegin(); it != domain.cend(); ++it) {
s << " '" << *it << "'" << endl;
}
return s.str();
}
void parser::check_schemelist(string type) {
if(type == "FACTS") {
return;
}
else {
check_scheme(type);
check_schemelist(get_token());
}
}
void parser::check_scheme(string type) {
schemelist.push_back(check_predicate(type));
}
void parser::check_factlist(string type) {
if(type == "RULES") {
return;
}
else {
check_fact(type);
check_factlist(get_token());
}
}
void parser::check_fact(string type) {
factlist.push_back(check_predicate(type));
match("PERIOD");
}
void parser::check_rulelist(string type) {
if(type == "QUERIES") {
return;
}
else {
check_rule(type);
check_rulelist(get_token());
}
}
void parser::check_rule(string type) {
rule r;
r.head = check_predicate(type);
match("COLON_DASH");
check_predicate_list(get_token(), r);
match("PERIOD");
rulelist.push_back(r);
}
void parser::check_querylist(string type) {
check_query(type);
if(tokens.empty()) {
return;
}
else {
check_querylist(get_token());
}
}
void parser::check_query(string type) {
querylist.push_back(check_predicate(type));
match("Q_MARK");
}
void parser::check_predicate_list(string type, rule& r) {
r.pred_rule.push_back(check_predicate(type));
if(get_token() == "COMMA") {
match("COMMA");
check_predicate_list(get_token(), r);
}
else {
return;
}
}
predicate parser::check_predicate(string type) {
predicate pred;
pred.id = tokens[0].character;
match("ID");
match("LEFT_PAREN");
if(get_token() == "RIGHT_PAREN") {
error();
}
check_parameterlist(get_token(), pred);
match("RIGHT_PAREN");
return pred;
}
void parser::check_parameterlist(string type, predicate& pred) {
if(type == "RIGHT_PAREN") {
return;
}
else {
check_parameter(type, pred);
if(get_token() == "COMMA") {
match("COMMA");
if(get_token() == "RIGHT_PAREN") {
error();
}
check_parameterlist(get_token(), pred);
}
else {
return;
}
}
}
void parser::check_parameter(string type, predicate& pred) {
parameter para;
if(type == "STRING") {
domain.insert(tokens[0].character);
para.param = tokens[0].character;
para.type = tokens[0].type;
pred.pred_list.push_back(para);
match("STRING");
return;
}
else if(type == "ID") {
para.param = tokens[0].character;
para.type = tokens[0].type;
pred.pred_list.push_back(para);
match("ID");
return;
}
else {
error();
}
}
void parser::match(string type) {
if(get_token() == type) {
if(tokens.empty()) {
error();
}
else {
tokens.erase(tokens.begin());
}
}
else {
error();
}
}
void parser::error() {
stringstream oss;
oss << tokens[0] << endl;
throw oss.str();
}