Parse Calls/ParseTrees

Signed-off-by: Username404 <w.iron.zombie@gmail.com>
This commit is contained in:
Username404 2022-01-29 12:20:42 +01:00
parent 3f75c5cfc8
commit f33aec687a
Signed by: Username404-59
GPG Key ID: 7AB361FBB257A5D1
8 changed files with 100 additions and 37 deletions

View File

@ -43,7 +43,7 @@ vector<tok> lex(const string& in)
} else goto insertToken;
}
[[unlikely]] case EOF_: --lineNumber;
case DEFINE: case LPAR: case RPAR:
case DEFINE: case LPAR: case RPAR: case COMMA:
case LBRACE: case RBRACE: case LBRACKET: case RBRACKET:
case PLUS: case HYPHEN: case LCOMP: case RCOMP:
case DOT: case DOLLAR_SIGN: case SQUOTE:

View File

@ -10,7 +10,7 @@ struct tok {
typedef Yerbacon::Exception LexerException;
enum type: const unsigned short {
UNEXPECTED = std::numeric_limits<unsigned char>::max() + 1, IDENTIFIER, NUMBER, ALPHACHAR,
EOF_ = '\0', DEFINE = '=', TAG = '#', DOLLAR_SIGN = '$', DOT = '.',
EOF_ = '\0', DEFINE = '=', TAG = '#', DOLLAR_SIGN = '$', DOT = '.', COMMA = ',',
LPAR = '(', LBRACE = '{', LBRACKET = '[', RPAR = ')',
RBRACE = '}', RBRACKET = ']',
PLUS = '+', HYPHEN = '-', DIVIDE = '/',

View File

@ -20,41 +20,27 @@ struct ParseComponent {
virtual ~ParseComponent() = default;
};
namespace StandardComponents {
struct NamedIdentifier: ParseComponent {
const string name;
explicit NamedIdentifier(string_view nameText): name(nameText) {}
};
struct Define: NamedIdentifier {
const bool final;
explicit Define(const bool& isFinal, string_view nameText): NamedIdentifier(nameText), final(isFinal) {}
explicit Define(string_view nameText): Define(false, nameText) {}
};
struct Reference: NamedIdentifier {
using NamedIdentifier::NamedIdentifier;
};
struct Class: NamedIdentifier {
using NamedIdentifier::NamedIdentifier;
};
namespace types {
struct String: ParseComponent {
const string content;
explicit String(const char* string): content(string) {}
};
}
}
struct NamedIdentifier: ParseComponent {
const string name;
explicit NamedIdentifier(string_view nameText): name(nameText) {}
};
#define IS_PARSECOMPONENT IS(ParseComponent)
class ParseTree {
class ParseTree: public ParseComponent {
mutable vector<unique_ptr<ParseComponent>> subComponents;
using array_type = decltype(subComponents);
using iterator = array_type::iterator;
using constant_iterator = array_type::const_iterator;
protected:
IS_PARSECOMPONENT
void addComponent(const T& component) const
{ subComponents.emplace_back(new T(component)); };
void addComponent(const T& component) const {
if constexpr(is_copy_constructible_v<T>) {
subComponents.emplace_back(new T(component));
} else {
static_assert(is_move_constructible_v<T>, "T is not copy-constructible or move-constructible");
subComponents.emplace_back(new T(move(const_cast<T&>(component))));
}
};
IS_PARSECOMPONENT
void addAllComponents(
const initializer_list<T>& components
@ -63,6 +49,7 @@ protected:
for (const T& current: components) addComponent<T>(current);
}
public:
inline size_t size() const { return subComponents.size(); }
inline iterator begin() const noexcept { return subComponents.begin(); }
inline constant_iterator cbegin() const noexcept { return subComponents.cbegin(); }
inline iterator end() const noexcept { return subComponents.end(); }
@ -77,7 +64,7 @@ public:
});
return filteredComponents;
}
IS(StandardComponents::NamedIdentifier)
IS(NamedIdentifier)
optional<reference_wrapper<T>> findReferenceByName(const string& name) const {
const vector<T*> identifiers = findById<T>();
for (T* identifier: identifiers) {
@ -88,16 +75,39 @@ public:
return optional<reference_wrapper<T>>();
};
inline decltype(*subComponents.data()) operator[](const unsigned int& index) const { return subComponents[index]; }
IS(StandardComponents::NamedIdentifier)
IS(NamedIdentifier)
inline auto operator[](const string& key) const { return findReferenceByName<T>(key); }
inline size_t getCompCount() const { return subComponents.size(); }
IS_PARSECOMPONENT inline void add(const T& component) { addComponent<T>(component); }
IS_PARSECOMPONENT inline void addAll(const initializer_list<T>& components) { addAllComponents<T>(components); }
IS_PARSECOMPONENT inline ParseTree& operator<<(const T& component) { add(component); return *this; }
ParseTree(): subComponents() {};
IS_PARSECOMPONENT constexpr explicit ParseTree(const T& element): ParseTree() { addComponent(element); }
IS_PARSECOMPONENT constexpr ParseTree(const initializer_list<T>& elements): ParseTree() { addAllComponents(elements); }
ParseTree(ParseTree&& parseTree) noexcept: subComponents(move(parseTree.subComponents)) {}
ParseTree(const ParseTree& parseTree) = delete;
};
#undef IS_PARSECOMPONENT
namespace StandardComponents {
struct Define: NamedIdentifier {
const bool final;
explicit Define(const bool& isFinal, string_view nameText): NamedIdentifier(nameText), final(isFinal) {}
explicit Define(string_view nameText): Define(false, nameText) {}
};
struct Reference: NamedIdentifier {
using NamedIdentifier::NamedIdentifier;
};
namespace types {
struct String: ParseComponent {
const string content;
explicit String(const char* string): content(string) {}
};
}
struct Call: ParseTree { inline explicit Call(ParseTree&& tree) noexcept: ParseTree(move(tree)) {} };
struct Class: NamedIdentifier {
using NamedIdentifier::NamedIdentifier;
};
}
#endif //YERBACON_PARSECOMPONENTS_HPP

View File

@ -58,7 +58,38 @@ namespace Parser {
parseTree << Reference(current.toktext);
}
}
break;
}
case LPAR: case LBRACE: case LBRACKET: {
const auto inverseCharacter = static_cast<tok::type>((current.toktype + 2) - (current.toktype == LPAR));
const auto closingCharacter = find_if(lexed.cbegin(), lexed.cend(), [&inverseCharacter](const tok& it){
return it.toktype == inverseCharacter;
});
if (closingCharacter != lexed.cend()) {
vector<tok> subTokens;
subTokens.reserve(distance(lexed.cbegin() + i, closingCharacter));
subTokens.assign(lexed.cbegin() + i + 1, closingCharacter);
if (current.toktype == LPAR || current.toktype == LBRACKET) {
if (subTokens.size() >= 2 && subTokens[1].toktype != RPAR) {
for (auto iterator = subTokens.cbegin(); iterator < (subTokens.cend() - 1); ++iterator) {
const auto nextIterator = iterator + 1;
if (nextIterator->toktype == COMMA) {
subTokens.erase(nextIterator);
} else throw ParsingException("Missing comma after \"" + iterator->toktext + '"');
}
}
}
switch (current.toktype) {
case LPAR: parseTree << Call(parseVector(subTokens)); break;
case LBRACE: // TODO Add structures for class/function bodies
case LBRACKET:
default: parseTree << parseVector(subTokens); break;
}
i = distance(lexed.cbegin(), closingCharacter);
} else parsingError(current, string(" is missing a closing \"").append(1, inverseCharacter) + '"', true);
break;
}
case RPAR: case RBRACE: case RBRACKET: parsingError(current, " \u27F5 Unexpected character", true);
default: break;
}
}

