1 #pragma once
2 #include "Tokenizer.h"
3 #include "Core/Expression.h"
4 #include "Commands/CommandSequence.h"
5 #include "DirectivesParser.h"
6 #include <set>
7 #include <map>
8 #include <unordered_map>
9 #include "Core/Common.h"
10 
11 struct AssemblyTemplateArgument
12 {
13 	const wchar_t* variableName;
14 	std::wstring value;
15 };
16 
17 struct ParserMacro
18 {
19 	std::wstring name;
20 	std::vector<std::wstring> parameters;
21 	std::set<std::wstring> labels;
22 	std::vector<Token> content;
23 	size_t counter;
24 };
25 
26 enum class ConditionalResult { Unknown, True, False };
27 
28 class Parser
29 {
30 public:
31 	Parser();
atEnd()32 	bool atEnd() { return entries.back().tokenizer->atEnd(); }
33 
34 	void addEquation(const Token& start, const std::wstring& name, const std::wstring& value);
35 
36 	Expression parseExpression();
37 	bool parseExpressionList(std::vector<Expression>& list, int min = -1, int max = -1);
38 	bool parseIdentifier(std::wstring& dest);
39 	std::unique_ptr<CAssemblerCommand> parseCommand();
40 	std::unique_ptr<CAssemblerCommand> parseCommandSequence(wchar_t indicator = 0, const std::initializer_list<const wchar_t*> terminators = {});
41 	std::unique_ptr<CAssemblerCommand> parseFile(TextFile& file, bool virtualFile = false);
42 	std::unique_ptr<CAssemblerCommand> parseString(const std::wstring& text);
43 	std::unique_ptr<CAssemblerCommand> parseTemplate(const std::wstring& text, const std::initializer_list<AssemblyTemplateArgument> variables = {});
44 	std::unique_ptr<CAssemblerCommand> parseDirective(const DirectiveMap &directiveSet);
45 	bool matchToken(TokenType type, bool optional = false);
46 
getTokenizer()47 	Tokenizer* getTokenizer() { return entries.back().tokenizer; };
48 	const Token& peekToken(int ahead = 0) { return getTokenizer()->peekToken(ahead); };
nextToken()49 	const Token& nextToken() { return getTokenizer()->nextToken(); };
eatToken()50 	void eatToken() { getTokenizer()->eatToken(); };
eatTokens(int num)51 	void eatTokens(int num) { getTokenizer()->eatTokens(num); };
52 
53 	void pushConditionalResult(ConditionalResult cond);
popConditionalResult()54 	void popConditionalResult() { conditionStack.pop_back(); };
isInsideTrueBlock()55 	bool isInsideTrueBlock() { return conditionStack.back().inTrueBlock; }
isInsideUnknownBlock()56 	bool isInsideUnknownBlock() { return conditionStack.back().inUnknownBlock; }
57 
58 	template <typename... Args>
printError(const Token & token,const wchar_t * text,const Args &...args)59 	void printError(const Token& token, const wchar_t* text, const Args&... args)
60 	{
61 		errorLine = token.line;
62 		Global.FileInfo.LineNumber = (int) token.line;
63 		std::wstring errorText = formatString(text,args...);
64 		Logger::printError(Logger::Error,errorText);
65 		error = true;
66 	}
67 
hasError()68 	bool hasError() { return error; }
69 	void updateFileInfo();
70 protected:
clearError()71 	void clearError() { error = false; }
72 	std::unique_ptr<CAssemblerCommand> handleError();
73 
74 	std::unique_ptr<CAssemblerCommand> parse(Tokenizer* tokenizer, bool virtualFile, const std::wstring& name = L"");
75 	std::unique_ptr<CAssemblerCommand> parseLabel();
76 	bool checkEquLabel();
77 	bool checkMacroDefinition();
78 	std::unique_ptr<CAssemblerCommand> parseMacroCall();
79 
80 	struct FileEntry
81 	{
82 		Tokenizer* tokenizer;
83 		bool virtualFile;
84 		int fileNum;
85 		int previousCommandLine;
86 	};
87 
88 	std::vector<FileEntry> entries;
89 	std::map<std::wstring,ParserMacro> macros;
90 	std::set<std::wstring> macroLabels;
91 	bool initializingMacro;
92 	bool error;
93 	size_t errorLine;
94 
95 	bool overrideFileInfo;
96 	int overrideFileNum;
97 	int overrideLineNum;
98 
99 	struct ConditionInfo
100 	{
101 		bool inTrueBlock;
102 		bool inUnknownBlock;
103 	};
104 
105 	std::vector<ConditionInfo> conditionStack;
106 };
107 
108 struct TokenSequenceValue
109 {
TokenSequenceValueTokenSequenceValue110 	TokenSequenceValue(const wchar_t* text)
111 	{
112 		type = TokenType::Identifier;
113 		textValue = text;
114 	}
115 
TokenSequenceValueTokenSequenceValue116 	TokenSequenceValue(int64_t num)
117 	{
118 		type = TokenType::Integer;
119 		intValue = num;
120 	}
121 
TokenSequenceValueTokenSequenceValue122 	TokenSequenceValue(double num)
123 	{
124 		type = TokenType::Float;
125 		floatValue = num;
126 	}
127 
128 
129 	TokenType type;
130 	union
131 	{
132 		const wchar_t* textValue;
133 		int64_t intValue;
134 		double floatValue;
135 	};
136 };
137 
138 using TokenSequence = std::initializer_list<TokenType>;
139 using TokenValueSequence = std::initializer_list<TokenSequenceValue>;
140 
141 class TokenSequenceParser
142 {
143 public:
144 	void addEntry(int result, TokenSequence tokens, TokenValueSequence values);
145 	bool parse(Parser& parser, int& result);
getEntryCount()146 	size_t getEntryCount() { return entries.size(); }
147 private:
148 	struct Entry
149 	{
150 		std::vector<TokenType> tokens;
151 		std::vector<TokenSequenceValue> values;
152 		int result;
153 	};
154 
155 	std::vector<Entry> entries;
156 };
157