# HG changeset patch # User Teemu Piippo # Date 1422969967 -7200 # Node ID d1ac217c9165e8ce99d9227dd00c8b95f77eb005 # Parent e15a577a0bfe46f3e6f1cfd031801de08605eada - ast: added root and macro nodes and processing of them diff -r e15a577a0bfe -r d1ac217c9165 CMakeLists.txt --- 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 diff -r e15a577a0bfe -r d1ac217c9165 src/script/ast.cpp --- 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 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 diff -r e15a577a0bfe -r d1ac217c9165 src/script/ast.h --- 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 #include +#include "../main.h" namespace Script { - using AstPointer = QSharedPointer; - - enum AstNodeType - { - - }; - - class AstNode + namespace Ast { - public: - AstNode (AstPointer parent); + using NodePointer = QSharedPointer; + using RootPointer = QSharedPointer; + using MacroPointer = QSharedPointer; + + 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 children() const { return m_children; } + void addChild (NodePointer child) { m_children.append (child); } + void dump(); + virtual QString describe() const = 0; + + private: + QVector m_children; + NodePointer m_parent; + NodeType m_type; + }; - private: - QVector 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 + QSharedPointer spawn (NodePointer parent, Args&&... args) + { + static_assert (std::is_base_of::value, + "Script::Ast::spawn can only be used for AST types."); + QSharedPointer ast (new T (parent, args...)); + parent->addChild (ast); + return ast; + } + + inline RootPointer spawnRoot() + { + return RootPointer (new RootNode()); + } + } } diff -r e15a577a0bfe -r d1ac217c9165 src/script/parser.cpp --- 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 (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]); + } +} diff -r e15a577a0bfe -r d1ac217c9165 src/script/parser.h --- 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 void scriptError (QString text, Args... args) @@ -153,7 +154,7 @@ QByteArray m_data; QVector m_lineEndings; SavedState m_state; - AstNode* m_astRoot; + Ast::RootPointer m_astRoot; Token m_rejectedToken; void parseString();