Pagini recente » Cod sursa (job #1556525) | Cod sursa (job #431070) | Cod sursa (job #1835464) | Cod sursa (job #3162040) | Cod sursa (job #1296724)
#include <fstream>
#include <iostream>
#include <vector>
#include <cctype>
#include <string>
enum class TokenType {
Variable,
And,
Or,
Not,
OpenParanthesis,
ClosedParanthesis,
Undefined
};
struct Var {
char key;
bool value;
void flip() {
value = !value;
}
};
struct Token {
TokenType type;
Var* var;
Token() : Token(TokenType::Undefined) {}
Token(TokenType type) : Token(type,nullptr) {}
Token(TokenType type, Var* var) :
type(type) , var(var) {}
};
std::vector<Var> variables;
Var True{'t',true};
Var False{'f',false};
class Tokenizer {
std::vector<Token> tokens;
unsigned index;
std::string text;
private:
void SkipWhitespace() {
while(isspace(text[index]))index++;
}
Token getConstant() {
std::string rT("TRUE");
std::string rF("FALSE");
unsigned myIndex = index;
while(myIndex-index < rT.size() && rT[myIndex-index] == text[myIndex]) myIndex++;
if(myIndex-index == rT.size()) {
index = myIndex;
return Token(TokenType::Variable,&True);
}
myIndex = index;
while(myIndex-index < rF.size() && rF[myIndex-index] == text[myIndex]) myIndex++;
if(myIndex-index == rF.size()) {
index = myIndex;
return Token(TokenType::Variable,&False);
}
return Token(TokenType::Undefined);
}
Token getVariable() {
return Token(TokenType::Variable,&(variables[text[index++]-'A']));
}
Token getOperator() {
std::vector<std::pair<Token,std::string>>
operators {{Token(TokenType::Not),std::string("NOT")},
{Token(TokenType::And),std::string("AND")},
{Token(TokenType::Or),std::string("OR")}};
for(const auto & op:operators) {
unsigned myIndex = index;
while(myIndex-index < op.second.size() && op.second[myIndex-index] == text[myIndex]) myIndex++;
if(myIndex-index == op.second.size()) {
index = myIndex;
return op.first;
}
}
return Token(TokenType::Undefined);
}
Token getToken() {
SkipWhitespace();
if(text[index] == '(') {
index++;
return Token(TokenType::OpenParanthesis);
}
else if(text[index] == ')') {
index++;
return Token(TokenType::ClosedParanthesis);
}
else {
Token t = getConstant();
if(t.type == TokenType::Undefined)
t = getOperator();
if(t.type == TokenType::Undefined)
t = getVariable();
return t;
}
}
public:
std::vector<Token> Tokenize(const std::string & text) {
this->index = 0;
this->text = text;
while(index < this->text.size()) {
tokens.push_back(getToken());
}
return tokens;
}
};
enum class ASTNodeType {
Undefined,
OperatorOr,
OperatorAnd,
OperatorNot,
Variable
};
struct ASTNode {
ASTNodeType type;
Var * var;
ASTNode * left;
ASTNode * right;
ASTNode() : ASTNode(ASTNodeType::Undefined, nullptr, nullptr) {}
ASTNode(ASTNodeType type, ASTNode * left, ASTNode * right):
type(type), left(left),right(right) {}
};
class Parser {
std::vector<Token>::iterator currentToken;
private:
ASTNode * Atom() {
ASTNode * atm = new ASTNode();
switch(currentToken->type) {
case TokenType::OpenParanthesis:
currentToken++;
atm = Expression();
currentToken++;
break;
case TokenType::Not:
atm->type = ASTNodeType::OperatorNot;
currentToken++;
atm->left = Expression();
break;
case TokenType::Variable:
atm->type = ASTNodeType::Variable;
atm->var = currentToken->var;
currentToken++;
break;
}
return atm;
}
ASTNode * Expression() {
ASTNode * atom = Atom();
ASTNodeType type = ASTNodeType::Undefined;
switch(currentToken->type){
case TokenType::And :
type = ASTNodeType::OperatorAnd;
currentToken++;
break;
case TokenType::Or :
type = ASTNodeType::OperatorOr;
currentToken++;
break;
default :
return atom;
}
ASTNode * expr = Expression();
return new ASTNode(type,atom,expr);
}
public:
ASTNode * Parse(std::vector<Token>::iterator begin) {
currentToken = begin;
return Expression();
}
};
void initVars() {
variables.resize('Z'-'A');
for(unsigned i = 0; i < 'Z'-'A'; i++) {
variables[i].key = static_cast<char>('A' + i);
variables[i].value = false;
}
}
std::string GetRepr(ASTNodeType type) {
switch(type)
{
case ASTNodeType::OperatorOr:
return "OperatorOr";
case ASTNodeType::OperatorAnd:
return "OperatorAnd";
case ASTNodeType::OperatorNot:
return "OperatorNot";
case ASTNodeType::Variable:
return "Variable";
}
}
std::ifstream in("bool.in");
void printAST(ASTNode * node, unsigned depth=0) {
if(node->type == ASTNodeType::Variable) {
std::cerr << depth << ".Variable{ " << node->var->key << " };\n";
return;
}
std::cerr << depth << "." << GetRepr(node->type) << "{ Left:" << GetRepr(node->left->type);
if(node->right)
std::cerr << ", "<< "Right: " << GetRepr(node->right->type);
std::cerr << "};\n";
if(node->left)
printAST(node->left, depth+1);
if(node->right)
printAST(node->right, depth+1);
}
class Evaluator {
public:
bool Evaluate(ASTNode * ast) {
switch(ast->type) {
case ASTNodeType::Variable:
return ast->var->value;
case ASTNodeType::OperatorNot:
return !Evaluate(ast->left);
case ASTNodeType::OperatorAnd:
return Evaluate(ast->left) && Evaluate(ast->right);
case ASTNodeType::OperatorOr:
return Evaluate(ast->left) || Evaluate(ast->right);
}
}
};
std::ofstream out("bool.out");
int main() {
initVars();
Tokenizer t;
std::string text;
getline(in,text);
std::vector<Token> tokens = t.Tokenize(text);
Parser p;
ASTNode * ast = p.Parse(tokens.begin());
Evaluator e;
unsigned changes;
in >> changes;
in.ignore();
for(int i = 0; i < changes; ++i) {
char c;
in >> c;
variables[c-'A'].flip();
out << e.Evaluate(ast);
}
}