More documentaaaaation.
parent
837d4c4bce
commit
058a18c612
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
#include "Object.h"
|
|
||||||
|
|
||||||
Object::Object()
|
|
||||||
{
|
|
||||||
number_value = 0;
|
|
||||||
//ctor
|
|
||||||
}
|
|
||||||
|
|
||||||
Object::~Object()
|
|
||||||
{
|
|
||||||
//dtor
|
|
||||||
}
|
|
|
@ -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
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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_ */
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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;">
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue