Created
May 8, 2015 15:28
-
-
Save ilev4ik/7ef7c294350bd434eb37 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include "stdafx.h" | |
#include "analysis.h" | |
#include "enums.h" | |
#include <sstream> | |
#include <stack> | |
#include <vector> | |
#include <cmath> | |
#include <string.h> | |
//Конструкторы | |
Operation::Operation(int type_, double data_, bool isInt_ = false) | |
{ | |
type = type_; | |
data = data_; | |
isInt = isInt_; | |
} | |
Lexeme::Lexeme(int type_ = LEX_NULL, int index_ = LEX_NULL, const std::string& buf_ = "", double value_ = 0, bool isInt_ = false) | |
{ | |
Lexeme::type = type_; | |
Lexeme::index = index_; | |
Lexeme::buf = buf_; | |
Lexeme::value = value_; | |
Lexeme::isInt = isInt_; | |
} | |
Parser::Parser(const std::string& file_name) | |
{ | |
ifs = new std::ifstream; | |
ifs->exceptions(std::ifstream::failbit | std::ifstream::badbit); | |
try { | |
ifs->open(file_name, std::ifstream::in); | |
std::cout << "file " << file_name << " has been correctly opened\n"; | |
} | |
catch (const std::ifstream::failure& ferr) { | |
std::cerr << "Exception opening" << file_name | |
<< "\nError: " << ferr.what(); | |
std::cin.get(); | |
std::exit(EXIT_FAILURE); | |
} | |
line_num = 1; | |
logical = false; | |
varStart = countOfVars = 0; | |
} | |
Parser::~Parser() | |
{ | |
try { | |
ifs->close(); | |
std::cout << "file has been correctly closed\n"; | |
} | |
catch(const std::ifstream::failure& ferr) { | |
std::cerr << "Exception closing the opened file" | |
<< "\nError: " << ferr.what(); | |
std::cin.get(); | |
std::exit(EXIT_FAILURE); | |
} | |
delete this->ifs; | |
} | |
void Parser::setType(const int start, const int count, const int type) | |
{ | |
for (auto i = start; i < count; ++i) | |
this->variables[i].setVarType(type); | |
} | |
Variable::Variable(const std::string& name): varName(name) {}; | |
//Вспомогательные функции | |
void Parser::gc() | |
{ | |
this->ifs->get(currentChar); | |
} | |
int Parser::find(const char* buf, const char* list[]) | |
{ | |
int i = 0; | |
while (list[i] != 0) | |
{ | |
if (strcmp(list[i], buf) == 0) | |
return i; | |
i++; | |
} | |
return 0; | |
} | |
int Parser::findVariable(const std::string& var) | |
{ | |
for (int i = 0; i < (int)variables.size(); ++i) | |
if (variables[i].varName == var) | |
return i; | |
return -1; | |
} | |
void Variable::setVarType(const int type_) | |
{ | |
varType = type_; | |
} | |
//Чтение и разбиение на лексемы | |
void Parser::getNextLexeme() | |
{ | |
currentLex = readNextLexeme(); | |
} | |
Lexeme Parser::readNextLexeme() | |
{ | |
enum State {S, W, F}; | |
State currentState = S; | |
std::string buf; | |
while (true) | |
{ | |
switch (currentState) | |
{ | |
case S: | |
{ | |
if ( | |
currentChar == ' ' || | |
currentChar == '\t'|| | |
currentChar == '\n' | |
) | |
{ | |
if (currentChar == '\n') | |
this->line_num++; | |
gc(); | |
currentState = S; | |
} | |
else if (isdigit(currentChar)) | |
{ | |
bool floatMode = false; | |
int intPart = 0; | |
double floatPart = 0.0; | |
const double floatMul = 0.1; | |
int p = 1, dotCount = 0, digCount= 0; | |
while (true) | |
{ | |
if (isdigit(currentChar)) | |
{ | |
digCount++; | |
if (!floatMode) | |
{ | |
intPart = 10*intPart + (int)currentChar - (int)'0'; | |
gc(); | |
} | |
else | |
{ | |
floatPart = floatPart + ((int)currentChar - (int)'0')*std::pow(floatMul, p++); | |
gc(); | |
} | |
} | |
else if (currentChar == '.') | |
{ | |
floatMode = true; | |
if (++dotCount > 1) | |
throw "Invalid input in entered number"; | |
gc(); | |
} | |
else break; | |
} | |
std::stringstream ss; | |
ss << intPart + floatPart; | |
if (digCount == 0) | |
throw "no digit in number found"; | |
return Lexeme(LEX_NUMBER, LEX_NULL, ss.str(), intPart + floatPart, !floatMode); | |
} | |
else if (currentChar == '.') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_EOF, LEX_NULL, buf); | |
} | |
else if (isalpha(currentChar)) | |
{ | |
buf += currentChar; | |
gc(); | |
currentState = W; | |
} | |
else if (currentChar == '<') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_DELIM, LEX_DEL_LESS, buf); | |
} | |
else if (currentChar == '>') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_DELIM, LEX_DEL_MORE, buf); | |
} | |
else if (currentChar == '=') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_DELIM, LEX_DEL_EQUAL, buf); | |
} | |
else if (currentChar == '|') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_DELIM, LEX_DEL_OR, buf); | |
} | |
else if (currentChar == '&') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_DELIM, LEX_DEL_AND, buf); | |
} | |
else if (currentChar == '!') | |
{ | |
buf += currentChar; | |
gc(); | |
return Lexeme(LEX_DELIM, LEX_DEL_NOT, buf); | |
} | |
else if (currentChar == '?') | |
{ | |
buf += currentChar; | |
gc(); | |
currentState = F; | |
} | |
else | |
{ | |
buf += currentChar; | |
gc(); | |
if (currentChar == '=') | |
{ | |
buf += currentChar; | |
gc(); | |
} | |
int index = find(buf.c_str(), LEX_DELIMS); | |
return Lexeme(LEX_DELIM, index, buf); | |
} | |
break; | |
} | |
case F: | |
{ | |
if (isalpha(currentChar) || currentChar == '_') | |
{ | |
buf += currentChar; | |
gc(); | |
currentState = F; | |
} | |
else | |
{ | |
int index = find(buf.c_str(), LEX_FUNC_OP); | |
if (index == 0) | |
{ | |
index = find(buf.c_str(), LEX_FUNC_NP); | |
if (index == 0) | |
return Lexeme(LEX_NULL, LEX_NULL, buf); | |
else | |
return Lexeme(LEX_FUNC_NO_P, index, buf); | |
} | |
else | |
return Lexeme(LEX_FUNC_ONE_P, index, buf); | |
} | |
break; | |
} | |
case W: | |
{ | |
if (isalpha(currentChar)) | |
{ | |
buf += currentChar; | |
gc(); | |
currentState = W; | |
} | |
else | |
{ | |
int index = find(buf.c_str(), LEX_CONSTS); | |
if (index == 0) | |
{ | |
index = find(buf.c_str(), LEX_KEYWORDS); | |
if (index == 0) | |
{ | |
index = find(buf.c_str(), LEX_VAR_TYPES); | |
if (index == 0) | |
{ | |
index = find(buf.c_str(), LEX_OPERATOR_NP); | |
if (index == 0) | |
{ | |
index = find(buf.c_str(), LEX_OPERATOR_OP); | |
if (index == 0) | |
{ | |
index = find(buf.c_str(), LEX_OPERATOR_TP); | |
if (index == 0) | |
{ | |
return Lexeme(LEX_VAR, LEX_NULL, buf); | |
} | |
else | |
return Lexeme(LEX_OPERATOR_TWO_P, index, buf); | |
} | |
else | |
return Lexeme(LEX_OPERATOR_ONE_P, index, buf); | |
} | |
else | |
return Lexeme(LEX_OPERATOR_NO_P, index, buf); | |
} | |
else | |
return Lexeme(LEX_VAR_TYPE, index, buf); | |
} | |
else | |
return Lexeme(LEX_KEYWORD, index, buf); | |
} | |
else | |
return Lexeme(LEX_CONST, index, buf, (double)(index == LEX_CONST_TRUE)); | |
} | |
} | |
} //switch | |
} //while | |
} //func | |
//Логические и арифметические выражения | |
void Parser::NumEXP() | |
{ | |
if (currentLex.type == LEX_NUMBER) | |
{ | |
this->program.push_back(Operation(Operation::CONST, currentLex.value, currentLex.isInt)); | |
getNextLexeme(); | |
} | |
else if (currentLex.type == LEX_VAR) | |
{ | |
int varIndex = findVariable(currentLex.buf); | |
if (varIndex < 0) | |
throw "Unknown variable"; | |
this->program.push_back(Operation(Operation::VAR, varIndex)); | |
getNextLexeme(); | |
} | |
else if (currentLex.type == LEX_CONST) | |
{ | |
this->program.push_back(Operation(Operation::CONST, currentLex.value)); | |
getNextLexeme(); | |
} | |
else if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_BRLEFT | |
) | |
{ | |
getNextLexeme(); | |
Sum(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_BRRIGHT | |
) | |
throw ") ariphmetic missed"; | |
getNextLexeme(); | |
} | |
else if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_MIN | |
) | |
{ | |
this->program.push_back(Operation(Operation::CONST, 0)); //-x = 0-x | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
NumEXP(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
else throw "Invalid input entered"; | |
} | |
void Parser::Mul() | |
{ | |
NumEXP(); | |
if ( | |
currentLex.type == LEX_DELIM && | |
( | |
currentLex.index == LEX_DEL_DIV || | |
currentLex.index == LEX_DEL_MUL | |
) | |
) | |
{ | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
Mul(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
else if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_MOD | |
) | |
{ | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
Mul(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
} | |
void Parser::Sum() | |
{ | |
Mul(); | |
if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_ADD | |
) | |
{ | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
Sum(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
else if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_MIN | |
) | |
{ | |
Sum(); | |
this->program.push_back(Operation(Operation::BINARY, LEX_DEL_ADD)); | |
} | |
} | |
void Parser::LogEXP() | |
{ | |
Sum(); | |
if ( | |
currentLex.type == LEX_DELIM && | |
( | |
currentLex.index == LEX_DEL_LESS || | |
currentLex.index == LEX_DEL_MORE || | |
currentLex.index == LEX_DEL_EQUAL | |
) | |
) | |
{ | |
this->logical = true; | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
Sum(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
} | |
void Parser::LogEXT() | |
{ | |
if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_NOT | |
) | |
{ | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
LogEXT(); | |
this->program.push_back(Operation(Operation::UNARY, operation.index)); | |
} | |
else if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_BROPEN | |
) | |
{ | |
logical = true; | |
getNextLexeme(); | |
LogOR(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_BRCLOSE | |
) | |
throw "] logic needed"; | |
getNextLexeme(); | |
} | |
else LogEXP(); | |
} | |
void Parser::LogAND() | |
{ | |
LogEXT(); | |
if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_AND | |
) | |
{ | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
LogAND(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
} | |
void Parser::LogOR() | |
{ | |
LogAND(); | |
if ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_OR | |
) | |
{ | |
Lexeme operation = currentLex; | |
getNextLexeme(); | |
LogOR(); | |
this->program.push_back(Operation(Operation::BINARY, operation.index)); | |
} | |
} | |
//Программа (наш язык) | |
void Parser::PARSE_PROGRAM() | |
{ | |
if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_PROG | |
) | |
{ | |
getNextLexeme(); | |
VAR(); | |
//объявление переменных | |
PARSE_BLOCK(); | |
//BEGIN...END | |
if (currentLex.type != LEX_EOF) | |
throw "final . (dot) missed"; | |
} | |
else throw "invalid program start"; | |
} | |
void Parser::VAR() | |
{ | |
if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_GETVAR | |
) | |
{ | |
getNextLexeme(); | |
PARSE_INIT(); | |
while ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_COM | |
) | |
{ | |
getNextLexeme(); | |
PARSE_INIT(); | |
} | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_SEMICOLON | |
) | |
throw "; needed"; | |
getNextLexeme(); | |
} | |
} | |
void Parser::PARSE_INIT() | |
{ | |
if (currentLex.type == LEX_VAR) | |
{ | |
variables.push_back(Variable(currentLex.buf)); | |
countOfVars++; | |
getNextLexeme(); | |
while ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_COM | |
) | |
{ | |
getNextLexeme(); | |
if (currentLex.type != LEX_VAR) | |
throw "variable not found"; | |
variables.push_back(Variable(currentLex.buf)); | |
countOfVars++; | |
getNextLexeme(); | |
} | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_COLON | |
) | |
throw ": missed"; | |
getNextLexeme(); | |
if (currentLex.type == LEX_VAR_TYPE) | |
{ | |
getVarType(); | |
} | |
else if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_ARR | |
) | |
{ | |
//Тут куч всего добавить ещё надо | |
getNextLexeme(); | |
if ( | |
currentLex.type != LEX_KEYWORD || | |
currentLex.index != LEX_KW_OF | |
) | |
throw "invalid array declaration"; | |
getNextLexeme(); | |
Sum(); //N - size of array | |
getVarType(); | |
} | |
getNextLexeme(); | |
} | |
} | |
void Parser::PARSE_BLOCK() | |
{ | |
if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_BEGIN | |
) | |
{ | |
getNextLexeme(); | |
PARSE_EXPRESSION(); | |
while ( | |
currentLex.type == LEX_DELIM && | |
currentLex.index == LEX_DEL_SEMICOLON | |
) | |
{ | |
getNextLexeme(); | |
PARSE_EXPRESSION(); | |
} | |
if ( | |
currentLex.type != LEX_KEYWORD || | |
currentLex.index != LEX_KW_END | |
) | |
throw "block has no finish marker"; | |
getNextLexeme(); | |
} | |
//else throw "block has no start marker"; | |
} | |
void Parser::PARSE_EXPRESSION() | |
{ | |
if (currentLex.type == LEX_VAR) | |
{ | |
int varIndex = findVariable(currentLex.buf); | |
if (varIndex < 0) | |
throw "unknown variable"; | |
getNextLexeme(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_INIT | |
) | |
throw "assignment (:=) expected"; | |
getNextLexeme(); | |
LogOR(); | |
this->program.push_back(Operation(Operation::ASSIGN, varIndex)); | |
} | |
else if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_IF | |
) | |
{ | |
getNextLexeme(); | |
LogOR(); | |
this->program.push_back(Operation(Operation::IF_JMP_FALSE, 0)); | |
int jumpPos = this->program.size() - 1; | |
if ( | |
currentLex.type != LEX_KEYWORD || | |
currentLex.index != LEX_KW_THEN | |
) | |
throw "\"then\" needed after condition operator"; | |
getNextLexeme(); | |
PARSE_EXPRESSION(); | |
program[jumpPos].data = this->program.size(); | |
if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_ELSE | |
) | |
{ | |
getNextLexeme(); | |
PARSE_EXPRESSION(); | |
} | |
} | |
else if ( | |
currentLex.type == LEX_KEYWORD && | |
currentLex.index == LEX_KW_WHILE | |
) | |
{ | |
getNextLexeme(); | |
LogOR(); | |
this->program.push_back(Operation(Operation::WHILE_JMP_FALSE, 0)); | |
int jumpPos = this->program.size() - 1; | |
if ( | |
currentLex.type != LEX_KEYWORD || | |
currentLex.index != LEX_KW_DO | |
) | |
throw "\"do\" needed after loop operator"; | |
getNextLexeme(); | |
PARSE_EXPRESSION(); | |
program[jumpPos].data = program.size(); | |
} | |
else if (currentLex.type == LEX_FUNC_NO_P) | |
{ | |
getNextLexeme(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_BRLEFT | |
) | |
throw "no-parameter function has no left '(' brace"; | |
getNextLexeme(); | |
//Заполнить | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_BRRIGHT | |
) | |
throw "no-parameter function has no right ')' brace"; | |
getNextLexeme(); | |
} | |
else if (currentLex.type == LEX_FUNC_ONE_P) | |
{ | |
getNextLexeme(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_BRLEFT | |
) | |
throw "one-parameter function has no left '(' brace"; | |
getNextLexeme(); | |
if (currentLex.type != LEX_NUMBER) | |
throw "wrong parameter type in one-parameter function"; | |
//Заполнить | |
LogOR(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_BRRIGHT | |
) | |
throw "one-parameter function has no right ')' brace"; | |
getNextLexeme(); | |
} | |
else if (currentLex.type == LEX_OPERATOR_NO_P) | |
{ | |
//smth | |
getNextLexeme(); | |
} | |
else if (currentLex.type == LEX_OPERATOR_ONE_P) | |
{ | |
getNextLexeme(); | |
if (currentLex.type != LEX_NUMBER) | |
throw "wrong parameter type in one-parameter operator"; | |
//Заполнить | |
LogOR(); | |
} | |
else if (currentLex.type == LEX_OPERATOR_TWO_P) | |
{ | |
getNextLexeme(); | |
if (currentLex.type != LEX_NUMBER) | |
throw "wrong parameter type in one-parameter function"; | |
LogOR(); | |
if ( | |
currentLex.type != LEX_DELIM || | |
currentLex.index != LEX_DEL_COM | |
) | |
throw "no delimeter (,) has found in two-parameter operator"; | |
getNextLexeme(); | |
if (currentLex.type != LEX_NUMBER) | |
throw "wrong parameter type in one-parameter function"; | |
LogOR(); | |
} | |
else PARSE_BLOCK(); | |
} | |
//Для повторного обращения | |
void Parser::getVarType() | |
{ | |
if (currentLex.index == LEX_VT_INT) | |
{ | |
this->setType(varStart, countOfVars, Variable::INT); | |
varStart += countOfVars; | |
} | |
else if (currentLex.index == LEX_VT_DOUBLE) | |
{ | |
this->setType(varStart, countOfVars, Variable::DOUBLE); | |
varStart += countOfVars; | |
} | |
else if (currentLex.index == LEX_VT_BOOL) | |
{ | |
this->setType(varStart, countOfVars, Variable::BOOL); | |
varStart += countOfVars; | |
} | |
else if (currentLex.index == LEX_VT_STRING) | |
{ | |
this->setType(varStart, countOfVars, Variable::STRING); | |
varStart += countOfVars; | |
} | |
else throw "invalid variable type entered"; | |
} | |
//работа с ПОЛИЗом | |
void Parser::calculate() | |
{ | |
std::stack <double> stack; | |
std::vector <double> values; | |
values.resize(variables.size()); | |
int currOp = 0; | |
while (currOp < program.size()) | |
{ | |
Operation op = program[currOp]; | |
int nextOp = currOp + 1; | |
switch (op.type) | |
{ | |
case Operation::CONST: | |
{ | |
stack.push(op.data); | |
break; | |
} | |
case Operation::BINARY: | |
{ | |
double right = stack.top(); | |
stack.pop(); | |
double left = stack.top(); | |
stack.pop(); | |
switch ((int)op.data) | |
{ | |
case LEX_DEL_ADD: | |
stack.push(left + right); | |
break; | |
case LEX_DEL_MIN: | |
stack.push(left - right); | |
break; | |
case LEX_DEL_MUL: | |
stack.push(left * right); | |
break; | |
case LEX_DEL_DIV: | |
if (!right) | |
throw "division by zero detacted"; | |
stack.push(left / right); | |
break; | |
case LEX_DEL_MOD: | |
if ((int)right == 0) | |
throw "mod (%) division by zerp detected"; | |
else | |
stack.push((int)left % (int)right); | |
break; | |
case LEX_DEL_LESS: | |
stack.push(left < right); | |
break; | |
case LEX_DEL_MORE: | |
stack.push(left > right); | |
break; | |
case LEX_DEL_EQUAL: | |
stack.push(left == right); | |
break; | |
case LEX_DEL_AND: | |
stack.push(left && right); | |
break; | |
case LEX_DEL_OR: | |
stack.push(left || right); | |
break; | |
default: throw "Unknown binary operation"; | |
} | |
break; | |
} | |
case Operation::UNARY: | |
{ | |
double arg = stack.top(); | |
stack.pop(); | |
switch ((int)op.data) | |
{ | |
case LEX_DEL_MIN: | |
stack.push(-arg); | |
break; | |
case LEX_DEL_NOT: | |
stack.push(!arg); | |
break; | |
default: throw "Unknown unary operation"; | |
} | |
break; | |
} | |
case Operation::ASSIGN: | |
{ | |
double var = stack.top(); | |
stack.pop(); | |
values[(int)op.data] = var; | |
break; | |
} | |
case Operation::VAR: | |
{ | |
stack.push(values[(int)op.data]); | |
break; | |
} | |
case Operation::IF_JMP_FALSE: | |
{ | |
double val = stack.top(); | |
stack.pop(); | |
if (!val) | |
nextOp = op.data; | |
break; | |
} | |
case Operation::WHILE_JMP_FALSE: | |
{ | |
break; | |
} | |
default: throw "Unknown operation type"; | |
} | |
currOp = nextOp; | |
} | |
return; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include "stdafx.h" | |
#include <string> | |
#include <vector> | |
#include <iostream> | |
#include <fstream> | |
#ifndef CLASS_H | |
#define CLASS_H | |
class Lexeme | |
{ | |
public: | |
int type; | |
int index; | |
std::string buf; | |
double value; | |
bool isInt; | |
Lexeme(int, int, const std::string&, double, bool); | |
}; | |
class Operation | |
{ | |
public: | |
int type; | |
double data; | |
bool isInt; | |
enum Type { | |
CONST, | |
BINARY, | |
UNARY, | |
ASSIGN, | |
VAR, | |
IF_JMP_FALSE, | |
WHILE_JMP_FALSE | |
}; | |
Operation(int, double, bool); | |
}; | |
class Variable | |
{ | |
public: | |
enum Type { | |
INT, | |
DOUBLE, | |
STRING, | |
BOOL | |
}; | |
std::string varName; | |
int varType; | |
std::string value; | |
void setVarType(const int); | |
Variable(const std::string&); | |
}; | |
class Parser | |
{ | |
public: | |
Parser(const std::string&); //конструктор | |
~Parser(); | |
std::ifstream* ifs; | |
char currentChar; | |
bool logical; | |
unsigned int line_num; | |
int varStart, countOfVars; | |
Lexeme currentLex; | |
Lexeme readNextLexeme(); | |
std::vector <Operation> program; | |
std::vector <Variable> variables; | |
int find(const char*, const char**); | |
int findVariable(const std::string&); | |
void gc(); | |
void getNextLexeme(); | |
void setType(const int, const int, const int); | |
void getVarType(); | |
//Парсим язык | |
void PARSE_PROGRAM(); | |
void VAR(); | |
void PARSE_BLOCK(); | |
void PARSE_INIT(); | |
void PARSE_EXPRESSION(); | |
//Процедуры РС-метода | |
void Sum(); | |
void Mul(); | |
void NumEXP(); | |
//Логический разбор | |
void LogEXP(); | |
void LogOR(); | |
void LogAND(); | |
void LogEXT(); | |
//Вычисление ПОЛИЗа | |
void calculate(); | |
}; | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include "stdafx.h" | |
enum LexType { | |
LEX_NULL, //для ошибок и нераспознанных лексем + | |
LEX_VAR_TYPE, | |
LEX_NUMBER, //числа + | |
LEX_CONST_STR, //константные строки типа | |
LEX_CONST, | |
LEX_DELIM, //логическое выражение + | |
LEX_VAR, //переменные | |
LEX_FUNC_NO_P, //функции без параметров | |
LEX_FUNC_ONE_P, //с одним параметром | |
LEX_OPERATOR_NO_P, //операторы без параметров | |
LEX_OPERATOR_ONE_P, //один параметр | |
LEX_OPERATOR_TWO_P, //два параметра | |
LEX_KEYWORD, //if, then, while + | |
LEX_EOF //конец ввода + | |
}; | |
enum LexVarType { | |
LEX_VT_NULL, | |
LEX_VT_INT, | |
LEX_VT_DOUBLE, | |
LEX_VT_BOOL, | |
LEX_VT_STRING | |
}; | |
const char* LEX_VAR_TYPES [] = { | |
"", | |
"int", | |
"double", | |
"bool", | |
"string", | |
0 | |
}; | |
enum LexConst { | |
LEX_CONST_NULL, | |
LEX_CONST_TRUE, | |
LEX_CONST_FALSE | |
}; | |
const char* LEX_CONSTS [] = { | |
"", | |
"true", | |
"false", | |
0 | |
}; | |
enum LexKeyword { | |
LEX_KW_NULL, | |
LEX_KW_PROG, | |
LEX_KW_GETVAR, | |
LEX_KW_BEGIN, | |
LEX_KW_END, | |
LEX_KW_IF, | |
LEX_KW_THEN, | |
LEX_KW_ELSE, | |
LEX_KW_WHILE, | |
LEX_KW_DO, | |
LEX_KW_ARR, | |
LEX_KW_OF | |
}; | |
const char* LEX_KEYWORDS [] = { | |
"", | |
"program", | |
"init", | |
"start", | |
"finish", | |
"if", | |
"then", | |
"else", | |
"while", | |
"do", | |
"array", | |
"of", | |
0 | |
}; | |
enum LexOperatorNoP { | |
LEX_NOP_NULL, | |
LEX_NOP_END | |
}; | |
const char* LEX_OPERATOR_NP [] = { | |
"", | |
"endturn", | |
0 | |
}; | |
enum LexOperatorOneP { | |
LEX_OOP_NULL, | |
LEX_OOP_PROD, | |
LEX_OOP_BUILD | |
}; | |
const char* LEX_OPERATOR_OP [] = { | |
"", | |
"prod", | |
"build", | |
0 | |
}; | |
enum LexOperatorTwoP { | |
LEX_TOP_NULL, | |
LEX_TOP_BUY, | |
LEX_TOP_SELL | |
}; | |
const char* LEX_OPERATOR_TP [] = { | |
"", | |
"buy", | |
"sell", | |
0 | |
}; | |
enum LexFuncOneParam { | |
LEX_FUNC_OP_NULL, | |
LEX_FUNC_OP_MONEY, | |
LEX_FUNC_OP_RAW, | |
LEX_FUNC_OP_PROD, | |
LEX_FUNC_OP_FACT, | |
LEX_FUNC_OP_AUTO_FACT, | |
LEX_FUNC_OP_MANUF, | |
LEX_FUNC_OP_RES_RAW_SOLD, | |
LEX_FUNC_OP_RES_RAW_PRICE, | |
LEX_FUNC_OP_RES_PROD_BOUGHT, | |
LEX_FUNC_OP_RES_PROD_PRICE | |
}; | |
const char* LEX_FUNC_OP [] = { | |
"", | |
"?money", | |
"?raw", | |
"?production", | |
"?factories", | |
"?auto_factories", | |
"?manufactured", | |
"?result_raw_sold", | |
"?result_raw_price", | |
"?result_prod_bought", | |
"?result_prod_price", | |
0 | |
}; | |
enum LexFuncNoParam { | |
LEX_FUNC_NP_NULL, | |
LEX_FUNC_NP_MYID, | |
LEX_FUNC_NP_TURN, | |
LEX_FUNC_NP_PLAYERS, | |
LEX_FUNC_NP_ACT_PLAYERS, | |
LEX_FUNC_NP_SUPPLY, | |
LEX_FUNC_NP_RAW_PRICE, | |
LEX_FUNC_NP_DEMAND, | |
LEX_FUNC_NP_PROD_PRICE | |
}; | |
const char* LEX_FUNC_NP [] = { | |
"", | |
"?my_id", | |
"?turn", | |
"?players", | |
"?active_players", | |
"?supply", | |
"?raw_price", | |
"?demand", | |
"?production_price", | |
0 | |
}; | |
enum LexDelims { | |
LEX_DEL_NULL, | |
LEX_DEL_ADD, | |
LEX_DEL_MIN, | |
LEX_DEL_MUL, | |
LEX_DEL_DIV, | |
LEX_DEL_MOD, | |
LEX_DEL_BROPEN, //квадратные скобки | |
LEX_DEL_BRCLOSE, | |
LEX_DEL_BRLEFT, //круглые скобки | |
LEX_DEL_BRRIGHT, | |
LEX_DEL_LESS, | |
LEX_DEL_MORE, | |
LEX_DEL_EQUAL, | |
LEX_DEL_OR, | |
LEX_DEL_AND, | |
LEX_DEL_NOT, | |
LEX_DEL_COM, //запятая | |
LEX_DEL_SEMICOLON, //точка с запятой | |
LEX_DEL_COLON, | |
LEX_DEL_INIT | |
}; | |
const char* LEX_DELIMS [] = { | |
"", | |
"+", | |
"-", | |
"*", | |
"/", | |
"%", | |
"[", | |
"]", | |
"(", | |
")", | |
"<", | |
">", | |
"=", | |
"|", | |
"&", | |
"!", | |
",", | |
";", | |
":", | |
":=", | |
0 | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//#include "stdafx.h" | |
#include "analysis.h" | |
#include <iomanip> | |
int main() | |
{ | |
std::cout << "Haykakan Si, brat. Gri inch uzumes, mernem srtit\n"; | |
Parser syntaxAn("code.txt"); | |
try { | |
syntaxAn.gc(); | |
syntaxAn.getNextLexeme(); | |
syntaxAn.PARSE_PROGRAM(); | |
} | |
catch (const char* err) { | |
std::cout << "Error parsing: " << err << ", but " | |
<< "{" << syntaxAn.currentLex.type | |
<< ", " << syntaxAn.currentLex.index | |
<< ", " << syntaxAn.currentLex.buf | |
<< ", " << syntaxAn.currentLex.value | |
<< "} got " << "in line #" << syntaxAn.line_num << std::endl; | |
std::cin.get(); | |
return 1; | |
} | |
std::cout << "Expression parsed, calculating...\n"; | |
std::cin.get(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment