Last active
August 29, 2015 14:18
-
-
Save maekawatoshiki/1f6aa02b8e29310fb3ec to your computer and use it in GitHub Desktop.
Interpreter "CON"
This file contains hidden or 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
/* | |
Interpreter "CON" | |
Using: | |
fizzbuzz.a : | |
i = 0 | |
:loop | |
if i < 40 | |
if i % 15 == 0 | |
print "FizzBuzz" | |
else | |
if i % 3 == 0 | |
print "Fizz" | |
else | |
if i % 5 == 0 | |
print "Buzz" | |
else | |
print i | |
end | |
print "\n" | |
i = i + 1 | |
goto :loop | |
end | |
Command Line: | |
$ g++ Main.cpp | |
$ ./a.out fizzbuzz.a | |
Copyright(C) 2015 MAEKAWA TOSHIKI. | |
*/ | |
// Main.cpp | |
// C++ Libaries | |
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <stack> | |
#include <vector> | |
#include <sstream> | |
#include <iomanip> | |
#include <map> | |
// C Libaries | |
#include <cstdio> | |
#include <cstdlib> | |
#include <cstring> | |
#include <cmath> | |
using namespace std; | |
#define ASSIG 100 | |
#define SAME 200 | |
#define DIFFER 201 | |
#define BIGLEFT 202 | |
#define BIGRIGHT 203 | |
#define SAME_BIGLEFT 204 | |
#define SAME_BIGRIGHT 205 | |
#define IF_TRUE 1 | |
#define IF_FALSE 0 | |
class Calculator | |
{ | |
private: | |
vector<string> array; | |
vector<string> ans; | |
public: | |
char *str; | |
string Strexpr; | |
double answer; | |
int expression(); | |
int fac(); | |
int term(); | |
int toRpn(); | |
double calc(); | |
Calculator(); | |
~Calculator(); | |
}; | |
Calculator::Calculator() | |
{ | |
str = new char[0xFFFF](); | |
} | |
Calculator::~Calculator() | |
{ | |
delete[] str; | |
} | |
int Calculator::fac() | |
{ | |
if (array.back() == "(") | |
{ | |
if (array.size() >= 2) array.pop_back(); | |
expression(); | |
if (array.back() == ")") | |
if (array.size() >= 2) | |
array.pop_back(); | |
} | |
else { | |
ans.push_back(array.back()); | |
if (array.size() >= 2) | |
array.pop_back(); | |
} | |
return 0; | |
} | |
int Calculator::term() | |
{ | |
fac(); | |
while (1) | |
{ | |
string c = array.back(); | |
if ( (c == "*" || c == "/") && array.size() >= 1) | |
{ | |
array.pop_back(); | |
fac(); | |
ans.push_back(c); | |
} | |
else | |
break; | |
} | |
return 0; | |
} | |
int Calculator::expression() | |
{ | |
term(); | |
while (1) | |
{ | |
string c = array.back(); | |
if ((c == "+" || c == "-" || c == "%") && array.size()) | |
{ | |
array.pop_back(); | |
term(); | |
ans.push_back(c); | |
} | |
else | |
break; | |
} | |
return 0; | |
} | |
int Calculator::toRpn() | |
{ | |
string olds = ""; | |
bool nm = false; | |
vector<string> siki2; | |
for (int i = 0; i < Strexpr.length(); i++) | |
{ | |
switch (Strexpr[i]) | |
{ | |
case '+': | |
case '-': | |
case '*': | |
case '/': | |
case '%': | |
case '(': | |
case ')': | |
if (nm == true) | |
{ | |
siki2.push_back(olds); | |
olds = ""; | |
nm = false; | |
} | |
olds = Strexpr[i]; | |
siki2.push_back(olds); | |
olds = ""; | |
break; | |
default: | |
olds += Strexpr[i]; | |
nm = true; | |
} | |
} | |
if (nm == true) siki2.push_back(olds); | |
// vector の順番を反対にします。 | |
for (int i = 0; siki2.empty() != true; i++) | |
{ | |
array.push_back(siki2.back()); | |
siki2.pop_back(); | |
} | |
expression(); | |
return 0; | |
} | |
double Calculator::calc() | |
{ | |
double num = 0, num2 = 0; | |
int i = 0, pos = 0; | |
stack<double> arr; | |
string s; char c; | |
Strexpr = str; | |
memset(str, 0, 0xFFFF); | |
toRpn(); | |
while (i < ans.size()) | |
{ | |
switch (ans[i][0]) | |
{ | |
case '+': | |
num = arr.top(); arr.pop(); | |
num2 = arr.top(); arr.pop(); | |
arr.push(num2 + num); | |
break; | |
case '-': | |
num = arr.top(); arr.pop(); | |
num2 = arr.top(); arr.pop(); | |
arr.push(num2 - num); | |
break; | |
case '%': | |
num = arr.top(); arr.pop(); | |
num2 = arr.top(); arr.pop(); | |
arr.push( (int) fmod(num2, num) ); | |
break; | |
case '*': | |
num = arr.top(); arr.pop(); | |
num2 = arr.top(); arr.pop(); | |
arr.push(num2 * num); | |
break; | |
case '/': | |
num = arr.top(); arr.pop(); | |
num2 = arr.top(); arr.pop(); | |
arr.push(num2 / num); | |
break; | |
default: | |
arr.push( atof( ans[i].c_str() ) ); | |
} | |
i++; pos++; | |
} | |
return answer = arr.top(); | |
} | |
char *checkFunc(int pos, char *code, char *funcNameBuf) | |
{ | |
int i; | |
const char functions[2][8] = { | |
"print", | |
"input" | |
}; | |
for(i=0; i < 2; i++) | |
{ | |
if( strncmp(&code[pos], functions[i], strlen( functions[i] )) == 0) | |
{ | |
strcpy(funcNameBuf, functions[i]); | |
return funcNameBuf; | |
} | |
} | |
return NULL; | |
} | |
char *checkString(int pos, char *code, char *stringBuf) | |
{ | |
int i; | |
memset(stringBuf, 0, 0xFF); | |
for(i = pos; ; i++) | |
{ | |
switch(code[i]) | |
{ | |
case '\"': | |
sprintf( stringBuf, "%s%c", stringBuf, code[i]); | |
return stringBuf; | |
} | |
sprintf( stringBuf, "%s%c", stringBuf, code[i]); | |
} | |
return NULL; | |
} | |
char *checkWord(int pos, char *code, char *WordNameBuf) | |
{ | |
int i; | |
const char words[11][8] = { | |
"if", | |
"for", | |
"else", | |
"==", | |
"!=", | |
"<=", | |
">=", | |
"<", | |
">", | |
"end", | |
"goto" | |
}; | |
for(i=0; i < 11; i++) | |
{ | |
if( strncmp(&code[pos], words[i], strlen( words[i] )) == 0) | |
{ | |
strcpy(WordNameBuf, words[i]); | |
return WordNameBuf; | |
} | |
} | |
return NULL; | |
} | |
char *checkVar(int pos, char *code, char *varNameBuf) | |
{ | |
int i; | |
memset(varNameBuf, 0, 0xFF); | |
for(i = pos; ; i++) | |
{ | |
switch(code[i]) | |
{ | |
case ';': | |
case '(': | |
case ')': | |
case '=': | |
case '+': | |
case '-': | |
case '*': | |
case '/': | |
case '%': | |
case '<': | |
case '>': | |
case '!': | |
case '\0': | |
case '\n': | |
case ' ': | |
case ':': | |
case '\t': | |
case '\"': | |
return varNameBuf; | |
} | |
sprintf( varNameBuf, "%s%c", varNameBuf, code[i]); | |
} | |
return NULL; | |
} | |
char *checkNumber(int pos, char *code, char *numberBuf) | |
{ | |
int i; | |
memset(numberBuf, 0, 0xFF); | |
for(i = pos; ; i++) | |
{ | |
switch(code[i]) | |
{ | |
case '0': | |
case '1': | |
case '2': | |
case '3': | |
case '4': | |
case '5': | |
case '6': | |
case '7': | |
case '8': | |
case '9': | |
case '.': | |
sprintf( numberBuf, "%s%c", numberBuf, code[i]); | |
break; | |
default: | |
return numberBuf; | |
} | |
} | |
return NULL; | |
} | |
string Token(string code) | |
{ | |
string output; | |
char funcname[0xFF] = { 0 }, | |
varname[0xFF] = { 0 }, | |
wordname[0xFF] = { 0 }, | |
labelname[0xFF] = { 0 }, | |
stringname[0xFF] = { 0 }, | |
number[0xFF] = { 0 }; | |
int nowpos, startToken = 0; | |
bool nameFlag = false, intFlag = false; | |
for(nowpos=0; nowpos<code.size(); nowpos++) | |
{ | |
switch(code[nowpos]) | |
{ | |
case ';': | |
case '\n': | |
case '(': | |
case ')': | |
case '=': | |
case '+': | |
case '-': | |
case '*': | |
case '/': | |
case '%': | |
case '<': | |
case '>': | |
case '!': | |
case ',': | |
if( checkWord(nowpos, (char *)code.c_str(), wordname) != NULL ) | |
{ | |
output += "W"; | |
output += wordname; | |
output += " "; | |
nowpos += strlen(wordname)-1; | |
} | |
else | |
output += "S" + code.substr(nowpos, 1) + " "; | |
break; | |
case '0': | |
case '1': | |
case '2': | |
case '3': | |
case '4': | |
case '5': | |
case '6': | |
case '7': | |
case '8': | |
case '9': | |
case '.': | |
output += "I"; | |
checkNumber(nowpos, (char *)code.c_str(), number); | |
output += number; | |
output += " "; | |
nowpos += strlen(number)-1; | |
break; | |
case ' ': | |
case '\t': | |
break; | |
case ':': | |
nowpos++; | |
if( checkVar(nowpos, (char *)code.c_str(), labelname) != NULL ) | |
{ | |
output += "L"; | |
output += labelname; | |
output += " "; | |
nowpos += strlen(labelname) - 1; | |
} | |
break; | |
case '\"': | |
nowpos++; | |
checkString(nowpos, (char *)code.c_str(), stringname); | |
output += "\""; | |
output += stringname; | |
output += " "; | |
nowpos += strlen(stringname) - 1; | |
break; | |
default: | |
if( checkWord(nowpos, (char *)code.c_str(), wordname) != NULL ) | |
{ | |
output += "W"; | |
output += wordname; | |
output += " "; | |
nowpos += strlen(wordname) - 1; | |
} | |
else | |
if( checkFunc(nowpos, (char *)code.c_str(), funcname) != NULL ) | |
{ | |
output += "F"; | |
output += funcname; | |
output += " "; | |
nowpos += strlen(funcname) - 1; | |
} | |
else if(checkVar(nowpos, (char *)code.c_str(), varname) != NULL) | |
{ | |
output += "V"; | |
output += varname; | |
output += " "; | |
nowpos += strlen(varname) - 1; | |
} | |
} | |
} | |
return output; | |
} | |
void setLabel( map<string, int> &label, char *code) | |
{ | |
int pos; | |
size_t codeSz = strlen(code); | |
char labelname[0xFF] = { 0 }; | |
for( pos = 0; pos < codeSz; pos++ ) | |
{ | |
if(code[pos] == 'L' && code[pos-6] != 'W') | |
{ | |
checkVar(pos+1, code, labelname); | |
label[labelname] = pos-2; | |
} | |
} | |
} | |
char *replace(char *str) | |
{ | |
char *pos; | |
char escape[6][3] = { | |
"\\n","\n", | |
"\\t","\t", | |
"\\b","\b" | |
}; | |
int i; | |
for(i = 0; i < 6; i += 2) | |
{ | |
while( (pos = strstr( str, escape[i] )) != NULL) | |
{ | |
pos[0] = escape[i+1][0]; | |
memmove(pos + 1, pos + 2, | |
strlen(str) - 2 + 1); | |
} | |
} | |
return str; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
if(argc < 2) return -1; | |
map<string, double> var; | |
map<string, int> label; | |
stack<int> fors, forEnds; | |
ifstream Source(argv[1]); | |
Calculator calc; | |
string code((istreambuf_iterator<char>(Source)), istreambuf_iterator<char>()); | |
string objcode; | |
char funcname[0xFF] = { 0 }, | |
varname[0xFF] = { 0 }, | |
number[0xFF] = { 0 }, | |
wordname[0xFF] = { 0 }, | |
stringname[0xFF] = { 0 }, | |
labelname[0xFF] = { 0 }, | |
assigVarName[0xFF] = { 0 }; | |
int nowpos; | |
bool assigFlag = false; | |
bool useIf = false, useFor = false, useGoto = false, useElse = false; | |
int ifCmp = 0, forNumber = 0, forNumber2 = 0; | |
double printDouble = 0, ifLeft = 0, ifRight = 0; | |
size_t objcode_size; | |
char *objcode_c; | |
{// パース後のコードを Char にセット | |
objcode = Token(code); | |
objcode_size = objcode.size(); | |
objcode_c = new char[objcode_size+2](); | |
strcpy(objcode_c, objcode.c_str()); | |
} | |
cout << "After Parse:" << endl << objcode_c << endl << endl; | |
cout << "Output:" << endl; | |
setLabel(label, objcode_c); | |
for( nowpos = 0; nowpos < objcode_size; nowpos++ ) | |
{ | |
switch(objcode_c[nowpos]) | |
{ | |
case '\"': nowpos++; | |
checkString(nowpos, objcode_c, calc.str); | |
nowpos += strlen(calc.str); | |
break; | |
case 'V': nowpos++; | |
checkVar(nowpos, (char *)objcode_c, varname); | |
sprintf(calc.str, "%s%.20lf", calc.str, var[varname]); | |
nowpos++; | |
break; | |
case 'W': nowpos++; | |
checkWord(nowpos, (char *)objcode_c, wordname); | |
nowpos++; | |
if(strcmp(wordname, "if") == 0) | |
useIf = true; | |
else if(strcmp(wordname, "goto") == 0) | |
useGoto = true; | |
else if(strcmp(wordname, "else") == 0) | |
{ | |
if( ifCmp == IF_TRUE ) | |
{ | |
int ifCount = 1; | |
while(nowpos < objcode_size && ifCount > 0) | |
{ | |
nowpos++; | |
if(objcode_c[nowpos] == 'W' ) | |
{ | |
checkWord(nowpos+1, objcode_c, wordname); | |
if(strcmp(wordname, "if") == 0) | |
ifCount++; | |
if(strcmp(wordname, "end") == 0) | |
ifCount--; | |
if(strcmp(wordname, "else") == 0) | |
ifCount--; | |
} | |
} | |
} | |
} | |
else if(strcmp(wordname, "end") == 0) | |
useElse = useIf = false; | |
else if( strcmp(wordname, "==") == 0 ) | |
{ | |
ifLeft = calc.calc(); | |
ifCmp = SAME; | |
} | |
else if(strcmp(wordname, "!=" ) == 0 ) { | |
ifLeft = calc.calc(); | |
ifCmp = DIFFER; | |
} | |
else if(strcmp(wordname, "<") == 0 ) { | |
ifLeft = calc.calc(); | |
ifCmp = BIGRIGHT; | |
} | |
else if(strcmp(wordname, ">") == 0 ) { | |
ifLeft = calc.calc(); | |
ifCmp = BIGLEFT; | |
} | |
else if(strcmp(wordname, ">=") == 0 ) { | |
ifLeft = calc.calc(); | |
ifCmp = SAME_BIGLEFT; | |
} | |
else if(strcmp(wordname, "<=") == 0 ) { | |
ifLeft = calc.calc(); | |
ifCmp = SAME_BIGRIGHT; | |
} | |
break; | |
case 'L': nowpos++; | |
checkVar(nowpos, (char *)objcode_c, labelname); | |
break; | |
case 'S': nowpos++; | |
switch(objcode_c[nowpos]) | |
{ | |
case '+': | |
case '-': | |
case '*': | |
case '/': | |
case '%': | |
case '(': | |
case ')': | |
sprintf(calc.str, "%s%c", calc.str, objcode_c[nowpos]); | |
break; | |
case '=': | |
assigFlag = true; | |
strcpy(assigVarName, varname); | |
memset(calc.str, 0, strlen(calc.str)); | |
break; | |
case ',': | |
break; | |
case '\n': | |
case ';': | |
if(assigFlag == true) | |
{ | |
var[assigVarName] = calc.calc(); | |
assigFlag = false; | |
} | |
if( useGoto ) | |
{ | |
nowpos = label[labelname]; | |
useIf = useGoto = false; | |
memset(calc.str, 0, 0xFFFF); | |
} | |
if( useIf ) | |
{ | |
ifRight = calc.calc(); | |
switch(ifCmp) | |
{ | |
case SAME: | |
if(ifRight == ifLeft) | |
ifCmp = IF_TRUE; | |
else ifCmp = IF_FALSE; | |
break; | |
case DIFFER: | |
if(ifRight != ifLeft) | |
ifCmp = IF_TRUE; | |
else ifCmp = IF_FALSE; | |
break; | |
case BIGLEFT: | |
if(ifLeft > ifRight) | |
ifCmp = IF_TRUE; | |
else ifCmp = IF_FALSE; | |
break; | |
case BIGRIGHT: | |
if(ifLeft < ifRight) | |
ifCmp = IF_TRUE; | |
else ifCmp = IF_FALSE; | |
break; | |
case SAME_BIGLEFT: | |
if(ifLeft >= ifRight) | |
ifCmp = IF_TRUE; | |
else ifCmp = IF_FALSE; | |
break; | |
case SAME_BIGRIGHT: | |
if(ifLeft <= ifRight) | |
ifCmp = IF_TRUE; | |
else ifCmp = IF_FALSE; | |
break; | |
} | |
if( ifCmp == IF_FALSE ) | |
{ | |
int ifCount = 1; | |
useElse = false; | |
while(nowpos < objcode_size && ifCount > 0) | |
{ | |
nowpos++; | |
if(objcode_c[nowpos] == 'W' ) | |
{ | |
checkWord(nowpos+1, objcode_c, wordname); | |
if(strcmp(wordname, "if") == 0) | |
ifCount++; | |
if(strcmp(wordname, "end") == 0) | |
{ | |
if( useElse ) { ifCount++; useElse = false; } | |
ifCount--; | |
} | |
if(strcmp(wordname, "else") == 0) | |
{ | |
useElse = true; | |
ifCount--; | |
} | |
} | |
} | |
nowpos += 6; | |
} | |
useIf = false; | |
memset(calc.str, 0, 0xFFFF); | |
}// IF | |
if(funcname != NULL) | |
{ | |
if(strcmp(funcname, "print") == 0) | |
{ | |
if( | |
( calc.str[0] >= 48 && | |
calc.str[0] <= 59 ) || | |
( calc.str[0] >= 40 && | |
calc.str[0] <= 43 ) || | |
calc.str[0] == 45 || | |
calc.str[0] == 47 | |
) | |
{ | |
printDouble = calc.calc(); | |
cout << setprecision(16) << printDouble; | |
} | |
else | |
{ | |
replace(calc.str); | |
calc.str[strlen(calc.str)-1] = 0; | |
cout << calc.str; | |
} | |
} | |
else if( strcmp(funcname, "input") == 0) | |
{ | |
cin >> var[varname]; | |
} | |
memset(funcname, 0, sizeof(funcname)); | |
memset(calc.str, 0, 0xFFFF); | |
} | |
break; | |
} | |
break; | |
case 'F': nowpos++; | |
checkFunc(nowpos, (char *)objcode_c, funcname); | |
nowpos++; | |
break; | |
case 'I': nowpos++; | |
checkNumber(nowpos, (char *)objcode_c, number); | |
sprintf(calc.str, "%s%.20lf", calc.str, atof(number)); | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment