More documentaaaaation.

master
Justyna Ilczuk 2013-01-13 17:36:38 +01:00
parent 837d4c4bce
commit 058a18c612
23 changed files with 438 additions and 333 deletions

View File

@ -76,10 +76,10 @@ SenchaObject Context::get(std::string name)
std::string Context::debug() { std::string Context::debug() {
std::string debug_note = ""; std::string debug_note = "";
debug_note += "Context: " + this->name + " contains:\n";
for( auto iter = this->object_store.begin(); iter != this->object_store.end(); iter++) for( auto iter = this->object_store.begin(); iter != this->object_store.end(); iter++)
{ {
debug_note += "Context: " + (*iter).second.repr() + ": " + (*iter).first + " " + "\n"; debug_note += "name: " + (*iter).first + ", value: " + (*iter).second.repr() + "\n";
} }
return debug_note; return debug_note;

View File

@ -24,29 +24,77 @@
*/ */
class Context { class Context {
public: public:
/**
* Context has unique name, which is passed to it in constructor.
*/
Context(std::string name); Context(std::string name);
std::string name; std::string name;
/**
* Typedef to make further declarations easier to read.
*/
typedef SenchaObject (*PointerToNativeFunction)(std::vector<ASTExpression *>); typedef SenchaObject (*PointerToNativeFunction)(std::vector<ASTExpression *>);
/**
* Function have to be declared, which means here, registered before usage.
* You can register them with register_function functions.
*/
void register_function(std::string name, PointerToNativeFunction f); void register_function(std::string name, PointerToNativeFunction f);
void register_function(std::string name, SenchaFunction * f); void register_function(std::string name, SenchaFunction * f);
SenchaObject execute_native_function(std::string name, std::vector<ASTExpression *> arguments); /**
SenchaObject get_updated_string(std::string name); * Map with function written in C++ stored like {"my_function" : &my_function}
std::string debug() ; */
void add(std::string name, SenchaObject object);
void set(std::string name, SenchaObject object);
SenchaObject get(std::string name);
bool contains_function(std::string name);
bool contains_sfunction(std::string name);
bool contains_nfunction(std::string name);
std::map<std::string, PointerToNativeFunction> registered_functions; std::map<std::string, PointerToNativeFunction> registered_functions;
/**
* Map with function written in Sencha stored like {"my_function" : &my_function}
*/
std::map<std::string, SenchaFunction *> registered_sfunctions; std::map<std::string, SenchaFunction *> registered_sfunctions;
/**
* contains_function("x") returns true if x can be found in registered native (c++) or sencha functions.
*/
bool contains_function(std::string name);
/**
* contains_function("x") returns true if x can be found in registered sencha functions.
*/
bool contains_sfunction(std::string name);
/**
* contains_function("x") returns true if x can be found in registered native (c++).
*/
bool contains_nfunction(std::string name);
/**
* Executes function written in c++
*/
SenchaObject execute_native_function(std::string name, std::vector<ASTExpression *> arguments);
/**
* get_updated_string(name) return string of given name with all updates done on its elements such as name[9] = "a";
*/
SenchaObject get_updated_string(std::string name);
/**
* debug() provides very useful info about context. What variables are stored, what are their values.
*/
std::string debug() ;
/**
* add(name, value) adds value called name to object store.
*/
void add(std::string name, SenchaObject object);
/**
* get(name) returns value from object store. If there isn't such a value. It returns SenchaObject();
*/
SenchaObject get(std::string name);
virtual ~Context(); virtual ~Context();
private: private:
unsigned int index; unsigned int index;
std::map<std::string, SenchaObject> object_store; std::map<std::string, SenchaObject> object_store;
}; };

View File

@ -18,7 +18,7 @@ ContextManager::~ContextManager() {
Context * ContextManager::create_new_context() Context * ContextManager::create_new_context()
{ {
Context * context = new Context("Zdzislaw" + to_string(index)); Context * context = new Context("abcd" + to_string(index));
index++; index++;
contexts[context->name] = context; contexts[context->name] = context;
stack.push(context); stack.push(context);
@ -61,12 +61,6 @@ SenchaObject ContextManager::execute_function(std::string name, std::vector<ASTE
} }
Context * ContextManager::get_context(std::string name)
{
return contexts[name];
}
Context * ContextManager::get_top() Context * ContextManager::get_top()
{ {
return stack.top(); return stack.top();

View File

@ -13,25 +13,35 @@
#include <stack> #include <stack>
#include "Context.h" #include "Context.h"
/**
* ContextManager manages contexts.
*/
class ContextManager { class ContextManager {
public: public:
ContextManager(); ContextManager();
/**
* execute_function(name, arguments) executes function giving her its own execution context.
*/
SenchaObject execute_function(std::string name, std::vector<ASTExpression *> arguments);
std::stack<Context *> stack; //creation, destruction and basic access to contexts
std::map<std::string, Context *> contexts;
Context * create_new_context(); Context * create_new_context();
void destroy_context(std::string name); void destroy_context(std::string name);
Context * get_context(std::string name);
Context * context(std::string name); Context * context(std::string name);
//access to contexts using stack
Context * get_top(); Context * get_top();
SenchaObject execute_function(std::string name, std::vector<ASTExpression *> arguments);
void pop_context(); void pop_context();
unsigned int index;
virtual ~ContextManager(); virtual ~ContextManager();
private:
/**
* Contexts are stored both in a stack (FILO) and in a map (indexed by names).
*/
std::stack<Context *> stack;
std::map<std::string, Context *> contexts;
unsigned int index;
}; };
#endif /* CONTEXT_MANAGER_H_ */ #endif /* CONTEXT_MANAGER_H_ */

View File

@ -8,6 +8,10 @@
#ifndef ELEMENT_H_ #ifndef ELEMENT_H_
#define ELEMENT_H_ #define ELEMENT_H_
/**
* Basic element in sencha language design. Actually now it does nothing.
* It'd be changed in further versions.
*/
class Element class Element
{ {
public: public:

View File

@ -11,20 +11,35 @@
#include "Element.h" #include "Element.h"
#include "../ContextManager.h" #include "../ContextManager.h"
/**
* SenchaArray is an abstraction of array element in a language.
* It provides access to its elements and some basic methods.
* It uses context_manager to evaluate its elements. SenchaArray is created on the go and stored nowhere.
*/
class SenchaArray: public Element { class SenchaArray: public Element {
public: public:
/**
* Basic, universal constructor.
*/
SenchaArray(std::string name, ContextManager * context_manager); SenchaArray(std::string name, ContextManager * context_manager);
/**
* Special constructor, used to deal with strings
*/
SenchaArray(std::string name, ContextManager * context_manager, std::string); SenchaArray(std::string name, ContextManager * context_manager, std::string);
ContextManager * context_manager;
std::string name;
typedef int IndexNumber; typedef int IndexNumber;
IndexNumber add(SenchaObject value); IndexNumber add(SenchaObject value);
void set(IndexNumber index, SenchaObject value); void set(IndexNumber index, SenchaObject value);
IndexNumber max_index;
SenchaObject get(IndexNumber index); SenchaObject get(IndexNumber index);
//lots of stuff
virtual ~SenchaArray(); virtual ~SenchaArray();
private:
ContextManager * context_manager;
std::string name;
IndexNumber max_index;
}; };
#endif /* SENCHAARRAY_H_ */ #endif /* SENCHAARRAY_H_ */

View File

@ -15,19 +15,23 @@
#include "../Utils/to_string.h" #include "../Utils/to_string.h"
#include "../AST/ASTNode.h" #include "../AST/ASTNode.h"
/**
* SenchaFunction is a class which is an abstraction of function written in SenchaLang.
* It stores name of the function, its body, and provides () call operator.
*/
class SenchaFunction : public Element class SenchaFunction : public Element
{ {
public: public:
std::string name;
std::vector<std::string> names_of_arguments;
ASTNode * body;
SenchaFunction(std::string name, std::vector<std::string> names_of_arguments, ASTNode * body); SenchaFunction(std::string name, std::vector<std::string> names_of_arguments, ASTNode * body);
SenchaObject operator()(); SenchaObject operator()();
std::string name;
std::vector<std::string> names_of_arguments;
virtual ~SenchaFunction(); virtual ~SenchaFunction();
private:
ASTNode * body;
}; };
#endif /* SENCHAFUNCTION_H_ */ #endif /* SENCHAFUNCTION_H_ */

View File

@ -91,10 +91,6 @@ std::string SenchaObject::repr()
representation = "type: null\n"; representation = "type: null\n";
representation += "null"; representation += "null";
break; break;
case symbol:
representation = "type: symbol\n";
representation += this->text;
break;
case invalid: case invalid:
representation = "type: invalid\n"; representation = "type: invalid\n";
representation += "some crap"; representation += "some crap";
@ -122,9 +118,6 @@ std::string SenchaObject::str()
case null: case null:
representation += "null"; representation += "null";
break; break;
case symbol:
representation += this->text;
break;
case invalid: case invalid:
representation += "some crap"; representation += "some crap";
break; break;
@ -150,6 +143,15 @@ SenchaObject SenchaObject::operator+(const SenchaObject& right)const
case float_number: case float_number:
result.set_value(this->number + right.number); result.set_value(this->number + right.number);
break; break;
case boolean:
result.type = invalid;
break;
case invalid:
result.type = invalid;
break;
case null:
result.type = invalid;
break;
} }
} }
else if(type == float_number && right.type == integer_number ) else if(type == float_number && right.type == integer_number )
@ -184,6 +186,15 @@ SenchaObject SenchaObject::operator-(const SenchaObject& right)const
case float_number: case float_number:
result.set_value(this->number - right.number); result.set_value(this->number - right.number);
break; break;
case boolean:
result.type = invalid;
break;
case invalid:
result.type = invalid;
break;
case null:
result.type = invalid;
break;
} }
} }
else if(type == float_number && right.type == integer_number ) else if(type == float_number && right.type == integer_number )
@ -217,6 +228,15 @@ SenchaObject SenchaObject::operator*(const SenchaObject& right)const
case float_number: case float_number:
result.set_value(this->number * right.number); result.set_value(this->number * right.number);
break; break;
case boolean:
result.type = invalid;
break;
case invalid:
result.type = invalid;
break;
case null:
result.type = invalid;
break;
} }
} }
else if(type == float_number && right.type == integer_number ) else if(type == float_number && right.type == integer_number )
@ -250,6 +270,15 @@ SenchaObject SenchaObject::operator/(const SenchaObject& right)const
case float_number: case float_number:
result.set_value(this->number / right.number); result.set_value(this->number / right.number);
break; break;
case boolean:
result.type = invalid;
break;
case invalid:
result.type = invalid;
break;
case null:
result.type = invalid;
break;
} }
} }
else if(type == float_number && right.type == integer_number ) else if(type == float_number && right.type == integer_number )
@ -269,7 +298,7 @@ SenchaObject SenchaObject::operator/(const SenchaObject& right)const
} }
SenchaObject SenchaObject::operator==(const SenchaObject& right)const SenchaObject SenchaObject::operator==(const SenchaObject& right)const
{ {
SenchaObject result; SenchaObject result;
bool value = false; bool value = false;
result.type = boolean; result.type = boolean;
@ -301,15 +330,21 @@ SenchaObject SenchaObject::operator==(const SenchaObject& right)const
value = true; value = true;
} }
break; break;
case invalid:
result.type = invalid;
break;
case null:
result.type = invalid;
break;
} }
} }
result.truthy = value; result.truthy = value;
return result; return result;
} }
SenchaObject SenchaObject::operator!=(const SenchaObject& right) const SenchaObject SenchaObject::operator!=(const SenchaObject& right) const
{ {
SenchaObject result; SenchaObject result;
result.type = boolean; result.type = boolean;
@ -319,7 +354,7 @@ SenchaObject SenchaObject::operator!=(const SenchaObject& right) const
else result.truthy = true; else result.truthy = true;
return result; return result;
} }
SenchaObject SenchaObject::operator>(const SenchaObject& right) const SenchaObject SenchaObject::operator>(const SenchaObject& right) const
@ -349,23 +384,32 @@ SenchaObject SenchaObject::operator>(const SenchaObject& right) const
value = true; value = true;
} }
break; break;
case invalid:
result.type = invalid;
break;
case boolean:
result.type = invalid;
break;
case null:
result.type = invalid;
break;
} }
} }
else if(type == float_number && right.type == integer_number ) else if(type == float_number && right.type == integer_number )
{ {
value = (this->number > right.integer); value = (this->number > right.integer);
} }
else if(type == integer_number && right.type == float_number) else if(type == integer_number && right.type == float_number)
{ {
value = (this->integer > right.number); value = (this->integer > right.number);
} }
result.truthy = value; result.truthy = value;
return result; return result;
} }
SenchaObject SenchaObject::operator>= (const SenchaObject& right) const SenchaObject SenchaObject::operator>= (const SenchaObject& right) const
{ {
SenchaObject result; SenchaObject result;
bool value = false; bool value = false;
result.type = boolean; result.type = boolean;
@ -376,7 +420,7 @@ SenchaObject SenchaObject::operator>= (const SenchaObject& right) const
} }
result.truthy = value; result.truthy = value;
return result; return result;
} }
SenchaObject SenchaObject::operator< (const SenchaObject& right) const SenchaObject SenchaObject::operator< (const SenchaObject& right) const
{ {

View File

@ -12,21 +12,31 @@
#include "../Utils/to_string.h" #include "../Utils/to_string.h"
#include "Element.h" #include "Element.h"
/**
* SenchaObject stores values in SenchaLang. It handles operations on them, thanks to defined, overloaded operators.
* Also provides representation of values.
*/
class SenchaObject : public Element { class SenchaObject : public Element {
public: public:
/**
* Possible types of SenchaObject
*/
typedef enum { typedef enum {
string_literal, string_literal,
integer_number, integer_number,
float_number, float_number,
null, null,
symbol,
boolean, boolean,
invalid invalid
} Type; } Type;
Type type; Type type;
/**
* repr() returns representation of value as a string
*/
virtual std::string repr(); virtual std::string repr();
virtual std::string str(); virtual std::string str();
virtual bool is_true(); virtual bool is_true();
@ -51,6 +61,7 @@ public:
SenchaObject(std::string text) { set_value(text); } SenchaObject(std::string text) { set_value(text); }
//Operators used in expressions
virtual SenchaObject operator< (const SenchaObject& right)const; virtual SenchaObject operator< (const SenchaObject& right)const;
virtual SenchaObject operator> (const SenchaObject& right)const; virtual SenchaObject operator> (const SenchaObject& right)const;
virtual SenchaObject operator<= (const SenchaObject& right)const; virtual SenchaObject operator<= (const SenchaObject& right)const;

View File

@ -9,31 +9,39 @@
using namespace std; using namespace std;
/**
* Lexer is a class which gets some text, analyzes it and returns a vector of tokens.
*/
class Lexer class Lexer
{ {
public: public:
Lexer(); Lexer();
virtual ~Lexer(); virtual ~Lexer();
/**
void add_keyword(string word); * parse_line(line) analyzes input and returns vector of tokens.
void add_punctuation_char(char c); */
void add_operator(string oper); vector<Token> parse_line(string line);
string unescape_string(string text); pair<string, Token> parse_token(string line);
vector<Token> parse_line(string line);
pair<string, Token> parse_token(string line);
type_of_token guess_type(string value);
bool is_keyword(string value); //helper function to evaluate type of token
bool is_punctuation(char c); bool is_keyword(string value);
bool is_operator(string value ); bool is_punctuation(char c);
bool is_operator(string value );
protected: private:
private: void add_keyword(string word);
void add_punctuation_char(char c);
void add_operator(string oper);
string unescape_string(string text);
/**
* Tokens have type and value. Type is evaluated in function guess_type(value).
*/
type_of_token guess_type(string value);
vector<string> keywords; vector<string> keywords;
vector<char> punctuation; vector<char> punctuation;
vector<string> operators; vector<string> operators;
}; };
#endif // LEXER_H #endif // LEXER_H

View File

@ -1,12 +0,0 @@
#include "Object.h"
Object::Object()
{
number_value = 0;
//ctor
}
Object::~Object()
{
//dtor
}

View File

@ -1,21 +0,0 @@
#ifndef OBJECT_H
#define OBJECT_H
#include <string>
//I don't know how should it look like!
class Object
{
public:
Object();
virtual ~Object();
//Representation of the object
std::string str();
//Type
std::string type();
//Possible values
double number_value;
std::string characters;
protected:
private:
};
#endif // OBJECT_H

View File

@ -118,15 +118,7 @@ bool Parser::is_type()
else return false; else return false;
} }
bool Parser::is_function_name()
{
if(context_manager->context("global")->contains_function(tok_value))
{
read_next();
return true;
}
else return false;
}
ASTStatement * Parser::statement() ASTStatement * Parser::statement()
{ {

View File

@ -10,6 +10,9 @@
using namespace std; using namespace std;
/**
* Parser does parsing and produces AST. It provides root of AST which can be used to execute statements.
*/
class Parser class Parser
{ {
public: public:
@ -47,9 +50,7 @@ class Parser
protected: protected:
private: private:
//Not used in current implementation, delete?
bool is_function_name();
Token current_token; Token current_token;
string tok_value; string tok_value;
vector<Token> token_stream; vector<Token> token_stream;

View File

@ -13,18 +13,22 @@
#include "../AST/BasicExpression.h" #include "../AST/BasicExpression.h"
#include "../AST/ConstantExpression.h" #include "../AST/ConstantExpression.h"
/**
* TestASTInspector checks some basic features of ASTInspector.
*/
class TestASTInspector: public TestSuite { class TestASTInspector: public TestSuite {
public: public:
TestASTInspector(); TestASTInspector();
virtual ~TestASTInspector(); virtual ~TestASTInspector();
std::string test_inspecting_basic_expression();
std::string test_inspecting_simple_AST();
virtual std::string all_tests(); virtual std::string all_tests();
private: private:
//tests
std::string test_inspecting_basic_expression();
std::string test_inspecting_simple_AST();
//helper functions
BasicExpression * build_basic_expression(std::string oper, SenchaObject arg1, SenchaObject arg2); BasicExpression * build_basic_expression(std::string oper, SenchaObject arg1, SenchaObject arg2);
BasicExpression * build_simple_AST(std::string oper, BasicExpression * left, BasicExpression * right); BasicExpression * build_simple_AST(std::string oper, BasicExpression * left, BasicExpression * right);
//instance of ASTInspector
ASTInspector inspector; ASTInspector inspector;
}; };

View File

@ -22,7 +22,6 @@ std::string TestLexer::all_tests()
std::string test_report = ""; std::string test_report = "";
mu_run_test(test_searching_keyword_for_not_keyword); mu_run_test(test_searching_keyword_for_not_keyword);
mu_run_test(test_fake);
mu_run_test(test_searching_keyword); mu_run_test(test_searching_keyword);
mu_run_test(test_parsing_simple_token); mu_run_test(test_parsing_simple_token);
mu_run_test(test_parsing_tricky_token); mu_run_test(test_parsing_tricky_token);
@ -30,11 +29,6 @@ std::string TestLexer::all_tests()
return test_report; return test_report;
} }
std::string TestLexer::test_fake()
{
mu_assert("1 == 1", 1 == 1);
return "";
}
std::string TestLexer::test_searching_keyword_for_not_keyword() std::string TestLexer::test_searching_keyword_for_not_keyword()
{ {

View File

@ -17,15 +17,14 @@ class TestLexer : public TestSuite {
public: public:
TestLexer(); TestLexer();
virtual ~TestLexer(); virtual ~TestLexer();
virtual std::string all_tests();
private:
Lexer lexer;
std::string test_searching_keyword_for_not_keyword(); std::string test_searching_keyword_for_not_keyword();
std::string test_searching_keyword(); std::string test_searching_keyword();
std::string test_parsing_simple_token(); std::string test_parsing_simple_token();
std::string test_parsing_tricky_token(); std::string test_parsing_tricky_token();
virtual std::string all_tests();
std::string test_fake();
private:
Lexer lexer;
}; };
#endif /* TESTLEXER_H_ */ #endif /* TESTLEXER_H_ */

View File

@ -16,24 +16,29 @@
#include <vector> #include <vector>
/**
* TestParser is test suite for testing parser.
* It checks if parser works correctly.
* Features checked: defining and calling functions, array access, changing letters in strings and so on.
*/
class TestParser: public TestSuite { class TestParser: public TestSuite {
public: public:
TestParser(); TestParser();
virtual ~TestParser(); virtual ~TestParser();
typedef std::pair<std::string, bool> InputOutputPair; typedef std::pair<std::string, bool> InputOutputPair;
typedef std::pair<std::string, SenchaObject> SInputOutputPair; typedef std::pair<std::string, SenchaObject> SInputOutputPair;
private: private:
//Actual tests
std::string test_parsing_and_evaluating_logical_expressions(); std::string test_parsing_and_evaluating_logical_expressions();
std::string test_adding_new_function(); std::string test_adding_new_function();
std::string test_calling_funtion(); std::string test_calling_funtion();
std::string prepare_some_function_declarations();
std::string test_writing_and_accessing_array_elements(); std::string test_writing_and_accessing_array_elements();
std::string test_changing_letters_in_string(); std::string test_changing_letters_in_string();
std::vector<InputOutputPair> prepare_logical_input(); std::vector<InputOutputPair> prepare_logical_input();
std::string prepare_some_function_declarations();
virtual std::string all_tests(); virtual std::string all_tests();
}; };

View File

@ -0,0 +1,121 @@
#include <iostream>
#include <string>
#include <vector>
#include <math.h>
#include "AST/AllTypesOfASTNodes.h"
using namespace std;
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;
}
}
SenchaObject print(vector<ASTExpression *> arguments)
{
for (auto argument: arguments)
{
auto value = argument->evaluate();
std::cout << value.str();
}
return SenchaObject();
}
SenchaObject println(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;
}
SenchaObject len(vector<ASTExpression *> arguments)
{
SenchaObject result;
SenchaObject argument = arguments[0]->evaluate();
if(argument.type == SenchaObject::string_literal)
{
result = SenchaObject(int(argument.text.size()));
}
return result;
}

View File

@ -187,8 +187,8 @@ div.line {
word-wrap: break-word; /* IE 5.5+ */ word-wrap: break-word; /* IE 5.5+ */
text-indent: -53px; text-indent: -53px;
padding-left: 53px; padding-left: 53px;
padding-bottom: 0px; padding-bottom: 2px;
margin: 0px; margin: 2px;
-webkit-transition-property: background-color, box-shadow; -webkit-transition-property: background-color, box-shadow;
-webkit-transition-duration: 0.5s; -webkit-transition-duration: 0.5s;
-moz-transition-property: background-color, box-shadow; -moz-transition-property: background-color, box-shadow;

View File

@ -21,9 +21,10 @@ $extrastylesheet
<div id="titlearea"> <div id="titlearea">
<table cellspacing="0" cellpadding="0"> <table cellspacing="0" cellpadding="0">
<tbody> <tbody>
<tr style="height: 56px;"> <tr style="height: 36px;">
<!--BEGIN PROJECT_LOGO--> <!--BEGIN PROJECT_LOGO-->
<td id="projectlogo"><img alt="Logo" src="$relpath$$projectlogo"/></td> <td id="projectlogo"><img alt="Logo" height="130"
width="80" src="$relpath$$projectlogo"/></td>
<!--END PROJECT_LOGO--> <!--END PROJECT_LOGO-->
<!--BEGIN PROJECT_NAME--> <!--BEGIN PROJECT_NAME-->
<td style="padding-left: 0.5em;"> <td style="padding-left: 0.5em;">

View File

@ -9,148 +9,21 @@
#include "ContextManager.h" #include "ContextManager.h"
#include "ASTInspector.h" #include "ASTInspector.h"
#include "Tests/tests.h" #include "Tests/tests.h"
#include "basic_native_functions.h"
#include <unistd.h> #include <unistd.h>
using namespace std; using namespace std;
//Helper functions
/*TODO void register_functions(ContextManager & context_manager)
* 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<ASTExpression *> arguments)
{ {
SenchaObject argument = arguments[0]->evaluate(); context_manager.context("global")->register_function("print", print);
if(argument.type == SenchaObject::integer_number && argument.integer >= 0) context_manager.context("global")->register_function("println", println);
{ context_manager.context("global")->register_function("sin", s_sin);
cout << "valid argument for sleep: " << argument.integer << endl; context_manager.context("global")->register_function("cos", s_cos);
usleep(1000 * argument.integer); context_manager.context("global")->register_function("tan", s_tan);
return SenchaObject(); context_manager.context("global")->register_function("sleep", sleep);
} context_manager.context("global")->register_function("len", len);
else
{
cout << "invalid argument for sleep";
argument.type = SenchaObject::invalid;
return argument;
}
}
SenchaObject print(vector<ASTExpression *> arguments)
{
for (auto argument: arguments)
{
auto value = argument->evaluate();
std::cout << value.str();
}
return SenchaObject();
}
SenchaObject println(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;
}
SenchaObject len(vector<ASTExpression *> 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<Token> 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 compute_indentation(int depth_level)
@ -163,18 +36,24 @@ string compute_indentation(int depth_level)
return indent; return indent;
} }
int how_depth_change(vector<Token> 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;
}
void interactive() void interactive()
{ {
//Initialization
Lexer lexer; Lexer lexer;
ContextManager context_manager; ContextManager context_manager;
context_manager.context("global")->register_function("print", print); register_functions(context_manager);
context_manager.context("global")->register_function("println", println);
context_manager.context("global")->register_function("sin", s_sin);
context_manager.context("global")->register_function("cos", s_cos);
context_manager.context("global")->register_function("tan", s_tan);
context_manager.context("global")->register_function("sleep", sleep);
context_manager.context("global")->register_function("len", len);
Parser parser(&context_manager); Parser parser(&context_manager);
ASTInspector inspector; ASTInspector inspector;
@ -183,6 +62,7 @@ void interactive()
string input; string input;
int level_of_depth = 0; int level_of_depth = 0;
string indentation = ""; string indentation = "";
//Main loop of interactive mode
while(true) while(true)
{ {
cout << ">> " + indentation; cout << ">> " + indentation;
@ -195,6 +75,7 @@ void interactive()
parser.add_tokens(tokens); parser.add_tokens(tokens);
//It executes when statements and braces are closed
if(level_of_depth == 0) { if(level_of_depth == 0) {
parser.interpret(); parser.interpret();
parser.program->execute_last(); parser.program->execute_last();
@ -206,55 +87,57 @@ void interactive()
} }
} }
} }
void execute_script(std::string name )
{
Lexer lexer;
ContextManager context_manager;
register_functions(context_manager);
Parser parser(&context_manager);
vector<Token> 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();
}
/**
* Main function resolves in which mode user want to run program
* Modes are:
* Interactive - it is run when no arguments are provided
* Tests - "SenchaLang --test"
* Script execution - if path provided
*/
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if(argc <= 1) if(argc <= 1)
{ {
cout << "Sencha-lang interpreter, version 0.12" << endl; cout << "Sencha-lang interpreter, version 0.44" << endl;
interactive(); interactive();
} }
else else
{ {
std::string argument1 = argv[1]; std::string argument1 = argv[1];
if(argument1 == "--test") { if(argument1 == "--test")
{
cout << "I'm running tests" << endl; cout << "I'm running tests" << endl;
run_tests(); run_tests();
} }
else { else {
auto name = argument1; execute_script(argument1);
Lexer lexer;
ContextManager context_manager;
context_manager.context("global")->register_function("print", print);
context_manager.context("global")->register_function("println", println);
context_manager.context("global")->register_function("sin", s_sin);
context_manager.context("global")->register_function("cos", s_cos);
context_manager.context("global")->register_function("tan", s_tan);
context_manager.context("global")->register_function("sleep", sleep);
context_manager.context("global")->register_function("len", len);
Parser parser(&context_manager);
vector<Token> 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();
}
ASTInspector inspector;
parser.interpret();
inspector.visit(parser.tree.root);
parser.program->execute();
//cout << inspector.get_report()<< endl;
} }
} }

View File

@ -45,7 +45,7 @@ PROJECT_BRIEF = "Simple language interpreter, in developement"
# exceed 55 pixels and the maximum width should not exceed 200 pixels. # exceed 55 pixels and the maximum width should not exceed 200 pixels.
# Doxygen will copy the logo to the output directory. # Doxygen will copy the logo to the output directory.
PROJECT_LOGO = PROJECT_LOGO = /home/att/old/development/sencha-web/static/senchalogo2.png
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put. # base path where the generated documentation will be put.
@ -835,7 +835,7 @@ USE_HTAGS = NO
# will generate a verbatim copy of the header file for each class for # will generate a verbatim copy of the header file for each class for
# which an include is specified. Set to NO to disable this. # which an include is specified. Set to NO to disable this.
VERBATIM_HEADERS = YES VERBATIM_HEADERS = NO
#--------------------------------------------------------------------------- #---------------------------------------------------------------------------
# configuration options related to the alphabetical class index # configuration options related to the alphabetical class index
@ -892,13 +892,13 @@ HTML_FILE_EXTENSION = .html
# have to redo this when upgrading to a newer version of doxygen or when # have to redo this when upgrading to a newer version of doxygen or when
# changing the value of configuration settings such as GENERATE_TREEVIEW! # changing the value of configuration settings such as GENERATE_TREEVIEW!
HTML_HEADER = HTML_HEADER = header.html
# The HTML_FOOTER tag can be used to specify a personal HTML footer for # The HTML_FOOTER tag can be used to specify a personal HTML footer for
# each generated HTML page. If it is left blank doxygen will generate a # each generated HTML page. If it is left blank doxygen will generate a
# standard footer. # standard footer.
HTML_FOOTER = HTML_FOOTER = footer.html
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading # The HTML_STYLESHEET tag can be used to specify a user-defined cascading
# style sheet that is used by each HTML page. It can be used to # style sheet that is used by each HTML page. It can be used to
@ -907,7 +907,7 @@ HTML_FOOTER =
# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this # HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
# tag will in the future become obsolete. # tag will in the future become obsolete.
HTML_STYLESHEET = HTML_STYLESHEET = customdoxygen.css
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
# user-defined cascading style sheet that is included after the standard # user-defined cascading style sheet that is included after the standard
@ -963,7 +963,7 @@ HTML_TIMESTAMP = YES
# documentation will contain sections that can be hidden and shown after the # documentation will contain sections that can be hidden and shown after the
# page has loaded. # page has loaded.
HTML_DYNAMIC_SECTIONS = NO HTML_DYNAMIC_SECTIONS = YES
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of
# entries shown in the various tree structured indices initially; the user # entries shown in the various tree structured indices initially; the user
@ -1214,7 +1214,7 @@ MATHJAX_EXTENSIONS =
# typically be disabled. For large projects the javascript based search engine # typically be disabled. For large projects the javascript based search engine
# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
SEARCHENGINE = YES SEARCHENGINE = NO
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a PHP enabled web server instead of at the web client # implemented using a PHP enabled web server instead of at the web client