You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1337 lines
28 KiB
1337 lines
28 KiB
#include <limits>
|
|
#include <vector>
|
|
#include <stack>
|
|
#include <vector>
|
|
#include <set>
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <valarray>
|
|
#include <iostream>
|
|
#include <cstring>
|
|
|
|
#define MAX_BUFFER 102400
|
|
|
|
char buffer[MAX_BUFFER + 2];
|
|
using namespace std;
|
|
|
|
enum Preservations {CONST, VAR, PROCEDURE, BEGIN, END, DOT/*EOF*/, COMMA, SEMICOLON/*END OF STATEMENT*/, IF, THEN, ELSE, CALL, READ, WRITE,
|
|
PLUS, MINUS, DIVISION, MULTIPLE, WHILE, DO, ASSIGNMENT, LP, RP, ODD, EQUAL, GREATER, LESS, GREATEREQ, LESSEQ, NOTEQ};
|
|
enum States { P, SP, C, V, PRO, CDEF, INIT, VDEF, ST, MORE, COND, EXP, EXP2, ARITH, ARI2, TERM, FACTS, MULDIV, FACT };
|
|
enum Operations{ INT, JMP, LIT, OPR, STO, CAL, JPC, LOD, SIO };//pl/0 USER MANUAL
|
|
const char *operations[] { "INT", "JMP", "LIT", "OPR", "STO", "CAL", "JPC", "LOD", "SIO" };
|
|
const char *preservations[] = { "CONST", "VAR", "PROCEDURE", "BEGIN", "END", ".", ",", ";", "IF", "THEN", "ELSE", "CALL","READ", "WRITE", "+", "-",
|
|
"/", "*", "WHILE", "DO", ":=", "(", ")", "ODD", "=", ">", "<", ">=", "<=", "#"};
|
|
int *** states, **follows ;
|
|
|
|
inline int** init_st(int i, ...);
|
|
enum Type { PSR, SYM, NUM };
|
|
//short status_pers_match = {false}; FOR LATER
|
|
#define P(a) a + 3
|
|
#define S(a) P(a) + NOTEQ + 1
|
|
#define DeS(a) a - 4 - NOTEQ
|
|
#define _S(a) a >= S(0) && a <= S(FACT)
|
|
#define init_follow(n, ...) init_st((n + 1), __VA_ARGS__, -1)[0]
|
|
#define A_MOD P(EQUAL)
|
|
|
|
struct IDS {
|
|
int type;
|
|
int index;
|
|
IDS(int type, int index) {
|
|
this->type = type;
|
|
this->index = index;
|
|
}
|
|
}**pres;
|
|
|
|
struct HASH {
|
|
|
|
IDS *id = 0;
|
|
char* value;
|
|
unsigned int* int_value = 0;
|
|
HASH(char* value, int index)
|
|
{
|
|
this->value = value;
|
|
int_value = NULL;
|
|
if (value[0] < '0' || value[0] > '9')
|
|
id = new IDS(1, index);
|
|
else
|
|
{
|
|
id = new IDS(2, index);
|
|
int_value = new unsigned int(0);
|
|
int length = strlen(value);
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
*int_value *= 10;
|
|
*int_value += value[i] - 48;
|
|
}
|
|
}
|
|
}
|
|
~HASH()
|
|
{
|
|
if (int_value != NULL)
|
|
delete(int_value);
|
|
if (id)
|
|
delete id;
|
|
}
|
|
};
|
|
|
|
vector<HASH *> sym;
|
|
vector<HASH *> num;
|
|
|
|
struct GrammaUnit {
|
|
int *follows;
|
|
};
|
|
|
|
vector<IDS*> identifiers;
|
|
|
|
|
|
void GETSYM() {
|
|
char* bp = buffer, token;
|
|
int n_syms = NOTEQ + 2;
|
|
unsigned char flags[1024] = { true };
|
|
int index = 0, lastLength = 0;
|
|
int j = 0, n_pre = 0, n_ids = 0, n_ids_const, n_nums = 0, n_nums_const , i = 0, nums_offset = 0, n_pre_const = 0;
|
|
bool takein = false, lastTaken = false;
|
|
IDS *lastMatch;
|
|
//init
|
|
pres = new IDS*[NOTEQ + 1];
|
|
for (j = 0; j <= NOTEQ; j++) {
|
|
pres[j] = new IDS(0, j);
|
|
}
|
|
|
|
while (*bp) {
|
|
takein = false;
|
|
lastTaken = false;
|
|
if (!index)
|
|
{
|
|
while (*bp == '\t' || *bp == '\n' || *bp == ' ' || *bp == '\r')
|
|
bp++;
|
|
n_pre = NOTEQ + 1;
|
|
n_pre_const = n_pre + 1;
|
|
n_nums_const = n_nums = num.size();
|
|
n_ids_const = n_ids = sym.size();
|
|
nums_offset = n_pre_const + n_ids_const + 1;
|
|
n_syms = NOTEQ + n_nums_const + n_ids_const + 3;
|
|
for (j = 0; j < n_syms; j++)
|
|
flags[j] = false;
|
|
|
|
if (*bp == '_' || (*bp >= 'a' && *bp <='z') || (*bp >= 'A' && *bp <= 'Z'))
|
|
flags[nums_offset - 1] = true;
|
|
else if (*bp >= '0' && *bp <= '9')
|
|
flags[n_pre] = true;
|
|
else
|
|
flags[nums_offset - 1] = flags[n_pre] = true;
|
|
lastMatch = 0;
|
|
lastLength = 0;
|
|
}
|
|
//pre
|
|
|
|
for (j = 0; j <= NOTEQ && n_pre > 0; j++)
|
|
if (!flags[j])
|
|
{
|
|
token = preservations[j][index];
|
|
if (!token)
|
|
{
|
|
flags[j] = 2;
|
|
lastMatch = pres[j];
|
|
lastLength = index - 1;
|
|
lastTaken = true;
|
|
n_pre--;
|
|
}
|
|
else {
|
|
if (*bp != token && (*bp != (token+ 32) || token <'A' || token >'Z'))
|
|
{
|
|
flags[j] = true;
|
|
n_pre--;
|
|
}
|
|
else {
|
|
takein = true;
|
|
}
|
|
}
|
|
}
|
|
if (!flags[n_pre_const - 1])
|
|
{
|
|
//id-todo - 1
|
|
//id-hasbeen
|
|
for (i = 0; i < n_ids_const && n_ids > 0; i++)
|
|
{
|
|
if (!flags[n_pre_const + i])
|
|
{
|
|
|
|
if (sym[i]->value[index])
|
|
{
|
|
if (*bp == sym[i]->value[index])
|
|
takein = true;
|
|
else {
|
|
flags[n_pre_const + i] = true;
|
|
n_ids--;
|
|
}
|
|
}
|
|
else if (!lastTaken)
|
|
{
|
|
flags[n_pre_const + i] = 2;
|
|
lastMatch = sym[i]->id;
|
|
lastLength = index - 1;
|
|
n_ids--;
|
|
lastTaken = true;
|
|
}
|
|
}
|
|
}
|
|
if (*bp == '_' || (*bp >= 'a' && *bp <= 'z') || (*bp >= 'A' && *bp <= 'Z') || (*bp >= '0' && *bp <= '9'))
|
|
{
|
|
takein = true;
|
|
}
|
|
else if (index != 0 && !lastTaken)
|
|
{
|
|
char* tmp = new char[index];
|
|
for (j = 0; j < index; j++)
|
|
tmp[j] = (bp-index)[j];
|
|
tmp[index] = 0;
|
|
sym.push_back(new HASH (tmp,n_ids_const));
|
|
lastMatch = sym.back()->id;
|
|
lastLength = index - 1;
|
|
flags[n_pre_const - 1] = true;
|
|
}
|
|
else {
|
|
flags[n_pre_const - 1] = true;
|
|
}
|
|
}
|
|
else if (!flags[nums_offset - 1]) {
|
|
|
|
for (i = 0; i < n_nums_const && n_nums > 0; i++)
|
|
if (!flags[nums_offset + i])
|
|
{
|
|
if (num[i]->value[index])
|
|
{
|
|
if (*bp == num[i]->value[index])
|
|
takein = true;
|
|
else {
|
|
flags[nums_offset + i] = true;
|
|
n_nums --;
|
|
}
|
|
}
|
|
else if (!lastTaken)
|
|
{
|
|
flags[nums_offset + i] = 2;
|
|
lastMatch = num[i]->id;
|
|
lastLength = index - 1;
|
|
n_nums --;
|
|
lastTaken = true;
|
|
}
|
|
}
|
|
if ((*bp >= '0' && *bp <= '9'))
|
|
{
|
|
takein = true;
|
|
}
|
|
else if(index != 0 && !lastMatch){
|
|
char* tmp = new char[index];
|
|
for (j = 0; j < index; j++)
|
|
tmp[j] = (bp - index)[j];
|
|
tmp[index] = 0;
|
|
|
|
num.push_back(new HASH(tmp, n_nums_const));
|
|
lastMatch = num.back()->id;
|
|
lastLength = index - 1;
|
|
flags[n_pre + n_ids_const + 1] = true;
|
|
}
|
|
else
|
|
flags[n_pre + n_ids_const + 1] = true;
|
|
}
|
|
|
|
if (takein)
|
|
{
|
|
bp++;
|
|
index++;
|
|
}
|
|
else if (lastMatch)
|
|
{
|
|
identifiers.push_back(lastMatch);
|
|
bp -= index - lastLength - 1;
|
|
index = 0;
|
|
}
|
|
else
|
|
{
|
|
cout << "undefined identifier " << *bp << '\n';
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
if (index == 1 && *(bp - index) == '.')
|
|
identifiers.push_back(pres[DOT]);
|
|
for (IDS *var : identifiers)
|
|
cout<<var->type<<'\t'<<var->index<< '\n';
|
|
cout <<'\n' <<"Ints"<< '\n';
|
|
for (HASH *var : num)
|
|
cout << *(var->int_value) << '\n';
|
|
cout << '\n' << "Syms" << '\n';
|
|
for (HASH *var : sym)
|
|
cout << var->value << '\n';
|
|
}
|
|
|
|
|
|
struct Instruction {
|
|
int nop, lop, rop;
|
|
Instruction(int nop, int lop, int rop) {
|
|
this->nop = nop;
|
|
this->lop = lop;
|
|
this->rop = rop;
|
|
}
|
|
} *firstjump;
|
|
vector<pair<int, unsigned int>> *propos[1024];
|
|
bool checklist[1024];
|
|
bool geting_proc = false;
|
|
vector<int> INTS;
|
|
int lv = -1, dx[1024] = { 0 };
|
|
void push();
|
|
template <typename T>
|
|
class cheque : public vector<T> {
|
|
public:
|
|
void push_back(T&& _Val )
|
|
{
|
|
if (!checklist[lv])
|
|
{
|
|
if (lv)
|
|
propos[lv - 1]->back().second = this->size();
|
|
else
|
|
firstjump->rop = this->size();
|
|
checklist[lv] = true;
|
|
push();
|
|
}
|
|
printf("inserting instructions...");
|
|
vector<T>::push_back(_Val);
|
|
}
|
|
void pb(T&& _Val)
|
|
{
|
|
vector<T>::push_back(_Val);
|
|
}
|
|
};
|
|
cheque<Instruction *> instructions;
|
|
void push() {
|
|
instructions.pb(new Instruction(INT, 0, INTS.back() + 1));
|
|
INTS.pop_back();
|
|
}
|
|
inline int** init_st(int i, ...) {
|
|
int j = 0, k = 0, t;
|
|
int **p = new int*[16];
|
|
va_list arg_ptr;
|
|
va_start(arg_ptr, i);
|
|
p[0] = new int[12];
|
|
|
|
do {
|
|
t = va_arg(arg_ptr, int);
|
|
p[j][k++] = t;
|
|
if (t == -2)
|
|
{
|
|
p[++j] = new int[8];
|
|
k = 0;
|
|
}
|
|
} while (t != -1);
|
|
p[j + 1] = new int(-3);
|
|
|
|
va_end(arg_ptr);
|
|
return p;
|
|
}
|
|
|
|
inline int is_not_mod(int modifier){
|
|
return (modifier >= P(EQUAL) && modifier <= P(NOTEQ)) ? A_MOD : modifier;
|
|
}
|
|
|
|
struct Reduced{
|
|
int type;//S
|
|
void* param;
|
|
Reduced(int type, void* param){
|
|
this->type = type;
|
|
this->param = param;
|
|
}
|
|
Reduced(int type) { //P
|
|
this->type = type;
|
|
}
|
|
~Reduced() {
|
|
//free(param);
|
|
}
|
|
};
|
|
class Indexes {
|
|
public:
|
|
int i, j, k;
|
|
Indexes(int i, int j, int k){
|
|
this->i = i;
|
|
this->j = j;
|
|
this->k = k;
|
|
}
|
|
Indexes(){
|
|
i = j = k = 0;
|
|
}
|
|
bool operator<(Indexes a) const
|
|
{
|
|
if (i == a.i)
|
|
if (j == a.j)
|
|
return k < a.k;
|
|
else
|
|
return j < a.j;
|
|
else
|
|
return i < a.i;
|
|
}
|
|
};
|
|
|
|
struct Vartable {
|
|
|
|
};
|
|
stack<int> lastSP;
|
|
vector<Reduced *> buf;
|
|
vector<pair<vector<pair<int, unsigned int>>*, int>> vartable;
|
|
vector<IDS *>::iterator it;
|
|
Reduced *nextSym = 0;
|
|
stack<set<Indexes>> archive;
|
|
struct Pos {
|
|
int start, end;
|
|
};
|
|
Reduced* peekNext()
|
|
{
|
|
if (!nextSym) {
|
|
if (it != identifiers.end())
|
|
switch ((*it)->type)
|
|
{
|
|
case 0:
|
|
return new Reduced(P((*it)->index), NULL);
|
|
case 1:
|
|
return new Reduced(1, (void *)&(*it)->index);
|
|
case 2:
|
|
return new Reduced(2, (void *)num[(*it)->index]->int_value);
|
|
default:
|
|
printf("Unchecked list?");
|
|
exit(1);
|
|
}
|
|
else
|
|
return NULL;
|
|
|
|
}
|
|
else return nextSym;
|
|
}
|
|
int address = 0;
|
|
bool Next() {
|
|
if (nextSym)
|
|
{
|
|
nextSym = NULL;
|
|
return true;
|
|
}
|
|
else if (it == identifiers.end())
|
|
return false;
|
|
|
|
it++;
|
|
address++;
|
|
return true;
|
|
}
|
|
Reduced* getNext()
|
|
{
|
|
Reduced *n = peekNext();
|
|
Next();
|
|
return n;
|
|
}
|
|
|
|
inline void pop(const int &i, const int &j) {
|
|
int k = 0;
|
|
while (states[i][j][k++]>0)
|
|
buf.pop_back();
|
|
}
|
|
inline void popArchive(const int&i, const int &j) {
|
|
int k = 0;
|
|
while (states[i][j][k++] > 0)
|
|
archive.pop();
|
|
}
|
|
inline bool searchTableforVar(const int& param, int &level, int &d, bool &found, const bool con = false)
|
|
{
|
|
for (pair<vector<pair<int, unsigned int>>*, int> var : vartable)
|
|
{
|
|
if (var.second == 1 || (var.second == 0 && con))
|
|
{
|
|
for (pair<int, unsigned int> v : *(var.first))
|
|
{
|
|
if (v.first == param)
|
|
{
|
|
level /= 3;
|
|
d = v.second;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found)
|
|
return (bool)var.second;
|
|
|
|
}
|
|
level++;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
Reduced* reduce(int i, int j) {
|
|
|
|
void *param = new int(0);
|
|
switch (i)
|
|
{
|
|
case P:
|
|
{
|
|
pop(i, j);
|
|
if (!Next())
|
|
cout << "succeed" << '\n';
|
|
}
|
|
break;
|
|
case SP:
|
|
{
|
|
instructions.push_back(new Instruction(OPR, 0, 0));
|
|
lv--;
|
|
pop(i, j);
|
|
}
|
|
break;
|
|
case C:
|
|
{
|
|
lv++;
|
|
checklist[lv] = 0;
|
|
if (vartable.empty())
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 0));
|
|
else if (vartable.back().second)
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 0));
|
|
pop(i, j);
|
|
|
|
}
|
|
break;
|
|
case CDEF:
|
|
pop(i, j);
|
|
break;
|
|
case INIT:
|
|
{
|
|
if (vartable.empty())
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 0));
|
|
else
|
|
if (vartable.back().second)
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 0));
|
|
pair<vector<pair<int, unsigned int>>*, int> *top = &vartable.back();
|
|
Reduced* last = buf.back();
|
|
if (last->type != 2)
|
|
cout << "Reducing Error: Expecting a number." << '\n';
|
|
unsigned int intval = *((unsigned int *)last->param);
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
last = buf.back();
|
|
if (last->type != 1)
|
|
cout << "Reducing Error: Expecting a number." << '\n';
|
|
int index = *((int *)last->param);
|
|
top->first->push_back(pair<int, unsigned int>(index, intval));
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case V:
|
|
{
|
|
if (vartable.back().second != 1)
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 1));
|
|
if (j == 1)
|
|
{
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
Reduced *last = buf.back();
|
|
pair<vector<pair<int, unsigned int>>*, int> *top = &vartable.back();
|
|
top->first->push_back(pair<int, unsigned int>(*((int *)last->param), dx[lv]++));
|
|
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 2));
|
|
propos[lv] = vartable.back().first;
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
INTS.push_back(vartable[vartable.size() - 2].first->size() + 2);
|
|
}
|
|
break;
|
|
case VDEF:
|
|
if (j == 1)
|
|
{
|
|
buf.pop_back();
|
|
Reduced *last = buf.back();
|
|
if (vartable.empty())
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 1));
|
|
else
|
|
if (vartable.back().second != 1)
|
|
vartable.push_back(make_pair(new vector<pair<int, unsigned int>>(), 1));
|
|
pair<vector<pair<int, unsigned int>>*, int> *top = &vartable.back();
|
|
top->first->push_back(pair<int, unsigned int>(*((int *)last->param), dx[lv]++));
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case PRO:
|
|
if (j == 1)
|
|
{
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
|
|
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case ST:
|
|
switch (j)
|
|
{
|
|
case 1:
|
|
{
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
int pa = *((int *)buf.back()->param);
|
|
buf.pop_back();
|
|
bool found = false;
|
|
int level = 0, d;
|
|
searchTableforVar(pa, level, d, found);
|
|
if (!found)
|
|
cout << "Error: undefined identifier " << sym[pa]->value << '\n';
|
|
else
|
|
instructions.push_back(new Instruction(STO, level, d));
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
//JMP
|
|
int pa = *((int *)buf.back()->param);
|
|
buf.pop_back();
|
|
bool found = false;
|
|
int pos = 0;
|
|
for (pair<vector<pair<int, unsigned int>>*, int> var : vartable)
|
|
{
|
|
if (var.second == 2)
|
|
{
|
|
for (pair<int, unsigned int> v : *(var.first))
|
|
{
|
|
if (v.first == pa)
|
|
{
|
|
pos = v.second;
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
cout << "Error: undefined procedure " << sym[pa]->value << '\n';
|
|
buf.pop_back();
|
|
instructions.push_back(new Instruction(JMP, 0, pos));
|
|
}
|
|
break;
|
|
case 3:
|
|
pop(i, j);
|
|
break;
|
|
case 4:
|
|
{
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
Reduced *cond = buf.back();
|
|
instructions[((Pos *)(cond->param))->end]->rop = instructions.size();
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case 5:
|
|
{
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
Reduced *cond = buf.back();
|
|
instructions.push_back(new Instruction(JMP, 0, ((Pos *)cond->param)->start + 1));
|
|
instructions[((Pos *)(cond->param))->end]->rop = instructions.size();
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
int level = 0, d;
|
|
bool found = false;
|
|
buf.pop_back();
|
|
|
|
searchTableforVar((*(int *)buf.back()->param), level, d, found);
|
|
|
|
if (found)
|
|
{
|
|
instructions.push_back(new Instruction(SIO, 0, 2));
|
|
instructions.push_back(new Instruction(STO, level, d));
|
|
}
|
|
else
|
|
cout << "Error: Undefined parameter: " << sym[*(int*)buf.back()->param]->value << '\n';
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case 7:
|
|
{
|
|
int level = 0, d;
|
|
bool found = false;
|
|
buf.pop_back();
|
|
Reduced *id = buf.back();
|
|
if (id->type == 1)
|
|
{
|
|
searchTableforVar((*(int *)(id->param)), level, d, found);
|
|
if(found)
|
|
instructions.push_back(new Instruction(LOD, level, d));
|
|
else
|
|
cout << "Error: Undefined parameter: " << sym[*(int*)buf.back()->param]->value << '\n';
|
|
}
|
|
else if (id->type == 2)
|
|
instructions.push_back(new Instruction(LIT, 0, *((int *)id->param)));
|
|
else
|
|
cout << "Error: Undefined parameter: " << *(int*)buf.back()->param - 3 << '\n';
|
|
|
|
instructions.push_back(new Instruction(SIO, 0, 1));
|
|
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case 8:
|
|
buf.pop_back();
|
|
default:
|
|
break;
|
|
}
|
|
break;
|
|
case MORE:
|
|
pop(i, j);
|
|
break;
|
|
case COND:
|
|
{
|
|
Pos *position = new Pos();
|
|
switch (j)
|
|
{
|
|
case 0:
|
|
{
|
|
Reduced* exp = buf.back();
|
|
position->start = *((int *) exp->param);
|
|
instructions.push_back(new Instruction(OPR, 0, 6));
|
|
instructions.push_back(new Instruction(JPC, 0, -1));
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
Reduced* r;
|
|
int rop = -1;
|
|
buf.pop_back();
|
|
r = buf.back();
|
|
|
|
switch (r->type)
|
|
{
|
|
case P(GREATER):
|
|
rop = 12;
|
|
break;
|
|
case P(LESS):
|
|
rop = 10;
|
|
break;
|
|
case P(GREATEREQ):
|
|
rop = 13;
|
|
break;
|
|
case P(LESSEQ):
|
|
rop = 11;
|
|
break;
|
|
case P(NOTEQ):
|
|
rop = 9;
|
|
break;
|
|
case P(EQUAL):
|
|
rop = 8;
|
|
break;
|
|
default:
|
|
cout << "Error: Expected an condition modifier." << '\n';
|
|
break;
|
|
}
|
|
if (rop == 9)
|
|
{
|
|
instructions.push_back(new Instruction(OPR, 0, 8));
|
|
instructions.push_back(new Instruction(LIT, 0, 0));
|
|
instructions.push_back(new Instruction(OPR, 0, 8));
|
|
}
|
|
else
|
|
instructions.push_back(new Instruction(OPR, 0, rop));
|
|
|
|
instructions.push_back(new Instruction(JPC, 0, -1));
|
|
buf.pop_back();
|
|
r = buf.back();
|
|
position->start = *((int*)r->param);
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
//push
|
|
position->end = instructions.size() - 1;
|
|
param = (void *)position;
|
|
}
|
|
break;
|
|
case EXP:
|
|
{
|
|
buf.pop_back();
|
|
Pos* pos = (Pos *)buf.back()->param;
|
|
int end = pos->end, *start = new int(pos->start);
|
|
vector<Instruction *>::iterator iter = instructions.begin() + end;
|
|
buf.pop_back();
|
|
int ari2 = *((int *)buf.back()->param);
|
|
if (ari2)
|
|
(*iter)->rop = 1;
|
|
else
|
|
instructions.erase(iter);
|
|
|
|
param = start;
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case EXP2:
|
|
if(j == 1)
|
|
{
|
|
buf.pop_back();
|
|
int end = ((Pos *)buf.back()->param)->end;
|
|
buf.pop_back();
|
|
int arith = *((int *)buf.back()->param);
|
|
if (arith)
|
|
instructions[end]->rop = 3;
|
|
else
|
|
instructions[end]->rop = 2;
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case ARITH:
|
|
{
|
|
buf.pop_back();
|
|
param = new int(j);
|
|
}
|
|
break;
|
|
case ARI2:
|
|
if (j == 0)
|
|
param = new int(0);
|
|
else
|
|
{
|
|
param = new int(*((int *)buf.back()->param));
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case TERM://head
|
|
{
|
|
int end = *((int *)buf.back()->param);
|
|
buf.pop_back();
|
|
if (end == 0)
|
|
end = ((Pos *)buf.back()->param)->end;
|
|
|
|
int start = ((Pos *)buf.back()->param)->start;
|
|
instructions.erase((instructions.begin() + end));
|
|
instructions.push_back(new Instruction(OPR, 0, -2));
|
|
buf.pop_back();
|
|
end = instructions.size() - 1;
|
|
Pos *pos = new Pos();
|
|
pos->start = start;
|
|
pos->end = end;
|
|
param = pos;
|
|
}
|
|
break;
|
|
case FACTS:
|
|
if (j == 1)
|
|
{
|
|
int change = *((int*)buf.back()->param);//FACTS.end
|
|
|
|
buf.pop_back();
|
|
int end = ((Pos *)buf.back()->param)->end;//fact->end
|
|
buf.pop_back();
|
|
int muldiv = *((int *)buf.back()->param);
|
|
if (muldiv)
|
|
instructions[end]->rop = 5;
|
|
else
|
|
instructions[end]->rop = 4;
|
|
param = new int((!change) ? change : end);
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case MULDIV:
|
|
{
|
|
buf.pop_back();
|
|
param = new int (j);
|
|
}
|
|
break;
|
|
case FACT:
|
|
{
|
|
Pos* pos = new Pos();
|
|
switch (j) {
|
|
case 0:
|
|
{
|
|
int level = 0, d;
|
|
bool found = false;
|
|
pos->start = instructions.size() - 1;
|
|
bool type = searchTableforVar(*((int *)buf.back()->param), level, d, found, true);
|
|
|
|
buf.pop_back();
|
|
if (found && type)
|
|
instructions.push_back(new Instruction(LOD, level, d));
|
|
else if(found && !type)
|
|
instructions.push_back(new Instruction(LIT, 0, d));
|
|
else
|
|
cout << "Error: Unfefined identifier: " << sym[*((int *)buf.back()->param)]->value << '\n';
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
pos->start = instructions.size() - 1;
|
|
instructions.push_back(new Instruction(LIT, 0, *((int *)buf.back()->param)));
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
buf.pop_back();
|
|
Reduced *exp = buf.back();
|
|
pos->start = *((int *)exp->param);
|
|
buf.pop_back();
|
|
buf.pop_back();
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
instructions.push_back(new Instruction(OPR, 0, -1));
|
|
pos->end = instructions.size() - 1;
|
|
param = (void *)pos;
|
|
}
|
|
break;
|
|
|
|
}
|
|
return new Reduced(S(i), param);
|
|
}
|
|
|
|
|
|
void initStates() {
|
|
|
|
states = new int**[FACT + 1];
|
|
states[P] = init_st(3, S(SP), P(DOT), -1);
|
|
states[SP] = init_st(6, S(C), S(V), S(PRO), S(ST), P(SEMICOLON), -1);
|
|
states[C] = init_st(6, -2, P(CONST), S(INIT), S(CDEF), P(SEMICOLON), -1);
|
|
states[CDEF] = init_st(5, -2, P(COMMA), S(INIT), S(CDEF), -1);
|
|
states[INIT] = init_st(4, 1, P(EQUAL), 2, -1);
|
|
states[V] = init_st(6, -2, P(VAR), 1, S(VDEF), P(SEMICOLON), -1);
|
|
states[VDEF] = init_st(5, -2, P(COMMA), 1, S(VDEF), -1);
|
|
states[PRO] = init_st(7, -2, P(PROCEDURE), 1, P(SEMICOLON), S(SP), S(PRO), -1);
|
|
states[ST] = init_st(35, -2, 1, P(ASSIGNMENT), S(EXP), -2, P(CALL), 1, -2,
|
|
P(BEGIN), S(ST), S(MORE), P(END), -2, P(IF), S(COND), P(THEN), S(ST), -2,
|
|
P(WHILE), S(COND), P(DO), S(ST), -2, P(READ), P(LP), 1, P(RP), -2, P(WRITE),
|
|
P(LP), 1, P(RP), -2, P(SEMICOLON), - 1);
|
|
states[MORE] = init_st(5, -2, P(SEMICOLON), S(ST), S(MORE), -1);
|
|
states[COND] = init_st(7, P(ODD), S(EXP), -2, S(EXP), A_MOD, S(EXP), -1);
|
|
states[EXP] = init_st(4, S(ARI2), S(TERM), S(EXP2), -1);
|
|
states[EXP2] = init_st(5, -2, S(ARITH), S(TERM), S(EXP2), -1);
|
|
states[ARITH] = init_st(4, P(PLUS), -2, P(MINUS), -1);
|
|
states[ARI2] = init_st(3, -2, S(ARITH), - 1);
|
|
states[TERM] = init_st(3, S(FACT), S(FACTS), -1);
|
|
states[FACTS] = init_st(5, -2, S(MULDIV), S(FACT), S(FACTS), -1);
|
|
states[MULDIV] = init_st(4, P(MULTIPLE), -2, P(DIVISION), -1);
|
|
states[FACT] = init_st(8, 1, -2, 2, -2, P(LP), S(EXP), P(RP), -1);
|
|
|
|
follows = new int*[FACT + 1];
|
|
follows[P] = init_follow(1, -1);
|
|
follows[SP] = init_follow(11, P(DOT), P(END), P(SEMICOLON), P(BEGIN), P(CALL), P(IF), P(WHILE), P(READ), P(WRITE), 1, P(PROCEDURE));
|
|
follows[C] = init_follow(11, P(VAR), P(END), P(SEMICOLON), P(BEGIN), P(CALL), P(IF), P(WHILE), P(READ), P(WRITE), 1, P(PROCEDURE));
|
|
follows[CDEF] = init_follow(1, P(SEMICOLON));
|
|
follows[INIT] = init_follow(2, P(SEMICOLON), P(COMMA));
|
|
follows[V] = init_follow(10, P(SEMICOLON), P(PROCEDURE), P(END), P(BEGIN), P(CALL), P(IF), P(WHILE), P(READ), P(WRITE), 1);
|
|
follows[VDEF] = init_follow(1, P(SEMICOLON));
|
|
follows[PRO] = init_follow(9, P(END), P(SEMICOLON), P(BEGIN), P(CALL), P(IF), P(WHILE), P(READ), P(WRITE), 1);
|
|
follows[ST] = init_follow(2, P(END), P(SEMICOLON));
|
|
follows[MORE] = init_follow(1, P(END));
|
|
follows[COND] = init_follow(2, P(THEN), P(DO));
|
|
follows[EXP] = init_follow(6, A_MOD, P(THEN), P(DO), P(RP), P(END), P(SEMICOLON));
|
|
follows[EXP2] = init_follow(6, A_MOD, P(THEN), P(DO), P(RP), P(END), P(SEMICOLON));
|
|
follows[ARITH] = init_follow(3, 1, 2, P(LP));
|
|
follows[ARI2] = init_follow(3, 1, 2, P(LP));
|
|
follows[TERM] = init_follow(8, P(PLUS), P(MINUS), A_MOD, P(THEN), P(DO), P(RP), P(END), P(SEMICOLON));
|
|
follows[FACTS] = init_follow(8, P(PLUS), P(MINUS), A_MOD, P(THEN), P(DO), P(RP), P(END), P(SEMICOLON));
|
|
follows[MULDIV] = init_follow(3, 1, 2, P(LP));
|
|
follows[FACT] = init_follow(10, P(MULTIPLE), P(DIVISION), P(PLUS), P(MINUS), A_MOD, P(THEN), P(DO), P(END), P(SEMICOLON), P(RP));
|
|
|
|
|
|
instructions.pb(new Instruction(JMP, 0, -1));
|
|
firstjump = instructions[0];
|
|
checklist[0] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void expend(set<Indexes> &togo) {
|
|
|
|
int size0, j;
|
|
do {
|
|
size0 = togo.size();
|
|
for (Indexes var : togo)
|
|
{
|
|
j = states[var.i][var.j][var.k];
|
|
int i;
|
|
if (_S(j))
|
|
for (i = 0; i < 16; i++) {
|
|
if (states[DeS(j)][i][0] == -3)
|
|
break;
|
|
else
|
|
togo.insert(Indexes(DeS(j), i, 0));
|
|
}
|
|
}
|
|
} while (size0 != togo.size());
|
|
|
|
}
|
|
|
|
void Shift(set<Indexes> togo) {
|
|
if (lv == 0)
|
|
int null = 1;
|
|
|
|
//shifting
|
|
Reduced* nextsym = peekNext();
|
|
set<Indexes> tobeReduced;
|
|
int nexttype = is_not_mod(nextsym->type), t;
|
|
archive.push(togo);
|
|
set<Indexes>::pointer pt;
|
|
set<Indexes>::iterator var = togo.begin();
|
|
while(var != togo.end()){
|
|
t = states[var->i][var->j][var->k];
|
|
if (t < 0)
|
|
{
|
|
tobeReduced.insert(Indexes(var->i, var->j, 0));
|
|
var = togo.erase(var);
|
|
if (togo.empty())
|
|
break;
|
|
}
|
|
else if (t != nexttype)
|
|
{
|
|
var = togo.erase(var);
|
|
if (togo.empty())
|
|
break;
|
|
}
|
|
else
|
|
var++;
|
|
}
|
|
//reducing
|
|
int FOL;
|
|
bool match;
|
|
int j;
|
|
var = tobeReduced.begin();
|
|
//reduce conflict.
|
|
while (var != tobeReduced.end())
|
|
{
|
|
j = 0;
|
|
match = false;
|
|
FOL = follows[var->i][j++];
|
|
while (FOL > 0)
|
|
if (is_not_mod(nextsym->type) == FOL)
|
|
{
|
|
match = true;
|
|
break;
|
|
}
|
|
else
|
|
FOL = follows[var->i][j++];
|
|
|
|
if (!match)
|
|
var = tobeReduced.erase(var);
|
|
else
|
|
var++;
|
|
|
|
if (tobeReduced.empty())
|
|
break;
|
|
|
|
}
|
|
if (tobeReduced.size() > 0)
|
|
{
|
|
int i = tobeReduced.begin()->i, k = 0;
|
|
j = tobeReduced.begin()->j;
|
|
nextSym = reduce(i, j);
|
|
|
|
while (states[i][j][k++] > 0)
|
|
archive.pop();
|
|
set<Indexes> togoNext = archive.top();
|
|
archive.pop();
|
|
Shift(togoNext);
|
|
return;
|
|
}
|
|
else if (Next())
|
|
{
|
|
if (!togo.empty())
|
|
{
|
|
set<Indexes> togoNext;
|
|
for (Indexes var : togo){
|
|
var.k++;
|
|
togoNext.insert(var);
|
|
}
|
|
togo.clear();
|
|
|
|
expend(togoNext);
|
|
buf.push_back(nextsym);
|
|
if (nexttype == P(PROCEDURE) && !geting_proc)
|
|
geting_proc = true;
|
|
else if (geting_proc && nexttype == 1)
|
|
{
|
|
propos[lv]->push_back(pair<int, unsigned int>(*((int *)nextsym->param), numeric_limits<int>::max()));
|
|
checklist[lv] = false;
|
|
geting_proc = false;
|
|
}
|
|
|
|
Shift(togoNext);
|
|
}
|
|
}
|
|
}
|
|
|
|
void BLOCK() {
|
|
initStates();
|
|
it = identifiers.begin();
|
|
set<Indexes> going;
|
|
going.insert(Indexes(P, 0, 0));
|
|
|
|
//
|
|
expend(going);
|
|
Shift(going);
|
|
|
|
|
|
vartable.clear();
|
|
cout << address <<Next() << '\n';
|
|
}
|
|
|
|
vector<void **> *memory;
|
|
vector<int> *t;
|
|
|
|
int PC, I;
|
|
void* b;
|
|
#define getij() _getij(i, j)
|
|
#define geti _geti(i)
|
|
inline void _getij(int &i, int &j) {
|
|
j = t->back();
|
|
t->pop_back();
|
|
i = t->back();
|
|
t->pop_back();
|
|
}
|
|
inline void _geti(int &i) {
|
|
i = t->back();
|
|
t->pop_back();
|
|
}
|
|
void PARSE() {
|
|
|
|
int inst = 0;
|
|
for (auto var : instructions)
|
|
cout << inst++ << " " << operations[var->nop] << " " << var->lop << " " << var->rop << '\n';
|
|
|
|
I = 0;
|
|
PC = -1;
|
|
int i, j;
|
|
memory = new vector<void **>;
|
|
while (I < instructions.size())
|
|
{
|
|
|
|
// cout << "\n inst "<< I << '\n';
|
|
switch (instructions[I] ->nop)
|
|
{
|
|
case INT:
|
|
{
|
|
b = new void*[instructions[I]->rop];
|
|
memory->push_back((void **)b);
|
|
|
|
t = new vector<int>;
|
|
((void **)b)[0] = t;
|
|
((void **)b)[1] = b;
|
|
((void **)b)[2] = new int(PC);
|
|
}
|
|
break;
|
|
case OPR:
|
|
switch (instructions[I]->rop)
|
|
{
|
|
case 0:
|
|
{
|
|
if ((*(int *)(((void**)b)[2])) > 0)
|
|
I = (*(int *)(((void**)b)[2]));
|
|
else
|
|
return;
|
|
|
|
delete (vector< int> *)((void **)b)[0];
|
|
delete[] ((void**)b);
|
|
memory->pop_back();
|
|
t = (vector< int > *)(memory->back()[0]);
|
|
b = memory->back()[1];
|
|
continue;
|
|
}
|
|
break;
|
|
case 1:
|
|
{
|
|
geti;
|
|
t->push_back(-i);
|
|
}
|
|
break;
|
|
case 2:
|
|
{
|
|
getij();
|
|
t->push_back(i + j);
|
|
}
|
|
break;
|
|
case 3:
|
|
{
|
|
getij();
|
|
t->push_back(i - j);
|
|
}
|
|
break;
|
|
case 4:
|
|
{
|
|
getij();
|
|
t->push_back(i * j);
|
|
}
|
|
break;
|
|
case 5:
|
|
{
|
|
getij();
|
|
if (j == 0)
|
|
{
|
|
cout << "Error: Division by zero" << '\n';
|
|
exit(1);
|
|
}
|
|
t->push_back(i / j);
|
|
}
|
|
break;
|
|
case 6:
|
|
{
|
|
geti;
|
|
t->push_back((i % 2) != 0);
|
|
}
|
|
break;
|
|
case 8:
|
|
{
|
|
getij();
|
|
t->push_back(i == j);
|
|
}
|
|
break;
|
|
case 9:
|
|
{
|
|
getij();
|
|
t->push_back(i != j);
|
|
}
|
|
break;
|
|
case 10:
|
|
{
|
|
getij();
|
|
t->push_back(i < j);
|
|
}
|
|
break;
|
|
case 11:
|
|
{
|
|
getij();
|
|
t->push_back(i <= j);
|
|
}
|
|
break;
|
|
case 12:
|
|
{
|
|
getij();
|
|
t->push_back(i > j);
|
|
}
|
|
break;
|
|
case 13:
|
|
{
|
|
getij();
|
|
t->push_back(i >= j);
|
|
}
|
|
|
|
break;
|
|
}
|
|
break;
|
|
case SIO:
|
|
if (instructions[I]->rop == 2) {
|
|
cin >> i;
|
|
t->push_back(i);
|
|
}
|
|
else {
|
|
i = t->back();
|
|
t->pop_back();
|
|
cout << i <<'\n';
|
|
|
|
}
|
|
break;
|
|
case LOD:
|
|
{
|
|
i = *(int *)(*memory)[instructions[I]->lop][instructions[I]->rop + 3];
|
|
t->push_back(i);
|
|
}
|
|
break;
|
|
case LIT:
|
|
t->push_back(instructions[I]->rop);
|
|
break;
|
|
case JMP:
|
|
I = instructions[I]->rop;
|
|
continue;
|
|
break;
|
|
case JPC:
|
|
{
|
|
geti;
|
|
if (!i)
|
|
{
|
|
I = instructions[I]->rop;
|
|
continue;
|
|
}
|
|
} break;
|
|
case STO:
|
|
{
|
|
geti;
|
|
(*memory)[instructions[I]->lop][instructions[I]->rop + 3] = new int(i);
|
|
}
|
|
break;
|
|
case CAL:
|
|
I = instructions[I]->rop;
|
|
break;
|
|
default:
|
|
cout << "Undefined Instruction: \n" << operations[instructions[I]->nop] << " " << instructions[I]->lop << " " << instructions[I]->rop << '\n';
|
|
break;
|
|
}
|
|
I++;
|
|
PC = I + 1;
|
|
}
|
|
delete memory;
|
|
}
|
|
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
|
|
long length;
|
|
char* file = 0;
|
|
FILE *fp = NULL;
|
|
if (argc > 1)
|
|
fp = fopen(argv[1], "r");
|
|
else
|
|
fp = fopen("input.pas", "r");
|
|
|
|
if (!fp)
|
|
file = new char[65536];
|
|
loop_input: while (!fp) {
|
|
cout << "Input the path of input file."<<'\n';
|
|
scanf("%s", file);
|
|
fp = fopen(file, "r");
|
|
}
|
|
fseek(fp, 0, SEEK_END);
|
|
length = ftell(fp);
|
|
if (length > MAX_BUFFER)
|
|
{
|
|
cout << "Cannot handle now:)" << '\n';
|
|
fclose(fp);
|
|
fp = NULL;
|
|
goto loop_input;
|
|
}
|
|
fseek(fp, 0, SEEK_SET);
|
|
fread(buffer, 1, length, fp);
|
|
fclose(fp);
|
|
|
|
buffer[length] = ' ';
|
|
buffer[length] = 0;
|
|
sym.reserve(512);
|
|
num.reserve(512);
|
|
|
|
//coping
|
|
GETSYM();
|
|
//PARSING
|
|
BLOCK();
|
|
//Interprating
|
|
PARSE();
|
|
|
|
cout << "\n\nProgram ended.\n";
|
|
if(file)
|
|
delete[] file;
|
|
return 0;
|
|
}
|
|
|