2012-12-10 10:45:09 +00:00
|
|
|
#include <fstream>
|
2012-11-02 23:07:00 +00:00
|
|
|
#include <iostream>
|
2012-12-10 10:45:09 +00:00
|
|
|
#include <string>
|
|
|
|
#include <math.h>
|
2012-11-02 23:07:00 +00:00
|
|
|
#include "Token.h"
|
|
|
|
#include "Lexer.h"
|
|
|
|
#include "Parser.h"
|
2012-11-04 12:18:26 +00:00
|
|
|
#include "Tests/TestLexer.h"
|
2012-12-08 19:59:05 +00:00
|
|
|
#include "Context.h"
|
2012-12-22 08:07:13 +00:00
|
|
|
#include "ASTInspector.h"
|
2012-12-22 11:20:23 +00:00
|
|
|
#include "Tests/tests.h"
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2012-11-02 23:07:00 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2012-12-17 08:25:58 +00:00
|
|
|
|
|
|
|
/*TODO
|
|
|
|
* Known bugs:
|
|
|
|
*
|
|
|
|
* >> print("I like bananas", dupa");
|
|
|
|
I like bananasnull
|
|
|
|
Context: 0: dupa"); type: null
|
|
|
|
null
|
|
|
|
|
2012-12-17 09:41:48 +00:00
|
|
|
dupa"); declaration? hello? It's probably temporary effect of searching for this name in variable tables
|
|
|
|
|
|
|
|
>>
|
2012-12-17 08:25:58 +00:00
|
|
|
*/
|
|
|
|
|
2012-12-22 11:20:23 +00:00
|
|
|
|
|
|
|
SenchaObject sleep(vector<ASTExpression *> arguments)
|
|
|
|
{
|
|
|
|
SenchaObject argument = arguments[0]->evaluate();
|
|
|
|
if(argument.type == SenchaObject::integer_number && argument.integer >= 0)
|
|
|
|
{
|
|
|
|
cout << "valid argument for sleep: " << argument.integer << endl;
|
|
|
|
usleep(1000 * argument.integer);
|
|
|
|
return SenchaObject();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
cout << "invalid argument for sleep";
|
|
|
|
argument.type = SenchaObject::invalid;
|
|
|
|
return argument;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2012-12-10 10:45:09 +00:00
|
|
|
SenchaObject print(vector<ASTExpression *> arguments)
|
|
|
|
{
|
|
|
|
for (auto argument: arguments)
|
|
|
|
{
|
|
|
|
auto value = argument->evaluate();
|
|
|
|
|
|
|
|
std::cout << value.str();
|
|
|
|
|
|
|
|
}
|
|
|
|
std::cout << std::endl;
|
|
|
|
return SenchaObject();
|
|
|
|
}
|
|
|
|
|
|
|
|
SenchaObject s_sin(vector<ASTExpression *> arguments)
|
|
|
|
{
|
|
|
|
SenchaObject result;
|
|
|
|
SenchaObject sin_argument = arguments[0]->evaluate();
|
|
|
|
if(sin_argument.type == SenchaObject::integer_number)
|
|
|
|
{
|
|
|
|
result = SenchaObject(sin(sin_argument.integer));
|
|
|
|
}
|
|
|
|
else if(sin_argument.type == SenchaObject::float_number)
|
|
|
|
{
|
|
|
|
result = SenchaObject(sin(sin_argument.number));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.type = SenchaObject::invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SenchaObject s_cos(vector<ASTExpression *> arguments)
|
|
|
|
{
|
|
|
|
SenchaObject result;
|
|
|
|
SenchaObject cos_argument = arguments[0]->evaluate();
|
|
|
|
if(cos_argument.type == SenchaObject::integer_number)
|
|
|
|
{
|
|
|
|
result = SenchaObject(cos(cos_argument.integer));
|
|
|
|
}
|
|
|
|
else if(cos_argument.type == SenchaObject::float_number)
|
|
|
|
{
|
|
|
|
result = SenchaObject(cos(cos_argument.number));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.type = SenchaObject::invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SenchaObject s_tan(vector<ASTExpression *> arguments)
|
|
|
|
{
|
|
|
|
SenchaObject result;
|
|
|
|
SenchaObject tan_argument = arguments[0]->evaluate();
|
|
|
|
if(tan_argument.type == SenchaObject::integer_number)
|
|
|
|
{
|
|
|
|
result = SenchaObject(tan(tan_argument.integer));
|
|
|
|
}
|
|
|
|
else if(tan_argument.type == SenchaObject::float_number)
|
|
|
|
{
|
|
|
|
result = SenchaObject(tan(tan_argument.number));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result.type = SenchaObject::invalid;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-11-02 23:07:00 +00:00
|
|
|
|
|
|
|
|
2012-11-18 13:44:46 +00:00
|
|
|
int how_depth_change(vector<Token> tokens)
|
|
|
|
{
|
|
|
|
int change = 0;
|
2012-12-08 19:59:05 +00:00
|
|
|
for (unsigned int i = 0; i < tokens.size(); i++)
|
2012-11-18 13:44:46 +00:00
|
|
|
{
|
|
|
|
if(tokens[i].value == "{") change++;
|
|
|
|
else if(tokens[i].value == "}") change--;
|
|
|
|
}
|
|
|
|
return change;
|
|
|
|
}
|
|
|
|
|
|
|
|
string compute_indentation(int depth_level)
|
|
|
|
{
|
|
|
|
string indent = "";
|
|
|
|
for(int i=0; i< depth_level; i++)
|
|
|
|
{
|
|
|
|
indent += " ";
|
|
|
|
}
|
|
|
|
return indent;
|
|
|
|
}
|
2012-11-08 20:16:00 +00:00
|
|
|
|
2012-11-04 15:21:51 +00:00
|
|
|
void interactive()
|
|
|
|
{
|
|
|
|
Lexer lexer;
|
2012-12-08 19:59:05 +00:00
|
|
|
|
|
|
|
Context context;
|
2012-12-10 10:45:09 +00:00
|
|
|
context.register_function("print", print);
|
|
|
|
context.register_function("sin", s_sin);
|
|
|
|
context.register_function("cos", s_cos);
|
|
|
|
context.register_function("tan", s_tan);
|
2012-12-22 11:20:23 +00:00
|
|
|
context.register_function("sleep", sleep);
|
2012-12-10 10:45:09 +00:00
|
|
|
|
2012-12-08 19:59:05 +00:00
|
|
|
Parser parser(&context);
|
2012-12-22 08:07:13 +00:00
|
|
|
ASTInspector inspector;
|
2012-11-04 15:21:51 +00:00
|
|
|
vector<Token> tokens;
|
|
|
|
|
2012-11-08 20:16:00 +00:00
|
|
|
string input;
|
|
|
|
int level_of_depth = 0;
|
|
|
|
string indentation = "";
|
2012-11-05 13:17:38 +00:00
|
|
|
while(true)
|
2012-11-04 15:21:51 +00:00
|
|
|
{
|
2012-11-08 20:16:00 +00:00
|
|
|
cout << ">> " + indentation;
|
2012-11-04 15:21:51 +00:00
|
|
|
getline(cin, input);
|
2012-11-05 13:17:38 +00:00
|
|
|
if(input == "quit()") break;
|
2012-11-04 15:21:51 +00:00
|
|
|
tokens = lexer.parse_line(input);
|
2012-11-18 13:44:46 +00:00
|
|
|
|
|
|
|
level_of_depth += how_depth_change(tokens);
|
|
|
|
indentation = compute_indentation(level_of_depth);
|
2012-11-08 20:16:00 +00:00
|
|
|
|
|
|
|
parser.add_tokens(tokens);
|
2012-11-18 13:44:46 +00:00
|
|
|
|
|
|
|
if(level_of_depth == 0) {
|
2012-11-08 20:16:00 +00:00
|
|
|
parser.interpret();
|
2012-12-09 11:57:51 +00:00
|
|
|
parser.program->execute_last();
|
2012-12-08 19:59:05 +00:00
|
|
|
//cout << parser.error_message << endl;
|
|
|
|
//cout << parser.show_tokens() << endl;
|
2012-12-22 08:07:13 +00:00
|
|
|
inspector.visit(parser.program);
|
2012-12-22 10:06:55 +00:00
|
|
|
|
2012-12-22 08:07:13 +00:00
|
|
|
//cout << parser.context->debug();
|
|
|
|
cout << inspector.get_report();
|
|
|
|
inspector.forget_everything();
|
2012-11-08 20:16:00 +00:00
|
|
|
}
|
2012-11-04 15:21:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-12-09 16:42:13 +00:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2012-12-17 11:47:05 +00:00
|
|
|
if(argc <= 1)
|
|
|
|
{
|
|
|
|
cout << "Sencha-lang interpreter, version 0.12" << endl;
|
|
|
|
interactive();
|
|
|
|
}
|
2012-12-18 21:41:39 +00:00
|
|
|
else
|
2012-12-17 11:47:05 +00:00
|
|
|
{
|
2012-12-18 21:41:39 +00:00
|
|
|
std::string argument1 = argv[1];
|
|
|
|
if(argument1 == "--test") {
|
|
|
|
|
|
|
|
cout << "I'm running tests" << endl;
|
|
|
|
run_tests();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
auto name = argument1;
|
|
|
|
Lexer lexer;
|
|
|
|
Context context;
|
|
|
|
context.register_function("print", print);
|
|
|
|
context.register_function("sin", s_sin);
|
|
|
|
context.register_function("cos", s_cos);
|
|
|
|
context.register_function("tan", s_tan);
|
2012-12-22 11:20:23 +00:00
|
|
|
context.register_function("sleep", sleep);
|
2012-12-18 21:41:39 +00:00
|
|
|
|
|
|
|
Parser parser(&context);
|
2012-12-22 08:07:13 +00:00
|
|
|
|
2012-12-18 21:41:39 +00:00
|
|
|
vector<Token> tokens;
|
|
|
|
string line;
|
|
|
|
ifstream input_file (name);
|
|
|
|
|
|
|
|
if (input_file.is_open())
|
2012-12-17 11:47:05 +00:00
|
|
|
{
|
2012-12-18 21:41:39 +00:00
|
|
|
while ( input_file.good() )
|
|
|
|
{
|
|
|
|
getline (input_file,line);
|
|
|
|
tokens = lexer.parse_line(line);
|
|
|
|
parser.add_tokens(tokens);
|
|
|
|
}
|
|
|
|
input_file.close();
|
2012-12-17 11:47:05 +00:00
|
|
|
}
|
|
|
|
|
2012-12-18 21:41:39 +00:00
|
|
|
parser.interpret();
|
|
|
|
parser.program->execute();
|
|
|
|
}
|
2012-12-17 11:47:05 +00:00
|
|
|
}
|
2012-12-09 16:42:13 +00:00
|
|
|
|
2012-12-17 11:47:05 +00:00
|
|
|
return 0;
|
2012-11-02 23:07:00 +00:00
|
|
|
}
|