Добавил:
Studfiles2
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Интерпретатор / _sources / MyLanguage / SyntacticParser
.cpp#include <vector>
#include "SyntacticParser.hpp"
#include "TokenParser.hpp"
#include "Errors.hpp"
namespace Parser_impl {
PolizProgram* SyntaticParser::parse(std::istream& is)
{
prog = new PolizProgram;
tokens = new TokenParser(is);
tokens->getNextToken();
Program();
delete tokens;
return prog;
}
void SyntaticParser::Program()
{
while (token()->type != TYPE_DELIM || token()->getLong() != T_EOF ) {
if ( token()->type != TYPE_RES )
error("Wrong variable or function definition");
if (token()->getLong() == T_VAR){
currvarttable = &(prog->global);
Vardef();
} else
Func();
}
checkProgram();
}
/**
* needs currvarttable
**/
void SyntaticParser::Vardef()
{
assert_token(TYPE_RES, T_VAR);
tokens->getNextToken();
if (token()->type != TYPE_RES)
error("Wrong variable type, 'int' or 'float' expected");
ElementTypes type;
if (token()->getLong() == T_INT)
type = INT;
else if (token()->getLong() == T_FLOAT)
type = FLOAT;
else
error("Wrong variable type, 'int' or 'float' expected");
tokens->getNextToken();
assert_token(TYPE_ID, 0);
if (currvarttable->contains(token()->str))
error("Redeclaration of '" + token()->str +"'");
currvarttable->put(token()->str, Variable(type, 0.0));
tokens->getNextToken();
for(;;){
if ( token()->type != TYPE_DELIM){
break;
} else if ( token()->getLong()!= T_COMMA )
break;
tokens->getNextToken();
assert_token(TYPE_ID, 0);
if (currvarttable->contains(token()->str))
error("Redeclaration of '" + token()->str +"'");
currvarttable->put(token()->str, Variable(type, 0));
tokens->getNextToken();
}
}
void SyntaticParser::Func()
{
if (token()->type != TYPE_RES)
error("Wrong variable or function definition");
Function fun;
std::string fun_name;
if (token()->getLong() == T_VOID)
fun.return_type = VOID;
else if (token()->getLong() == T_INT)
fun.return_type = INT;
else if (token()->getLong() == T_FLOAT)
fun.return_type = FLOAT;
else
error("Wrong function return type declaration, expected 'int', 'float' or 'void'");
tokens->getNextToken();
assert_token(TYPE_ID, 0);
fun_name = token()->str;
tokens->getNextToken();
assert_token(TYPE_DELIM, T_LBRACK);
tokens->getNextToken();
bool expected = false;
for(;;){
if ( token()->type == TYPE_DELIM && token()->getLong() == T_RBRACK){
if (expected)
error("Wrong ';' before ')'");
break;
}
expected =false;
if (token()->type != TYPE_RES)
error("Wrong argument type, 'int' or 'float' expected");
Variable var;
if (token()->getLong() == T_INT)
var.type = INT;
else if (token()->getLong() == T_FLOAT)
var.type = FLOAT;
else
error("Wrong argument type, 'int' or 'float' expected");
tokens->getNextToken();
assert_token (TYPE_ID, 0);
if (fun.local.contains(token()->str))
error("Redeclaration of '" + token()->str + "'");
fun.local.put(token()->str, var);
tokens->getNextToken();
if (token()->type == TYPE_DELIM) {
if (token()->getLong() == T_SEMIC){
expected = true;
tokens->getNextToken();
} else if (token()->getLong() != T_RBRACK)
error("Wrong delimitor, ';' is used to separate function arguments");
} else
error("Wrong delimitor, ';' is used to separate function arguments");
}
fun.args_count = fun.local.getSize();
fun.name = fun_name;
tokens->getNextToken();
if (token()->type == TYPE_DELIM && token()->getLong() == T_SEMIC){
fun.declared = false;
if (prog->functions.contains(fun_name)){
if (!fun.hasParamsEqualTo(prog->functions.get(fun_name)))
error("Function redeclaration with different arguments or return value");
} else {
prog->functions.put(fun_name, fun);
}
tokens->getNextToken();
return;
} else {
fun.declared = true;
if (prog->functions.contains(fun_name)){
Function& f = prog->functions.get(fun_name);
if (!fun.hasParamsEqualTo(f))
error("Function redeclaration with different arguments or return value");
if (f.declared)
error("Function already defined");
f.declared = true;
currfunc = &f;
} else {
int i = prog->functions.put(fun_name, fun);
currfunc = &(prog->functions.get(i));
}
BL();
}
}
/* *
* needs currfunc
* */
void SyntaticParser::BL()
{
assert_token(TYPE_RES, T_BEGIN);
tokens->getNextToken();
if (!(token()->type == TYPE_RES && token()->getLong()==T_END)){
ST();
while ( token()->type == TYPE_DELIM && token()->getLong()==T_SEMIC){
tokens->getNextToken();
if (token()->type == TYPE_RES && token()->getLong()==T_END)
error("';' can't stand before 'end'. ';' is statement separator, not statement end");
ST();
}
}
assert_token(TYPE_RES, T_END);
tokens->getNextToken();
}
/* *
* needs currfunc
* */
void SyntaticParser::ST()
{
if (token()->type == TYPE_RES) {
long t = token()->getLong();
if (t == T_VAR){
currvarttable = &(currfunc->local);
Vardef();
} else if (t == T_IF){
tokens->getNextToken();
E();
int start = currfunc->code.size();
currfunc->code.push_back( PolizInstruction(TIfNot) );
assert_token(TYPE_RES, T_THEN);
tokens->getNextToken();
ST();
int gt1 = currfunc->code.size();
if (token()->type == TYPE_RES && token()->getLong() == T_ELSE){
currfunc->code.push_back( PolizInstruction(TGoto) );
++gt1;
tokens->getNextToken();
ST();
(currfunc->code)[start].val = gt1;
(currfunc->code)[gt1-1].val = currfunc->code.size();
} else {
(currfunc->code)[start].val = gt1;
}
} else if (t == T_WHILE){
int start = currfunc->code.size();
tokens->getNextToken();
E();
assert_token(TYPE_RES, T_DO);
int gt = currfunc->code.size();
currfunc->code.push_back( PolizInstruction(TIfNot) );
tokens->getNextToken();
ST();
currfunc->code.push_back( PolizInstruction(TGoto, start) );
(currfunc->code)[gt].val = currfunc->code.size();
} else if (t == T_BEGIN){
BL();
} else if (t == T_RETURN){
if (currfunc->return_type == VOID)
error("Function can't return a value");
tokens->getNextToken();
E();
currfunc->code.push_back( PolizInstruction(TReturn, currfunc->return_type) );
} else if (t == T_WRITE){
tokens->getNextToken();
assert_token(TYPE_DELIM, T_LBRACK);
tokens->getNextToken();
int params = 0;
bool expected = false;
for(;;){
if (token()->type == TYPE_DELIM && token()->getLong()==T_RBRACK){
if (expected)
error("Wrong ',' before ')'");
break;
}
expected = false;
++params;
if (token()->type==TYPE_LITSTR){
PolizInstruction i = PolizInstruction(TStrLit, 0);
i.str=token()->str;
currfunc->code.push_back( i );
tokens->getNextToken();
} else
E();
if (token()->type == TYPE_DELIM){
if (token()->getLong()==T_COMMA){
expected = true;
tokens->getNextToken();
} else if (token()->getLong()!=T_RBRACK)
error("Operands in 'write' statement must be separated by ','");
} else
error("Operands in 'write' statement must be separated by ','");
}
if (params == 0)
error("'write' statetment can't be without arguments");
currfunc->code.push_back( PolizInstruction(TWrite, params) );
tokens->getNextToken();
} else if (t == T_READ){
tokens->getNextToken();
if (token()->type != TYPE_ID)
error("wrong 'read' statement. Expected ID after 'read'");
std::string& id = token()->str;
if (!containsId(id))
error("Undeclared identifier '" + id +"'");
currfunc->code.push_back( makeVarPoliz(id) );
currfunc->code.push_back( PolizInstruction(TRead) );
tokens->getNextToken();
} else if (t == T_EXIT ){
tokens->getNextToken();
E();
currfunc->code.push_back( PolizInstruction(TExit) );
} else
error("Wrong statement");
} else if (token()->type == TYPE_ID){
std::string id = token()->str;
tokens->getNextToken();
if (token()->type == TYPE_DELIM && token()->getLong() == T_LBRACK) {
// Function call
if (!prog->functions.contains(id))
error("Function '"+id+"' is not declared");
tokens->getNextToken();
int params = 0;
bool expected = false;
for(;;) {
if ( token()->type == TYPE_DELIM && token()->getLong() == T_RBRACK){
if (expected)
error("Wrong ',' befor ')'");
break;
}
expected =false;
++params;
E();
if (token()->type == TYPE_DELIM){
if (token()->getLong()==T_COMMA){
expected = true;
tokens->getNextToken();
} else if (token()->getLong()!=T_RBRACK)
error("Arguments must be separated by ',' in function call");
} else
error("Arguments must be separated by ',' in function call");
}
Function& f = prog->functions.get(id);
if (params != f.args_count)
error("Wrong number of arguments in function '" + f.name +"' call");
currfunc->code.push_back( PolizInstruction(TFunction, prog->functions.getPos(id)) );
if (f.return_type != VOID)
currfunc->code.push_back( PolizInstruction(TPOP) );
tokens->getNextToken();
} else if (token()->type == TYPE_OPER && token()->getLong() == T_ASS) {
// Assignment
if ( !containsId(id) )
error("ID '"+id+"' is not declared");
currfunc->code.push_back( makeVarPoliz(id) );
tokens->getNextToken();
E();
currfunc->code.push_back( PolizInstruction(TOperation, T_ASS) );
} else
error("Wrong statement. After ID expected '(' or '='");
} else
error("Wrong statement");
}
/* *
* needs currfunc
* */
void SyntaticParser::E()
{
E1();
while ( token()->type == TYPE_OPER && token()->getLong()==T_OR) {
tokens->getNextToken();
E1();
currfunc->code.push_back( PolizInstruction(TOperation, T_OR) );
}
}
void SyntaticParser::E1()
{
E2();
while ( token()->type == TYPE_OPER && token()->getLong()==T_AND) {
tokens->getNextToken();
E2();
currfunc->code.push_back( PolizInstruction(TOperation, T_AND) );
}
}
void SyntaticParser::E2()
{
E7();
if (token()->type == TYPE_OPER && (token()->getLong() == T_EQ ||
token()->getLong() == T_NEQ)){
int tt = token()->getLong();
tokens->getNextToken();
E7();
currfunc->code.push_back( PolizInstruction(TOperation, tt) );
}
}
void SyntaticParser::E3()
{
E4();
while ( token()->type == TYPE_OPER && (token()->getLong() == T_PLUS ||
token()->getLong() == T_MINUS ) ) {
int tt = token()->getLong();
tokens->getNextToken();
E4();
currfunc->code.push_back( PolizInstruction(TOperation, tt) );
}
}
void SyntaticParser::E4()
{
E5();
while ( token()->type == TYPE_OPER && (token()->getLong() == T_MUL ||
token()->getLong() == T_DIV ||
token()->getLong() == T_MOD ) ) {
int tt = token()->getLong();
tokens->getNextToken();
E5();
currfunc->code.push_back( PolizInstruction(TOperation, tt) );
}
}
void SyntaticParser::E5()
{
E6();
if (token()->type == TYPE_OPER && (token()->getLong() == T_DEG)){
int tt = token()->getLong();
tokens->getNextToken();
E6();
currfunc->code.push_back( PolizInstruction(TOperation, tt) );
}
}
void SyntaticParser::E6()
{
if (token()->type != TYPE_ID) {
if (token()->type == TYPE_RES && token()->getLong() == T_WASERROR){
currfunc->code.push_back( PolizInstruction(TWasError) );
tokens->getNextToken();
} else if (token()->type == TYPE_LIT){
PolizInstruction i(TLiteral,INT);
if (token()->isFloat)
i.val = FLOAT;
i.value = token()->value;
currfunc->code.push_back(i);
tokens->getNextToken();
}else if (token()->type == TYPE_OPER){
long op = token()->getLong();
if (op == T_NOT){
} else if (op == T_PLUS){
op = T_PLUSUN;
} else if (op == T_MINUS){
op = T_MINUSUN;
} else
error("Wrong operation in expression");
tokens->getNextToken();
E6();
currfunc->code.push_back( PolizInstruction(TOperation, op) );
} else if (token()->type == TYPE_DELIM && token()->getLong() == T_LBRACK){
tokens->getNextToken();
E();
assert_token(TYPE_DELIM, T_RBRACK);
tokens->getNextToken();
} else
error ("Wrong expression");
} else { // ID
assert_token(TYPE_ID, 0);
std::string id = token()->str;
int line = tokens->getLineNumber();
tokens->getNextToken();
if (token()->type == TYPE_DELIM && token()->getLong() == T_LBRACK) {
// Function call
if (!prog->functions.contains(id))
error("Function '"+id+"' is not declared");
Function& f = prog->functions.get(id);
if (f.return_type == VOID)
error("Function '" + f.name + "' doesn't return a value. You can't use it in expression");
tokens->getNextToken();
int params = 0;
bool expected = false;
for(;;) {
if ( token()->type == TYPE_DELIM && token()->getLong() == T_RBRACK){
if (expected)
error("Wrong ',' befor ')'");
break;
}
expected =false;
++params;
E();
if (token()->type == TYPE_DELIM){
if (token()->getLong()==T_COMMA){
expected = true;
tokens->getNextToken();
} else if (token()->getLong()!=T_RBRACK)
error("Arguments must be separated by ',' in function call");
} else
error("Arguments must be separated by ',' in function call");
}
tokens->getNextToken();
if (params != f.args_count)
error("Wrong number of arguments in function '" + f.name +"' call");
currfunc->code.push_back( PolizInstruction(TFunction, prog->functions.getPos(id)) );
}else {
// ID
if ( !containsId(id) )
throw SyntacticParserException("Id '"+id+"' is not declared", line);
currfunc->code.push_back( makeVarPoliz(id) );
}
}
}
void SyntaticParser::E7()
{
E3();
if (token()->type == TYPE_OPER && ( token()->getLong() == T_GRT ||
token()->getLong() == T_GRTEQ ||
token()->getLong() == T_LSS ||
token()->getLong() == T_LSSEQ ) ){
int tt = token()->getLong();
tokens->getNextToken();
E3();
currfunc->code.push_back( PolizInstruction(TOperation, tt) );
}
}
}
Соседние файлы в папке MyLanguage