Tue, 03 Feb 2015 15:26:07 +0200
- ast: added root and macro nodes and processing of them
CMakeLists.txt | file | annotate | diff | comparison | revisions | |
src/script/ast.cpp | file | annotate | diff | comparison | revisions | |
src/script/ast.h | file | annotate | diff | comparison | revisions | |
src/script/parser.cpp | file | annotate | diff | comparison | revisions | |
src/script/parser.h | file | annotate | diff | comparison | revisions |
--- a/CMakeLists.txt Tue Feb 03 04:03:19 2015 +0200 +++ b/CMakeLists.txt Tue Feb 03 15:26:07 2015 +0200 @@ -73,6 +73,7 @@ src/editmodes/selectMode.cc src/script/parser.cpp src/script/objtype.cpp + src/script/ast.cpp ) set (LDFORGE_HEADERS @@ -109,6 +110,9 @@ src/editmodes/magicWandMode.h src/editmodes/rectangleMode.h src/editmodes/selectMode.h + src/script/parser.h + src/script/objtype.h + src/script/ast.h ) set (LDFORGE_FORMS
--- a/src/script/ast.cpp Tue Feb 03 04:03:19 2015 +0200 +++ b/src/script/ast.cpp Tue Feb 03 15:26:07 2015 +0200 @@ -1,7 +1,40 @@ #include "ast.h" -Script::AstNode::AstNode (QSharedPointer<AstNode> parent) : - m_parent (parent) +Script::Ast::BaseNode::BaseNode (NodePointer parent, NodeType type) : + m_parent (parent), + m_type (type) +{ +} + +Script::Ast::BaseNode::~BaseNode() {} + +void Script::Ast::BaseNode::dump() { + static QString tabs; + if (children().isEmpty()) + { + print (tabs + describe() + "\n"); + } + else + { + print (tabs + describe() + ":\n"); + + for (NodePointer child : children()) + { + tabs += '\t'; + child->dump(); + tabs.chop(1); + } + } } + +QString Script::Ast::RootNode::describe() const +{ + return "root"; +} + +QString Script::Ast::MacroNode::describe() const +{ + return format ("macro (%1)", m_macroName); +} \ No newline at end of file
--- a/src/script/ast.h Tue Feb 03 04:03:19 2015 +0200 +++ b/src/script/ast.h Tue Feb 03 15:26:07 2015 +0200 @@ -1,23 +1,75 @@ #pragma once #include <QVector> #include <QSharedPointer> +#include "../main.h" namespace Script { - using AstPointer = QSharedPointer<class AstNode>; - - enum AstNodeType - { - - }; - - class AstNode + namespace Ast { - public: - AstNode (AstPointer parent); + using NodePointer = QSharedPointer<class BaseNode>; + using RootPointer = QSharedPointer<class RootNode>; + using MacroPointer = QSharedPointer<class MacroNode>; + + enum NodeType + { + ROOT, + MACRO, + }; + + class BaseNode + { + public: + BaseNode (NodePointer parent, NodeType type); + virtual ~BaseNode() = 0; + + NodeType type() const { return m_type; } + NodePointer parent() const { return m_parent; } + QVector<NodePointer> children() const { return m_children; } + void addChild (NodePointer child) { m_children.append (child); } + void dump(); + virtual QString describe() const = 0; + + private: + QVector<NodePointer> m_children; + NodePointer m_parent; + NodeType m_type; + }; - private: - QVector<AstPointer> m_children; - AstPointer m_parent; - }; + class RootNode : public BaseNode + { + public: + RootNode() : BaseNode (NodePointer(), ROOT) {} + QString describe() const override; + }; + + class MacroNode : public BaseNode + { + public: + MacroNode (NodePointer parent, QString macroName) : + BaseNode (parent, MACRO), + m_macroName (macroName) {} + + QString macroName() const { return m_macroName; } + QString describe() const override; + + private: + QString m_macroName; + }; + + template<typename T, typename... Args> + QSharedPointer<T> spawn (NodePointer parent, Args&&... args) + { + static_assert (std::is_base_of<BaseNode, T>::value, + "Script::Ast::spawn can only be used for AST types."); + QSharedPointer<T> ast (new T (parent, args...)); + parent->addChild (ast); + return ast; + } + + inline RootPointer spawnRoot() + { + return RootPointer (new RootNode()); + } + } }
--- a/src/script/parser.cpp Tue Feb 03 04:03:19 2015 +0200 +++ b/src/script/parser.cpp Tue Feb 03 15:26:07 2015 +0200 @@ -89,11 +89,25 @@ { preprocess(); m_state.reset(); + m_astRoot = Ast::spawnRoot(); - while (next (TOK_Any)) + while (next()) { - print ("token: %1 (%2)\n", state().token.text, TokenNames[state().token.type]); + if (m_state.token.type == TOK_Semicolon) + continue; + + tokenMustBe (TOK_Macro); + mustGetNext (TOK_Symbol); + Ast::MacroPointer macroAst = Ast::spawn<Ast::MacroNode> (m_astRoot, state().token.text); + mustGetNext (TOK_Semicolon); + + do + { + mustGetNext(); + } while (m_state.token.type != TOK_EndMacro); } + + m_astRoot->dump(); } // @@ -571,4 +585,17 @@ unread(); return identifier; -} \ No newline at end of file +} + +// +// ------------------------------------------------------------------------------------------------- +// +void Script::Parser::tokenMustBe (TokenType desiredType) +{ + if (m_state.token.type != desiredType) + { + scriptError ("expected %1, got %2", + TokenNames[desiredType], + TokenNames[m_state.token.type]); + } +}
--- a/src/script/parser.h Tue Feb 03 04:03:19 2015 +0200 +++ b/src/script/parser.h Tue Feb 03 15:26:07 2015 +0200 @@ -141,6 +141,7 @@ void skipSpace(); bool isAtEnd() const { return m_state.position >= m_data.length(); } bool tryMatch (const char* text, bool caseSensitive); + void tokenMustBe (TokenType desiredType); template<typename... Args> void scriptError (QString text, Args... args) @@ -153,7 +154,7 @@ QByteArray m_data; QVector<int> m_lineEndings; SavedState m_state; - AstNode* m_astRoot; + Ast::RootPointer m_astRoot; Token m_rejectedToken; void parseString();