src/parser.h

changeset 119
bdf8d46c145f
child 133
dbbdb870c835
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/parser.h	Sun Mar 30 21:51:23 2014 +0300
@@ -0,0 +1,258 @@
+/*
+	Copyright 2012-2014 Santeri Piippo
+	All rights reserved.
+
+	Redistribution and use in source and binary forms, with or without
+	modification, are permitted provided that the following conditions
+	are met:
+
+	1. Redistributions of source code must retain the above copyright
+	   notice, this list of conditions and the following disclaimer.
+	2. Redistributions in binary form must reproduce the above copyright
+	   notice, this list of conditions and the following disclaimer in the
+	   documentation and/or other materials provided with the distribution.
+	3. The name of the author may not be used to endorse or promote products
+	   derived from this software without specific prior written permission.
+
+	THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+	IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+	OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+	IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+	INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+	DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+	THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+	(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+	THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef BOTC_PARSER_H
+#define BOTC_PARSER_H
+
+#include <stdio.h>
+#include "main.h"
+#include "commands.h"
+#include "lexerScanner.h"
+#include "tokens.h"
+
+class DataBuffer;
+class Lexer;
+class Variable;
+
+// ============================================================================
+// Mark types
+//
+named_enum MarkType
+{
+	MARK_Label,
+	MARK_If,
+	MARK_Internal, // internal structures
+};
+
+// ============================================================================
+// Scope types
+//
+named_enum ScopeType
+{
+	SCOPE_Unknown,
+	SCOPE_If,
+	SCOPE_While,
+	SCOPE_For,
+	SCOPE_Do,
+	SCOPE_Switch,
+	SCOPE_Else,
+};
+
+named_enum AssignmentOperator
+{
+	ASSIGNOP_Assign,
+	ASSIGNOP_Add,
+	ASSIGNOP_Subtract,
+	ASSIGNOP_Multiply,
+	ASSIGNOP_Divide,
+	ASSIGNOP_Modulus,
+	ASSIGNOP_Increase,
+	ASSIGNOP_Decrease,
+};
+
+named_enum Writability
+{
+	WRITE_Mutable,		// normal read-many-write-many variable
+	WRITE_Const,		// write-once const variable
+	WRITE_Constexpr,	// const variable whose value is known to compiler
+};
+
+// =============================================================================
+//
+// Parser mode: where is the parser at?
+//
+named_enum ParserMode
+{
+	PARSERMODE_TopLevel,	// at top level
+	PARSERMODE_Event,		// inside event definition
+	PARSERMODE_MainLoop,	// inside mainloop
+	PARSERMODE_Onenter,		// inside onenter
+	PARSERMODE_Onexit,		// inside onexit
+};
+
+// ============================================================================
+//
+struct Variable
+{
+	String			name;
+	String			statename;
+	DataType		type;
+	int				index;
+	Writability		writelevel;
+	int				value;
+	String			origin;
+	bool			isarray;
+
+	inline bool IsGlobal() const
+	{
+		return statename.isEmpty();
+	}
+};
+
+// ============================================================================
+//
+struct CaseInfo
+{
+	ByteMark*		mark;
+	int				number;
+	DataBuffer*		data;
+};
+
+// ============================================================================
+//
+// Meta-data about scopes
+//
+struct ScopeInfo
+{
+	ByteMark*					mark1;
+	ByteMark*					mark2;
+	ScopeType					type;
+	DataBuffer*					buffer1;
+	int							globalVarIndexBase;
+	int							globalArrayIndexBase;
+	int							localVarIndexBase;
+
+	// switch-related stuff
+	List<CaseInfo>::Iterator	casecursor;
+	List<CaseInfo>				cases;
+	List<Variable*>				localVariables;
+	List<Variable*>				globalVariables;
+	List<Variable*>				globalArrays;
+};
+
+// ============================================================================
+//
+class BotscriptParser
+{
+	PROPERTY (public, bool, isReadOnly, setReadOnly, STOCK_WRITE)
+
+	public:
+		enum EReset
+		{
+			eNoReset,
+			SCOPE_Reset,
+		};
+
+		BotscriptParser();
+		~BotscriptParser();
+		void					parseBotscript (String fileName);
+		DataBuffer*				parseCommand (CommandInfo* comm);
+		DataBuffer*				parseAssignment (Variable* var);
+		AssignmentOperator		parseAssignmentOperator();
+		String					parseFloat();
+		void					pushScope (EReset reset = SCOPE_Reset);
+		DataBuffer*				parseStatement();
+		void					addSwitchCase (DataBuffer* b);
+		void					checkToplevel();
+		void					checkNotToplevel();
+		bool					tokenIs (ETokenType a);
+		String					getTokenString();
+		String					describePosition() const;
+		void					writeToFile (String outfile);
+		Variable*				findVariable (const String& name);
+		bool					isInGlobalState() const;
+		void					suggestHighestVarIndex (bool global, int index);
+		int						getHighestVarIndex (bool global);
+
+		inline ScopeInfo& scope (int offset)
+		{
+			return m_scopeStack[m_scopeCursor - offset];
+		}
+
+		inline int numEvents() const
+		{
+			return m_numEvents;
+		}
+
+		inline int numStates() const
+		{
+			return m_numStates;
+		}
+
+	private:
+		// The main buffer - the contents of this is what we
+		// write to file after parsing is complete
+		DataBuffer*		m_mainBuffer;
+
+		// onenter buffer - the contents of the onenter {} block
+		// is buffered here and is merged further at the end of state
+		DataBuffer*		m_onenterBuffer;
+
+		// Mainloop buffer - the contents of the mainloop {} block
+		// is buffered here and is merged further at the end of state
+		DataBuffer*		m_mainLoopBuffer;
+
+		// Switch buffer - switch case data is recorded to this
+		// buffer initially, instead of into main buffer.
+		DataBuffer*		m_switchBuffer;
+
+		Lexer*			m_lexer;
+		int				m_numStates;
+		int				m_numEvents;
+		ParserMode		m_currentMode;
+		String			m_currentState;
+		bool			m_isStateSpawnDefined;
+		bool			m_gotMainLoop;
+		int				m_scopeCursor;
+		bool			m_isElseAllowed;
+		int				m_highestGlobalVarIndex;
+		int				m_highestStateVarIndex;
+		int				m_numWrittenBytes;
+		List<ScopeInfo>	m_scopeStack;
+		int				m_zandronumVersion;
+		bool			m_defaultZandronumVersion;
+
+		DataBuffer*		currentBuffer();
+		void			parseStateBlock();
+		void			parseEventBlock();
+		void			parseMainloop();
+		void			parseOnEnterExit();
+		void			parseVar();
+		void			parseGoto();
+		void			parseIf();
+		void			parseElse();
+		void			parseWhileBlock();
+		void			parseForBlock();
+		void			parseDoBlock();
+		void			parseSwitchBlock();
+		void			parseSwitchCase();
+		void			parseSwitchDefault();
+		void			parseBreak();
+		void			parseContinue();
+		void			parseBlockEnd();
+		void			parseLabel();
+		void			parseEventdef();
+		void			parseFuncdef();
+		void			parseUsing();
+		void			writeMemberBuffers();
+		void			writeStringTable();
+		DataBuffer*		parseExpression (DataType reqtype, bool fromhere = false);
+		DataHeader		getAssigmentDataHeader (AssignmentOperator op, Variable* var);
+};
+
+#endif // BOTC_PARSER_H

mercurial