#include #include #include #include #include "Token.h" #include "Lexer.h" #include "Parser.h" #include "Tests/TestLexer.h" #include "ContextManager.h" #include "ASTInspector.h" #include "Tests/tests.h" #include using namespace std; /*TODO * Known bugs: * * >> print("I like bananas", dupa"); I like bananasnull Context: 0: dupa"); type: null null dupa"); declaration? hello? It's probably temporary effect of searching for this name in variable tables >> */ SenchaObject sleep(vector 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; } } SenchaObject print(vector arguments) { for (auto argument: arguments) { auto value = argument->evaluate(); std::cout << value.str(); } std::cout << std::endl; return SenchaObject(); } SenchaObject s_sin(vector 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 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 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; } SenchaObject len(vector arguments) { SenchaObject result; SenchaObject argument = arguments[0]->evaluate(); if(argument.type == SenchaObject::string_literal) { result = SenchaObject(int(argument.text.size())); } return result; } int how_depth_change(vector tokens) { int change = 0; for (unsigned int i = 0; i < tokens.size(); i++) { 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; } void interactive() { Lexer lexer; ContextManager context; context.register_function("print", print); context.register_function("sin", s_sin); context.register_function("cos", s_cos); context.register_function("tan", s_tan); context.register_function("sleep", sleep); context.register_function("len", len); Parser parser(&context); ASTInspector inspector; vector tokens; string input; int level_of_depth = 0; string indentation = ""; while(true) { cout << ">> " + indentation; getline(cin, input); if(input == "quit()") break; tokens = lexer.parse_line(input); level_of_depth += how_depth_change(tokens); indentation = compute_indentation(level_of_depth); parser.add_tokens(tokens); if(level_of_depth == 0) { parser.interpret(); parser.program->execute_last(); inspector.visit(parser.program); cout << inspector.get_report(); inspector.forget_everything(); } } } int main(int argc, char *argv[]) { if(argc <= 1) { cout << "Sencha-lang interpreter, version 0.12" << endl; interactive(); } else { std::string argument1 = argv[1]; if(argument1 == "--test") { cout << "I'm running tests" << endl; run_tests(); } else { auto name = argument1; Lexer lexer; ContextManager context; context.register_function("print", print); context.register_function("sin", s_sin); context.register_function("cos", s_cos); context.register_function("tan", s_tan); context.register_function("sleep", sleep); context.register_function("len", len); Parser parser(&context); vector tokens; string line; ifstream input_file (name); if (input_file.is_open()) { while ( input_file.good() ) { getline (input_file,line); tokens = lexer.parse_line(line); parser.add_tokens(tokens); } input_file.close(); } parser.interpret(); parser.program->execute(); } } return 0; }