View File

@ -67,15 +67,33 @@ protected:
typedef function<void (const ParseTree& parsedTree, unsigned int& index)> task;
#define make_task_base(type, captures, function_body) make_pair(type_index(typeid(type)), [captures](const ParseTree& parsedTree, unsigned int& index) { const type& parseComponent = pointerAs<type>(parsedTree[index]); function_body })
#define make_task(T, F) make_task_base(T, this, F)
#define make_nonlocal_task(T, F) make_task_base(T, , F)
typedef unordered_map<type_index, task> unordered_task_map;
typedef pair<const char*, const char*> print_functions_pair;
virtual unordered_task_map getTaskMap() = 0;
virtual print_functions_pair printFunctions() = 0;
public:
const unordered_task_map& getTaskMapInstance() {
static unordered_task_map staticMap = getTaskMap();
// Default / Shared tasks:
staticMap.merge(unordered_task_map({
make_task(StandardComponents::Reference,
output << parseComponent.name;
make_task(ParseTree,
unsigned int subIndex = 0;
for (auto pointer_iterator = parseComponent.cbegin(); pointer_iterator < parseComponent.cend(); ++pointer_iterator) {
staticMap[pointer_iterator->get()->getId()](parseComponent, subIndex); ++subIndex;
if ((pointer_iterator + 1) != parseComponent.cend() && parseComponent.getId() == typeid(StandardComponents::Call)) {
output << ", ";
}
}
),
make_task_base(StandardComponents::Reference, &,
const auto print_functions = printFunctions();
output << ((parseComponent.name == "print") ? print_functions.first : (parseComponent.name == "print_line") ? print_functions.second : parseComponent.name);
),
make_task(StandardComponents::Call,
output << '(';
staticMap[typeid(ParseTree)](parsedTree, index);
output << ')';
)
}));
return staticMap;
@ -88,12 +106,11 @@ public:
throw Yerbacon::Exception("--newlines=off is not supported by the current target");
}
output.str(string());
for (unsigned int i = 0; i < tree.getCompCount(); ++i) {
for (unsigned int i = 0; i < tree.size(); ++i) {
const unique_ptr<ParseComponent>& component = tree[i];
const type_info& id = component->getId();
try {
const task& currentTask = taskMap.at(id);
currentTask(tree, i);
taskMap.at(id)(tree, i);
} catch (const out_of_range&) {
throw Yerbacon::Exception(string(
#ifndef __GNUC__
@ -141,7 +158,9 @@ shared_ptr<Target> Target::forName(string_view name, const bool newLines = true)
default: Yerbacon::exit({"\"", string(1, (char) toupper(name.at(1))).data(), name.substr(2).data(), "\" is not a valid target."});
}
#undef ADDTARGET
#undef make_nonlocal_task
#undef make_task
#undef make_task_base
return target;
}

View File

@ -3,6 +3,7 @@
using namespace StandardComponents;
struct JsTarget: Target {
print_functions_pair printFunctions() final { return make_pair("util.write", "console.log"); }
unordered_task_map getTaskMap() final {
return {
make_task(Define,

View File

@ -3,6 +3,7 @@
using namespace StandardComponents;
struct LuaTarget: Target {
print_functions_pair printFunctions() final { return make_pair("io.write", "print"); }
unordered_task_map getTaskMap() final {
return {
make_task(Define,

View File

@ -4,6 +4,7 @@ using namespace StandardComponents;
struct PyTarget: Target {
bool supportsOneLine() final { return false; }
print_functions_pair printFunctions() final { return make_pair("sys.stdout.write", "print"); }
unordered_task_map getTaskMap() final {
return {
make_task(Define, output << parseComponent.name << " = ";),