|
|
|
#ifndef JSPARSER_H
|
|
|
|
#define JSPARSER_H
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
// for gcc & shared_ptr
|
|
|
|
#include <iostream>
|
|
|
|
#include <memory>
|
|
|
|
|
|
|
|
|
|
|
|
// Internal JS types: String, Number, Function, Array, Object
|
|
|
|
// blocks/scopes?
|
|
|
|
class js_internal_storage {
|
|
|
|
public:
|
|
|
|
// toBool
|
|
|
|
// toString
|
|
|
|
// toNumber
|
|
|
|
// toFunction
|
|
|
|
// toArray
|
|
|
|
// toObject
|
|
|
|
// toReference
|
|
|
|
virtual ~js_internal_storage() = default;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_scope {
|
|
|
|
public:
|
|
|
|
js_scope *parent;
|
|
|
|
// what do we need children for?
|
|
|
|
// a callstack only includes it's parents (in JS?)
|
|
|
|
std::vector<js_scope> children;
|
|
|
|
js_scope() {
|
|
|
|
parent = nullptr;
|
|
|
|
}
|
|
|
|
std::map<std::string, std::string> variables;
|
|
|
|
std::map<std::string, js_internal_storage *> data;
|
|
|
|
// maybe a vector of resolve on execution assignments...
|
|
|
|
// feel like we need an instruction pointer...
|
|
|
|
// esp. for loops
|
|
|
|
// but how we address tokens, by index?
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_bool : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
bool value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_string : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
std::string value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_number : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
signed long value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_function : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
std::vector<std::string> tokens;
|
|
|
|
js_scope scope;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_array : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
std::vector<js_internal_storage> value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_object : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
// I think 2nd needs to be a pointer...
|
|
|
|
std::map<std::string, js_internal_storage *> value;
|
|
|
|
};
|
|
|
|
|
|
|
|
class js_reference : public js_internal_storage {
|
|
|
|
public:
|
|
|
|
js_internal_storage *ptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
bool doAssignment(js_scope &rootScope, std::string token);
|
|
|
|
size_t parseFunctionBody(std::string source, size_t start);
|
|
|
|
size_t getNextExpression(const std::string source, const size_t start);
|
|
|
|
|
|
|
|
class JavaScript {
|
|
|
|
public:
|
|
|
|
void clear() {
|
|
|
|
tokens.clear();
|
|
|
|
rootScope.parent = nullptr;
|
|
|
|
rootScope.children.clear();
|
|
|
|
rootScope.variables.clear();
|
|
|
|
}
|
|
|
|
// each token is one statement
|
|
|
|
std::vector<std::string> tokens;
|
|
|
|
// we're just settings the rootScope.variables
|
|
|
|
std::vector<std::string> definitions; // all var declarations and their expressions
|
|
|
|
std::vector<std::string> instructions; // then a list of all remaining expressions and function calls
|
|
|
|
js_scope rootScope;
|
|
|
|
};
|
|
|
|
|
|
|
|
js_internal_storage *parseExpression(js_scope &rootScope, std::string token);
|
|
|
|
void parseArray(js_scope &rootScope, std::string token);
|
|
|
|
void parseJSON(js_scope &rootScope, std::string token);
|
|
|
|
|
|
|
|
// this is no members could all be static
|
|
|
|
class JSParser {
|
|
|
|
public:
|
|
|
|
//std::shared_ptr<JavaScript> parse(const std::string &javascript) const;
|
|
|
|
void parseTokens(const std::vector<std::string> &tokens, js_scope *scope) const;
|
|
|
|
std::vector<std::string> getTokens(const std::string &source) const;
|
|
|
|
std::shared_ptr<JavaScript> append(std::shared_ptr<JavaScript> &destination, const std::shared_ptr<JavaScript> &source) const;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|