summaryrefslogtreecommitdiffhomepage
path: root/dev/LibCompiler/Parser.h
blob: 779bf36e15006322890da9e86d336b34f7a86e19 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/* -------------------------------------------

	Copyright (C) 2024 Amlal EL Mahrouss, all rights reserved

------------------------------------------- */

#pragma once

#include <LibCompiler/AAL/AssemblyInterface.h>

namespace LibCompiler
{
	inline auto kInvalidFrontend = "NA";

	/// @brief Compiler backend, implements a frontend, such as C, C++...
	/// See Toolchain, for some examples.
	class ICompilerFrontend
	{
	public:
		explicit ICompilerFrontend() = default;
		virtual ~ICompilerFrontend() = default;

		LIBCOMPILER_COPY_DEFAULT(ICompilerFrontend);

		// NOTE: cast this to your user defined ast.
		typedef void* AstType;

		//! @brief Compile a syntax tree ouf of the text.
		//! Also takes the source file name for metadata.

		virtual bool Compile(std::string text, const std::string file) = 0;

		//! @brief What language are we dealing with?
		virtual const char* Language()
		{
			return kInvalidFrontend;
		}

		virtual bool IsValid()
		{
			return strcmp(this->Language(), kInvalidFrontend) > 0;
		}
	};

	struct SyntaxLeafList;
	struct SyntaxLeafList;
	struct CompilerKeyword;

	/// we want to do that because to separate keywords.
	enum KeywordKind
	{
		kKeywordKindNamespace,
		kKeywordKindFunctionStart,
		kKeywordKindFunctionEnd,
		kKeywordKindVariable,
		kKeywordKindVariablePtr,
		kKeywordKindType,
		kKeywordKindTypePtr,
		kKeywordKindExpressionBegin,
		kKeywordKindExpressionEnd,
		kKeywordKindArgSeparator,
		kKeywordKindBodyStart,
		kKeywordKindBodyEnd,
		kKeywordKindClass,
		kKeywordKindPtrAccess,
		kKeywordKindAccess,
		kKeywordKindIf,
		kKeywordKindElse,
		kKeywordKindElseIf,
		kKeywordKindVariableAssign,
		kKeywordKindVariableDec,
		kKeywordKindVariableInc,
		kKeywordKindConstant,
		kKeywordKindTypedef,
		kKeywordKindEndInstr,
		kKeywordKindSpecifier,
		kKeywordKindInvalid,
		kKeywordKindReturn,
		kKeywordKindCommentInline,
		kKeywordKindCommentMultiLineStart,
		kKeywordKindCommentMultiLineEnd,
		kKeywordKindEq,
		kKeywordKindNotEq,
		kKeywordKindGreaterEq,
		kKeywordKindLessEq,
		kKeywordKindPtr,
	};

	/// \brief Compiler keyword information struct.
	struct CompilerKeyword
	{
		std::string keyword_name;
		KeywordKind keyword_kind = kKeywordKindInvalid;
	};
	struct SyntaxLeafList final
	{
		struct SyntaxLeaf final
		{
			Int32 fUserType;
#ifdef LC_USE_STRUCTS
			CompilerKeyword fUserData;
#else
			std::string fUserData;
#endif

			std::string		   fUserValue;
			struct SyntaxLeaf* fNext;
		};

		std::vector<SyntaxLeaf> fLeafList;
		SizeType				fNumLeafs;

		size_t SizeOf()
		{
			return fNumLeafs;
		}
		std::vector<SyntaxLeaf>& Get()
		{
			return fLeafList;
		}
		SyntaxLeaf& At(size_t index)
		{
			return fLeafList[index];
		}
	};

	/// find the perfect matching word in a haystack.
	/// \param haystack base string
	/// \param needle the string we search for.
	/// \return if we found it or not.
	inline bool find_word(const std::string& haystack,
						  const std::string& needle) noexcept
	{
		auto index = haystack.find(needle);

		// check for needle validity.
		if (index == std::string::npos)
			return false;

		// declare lambda
		auto not_part_of_word = [&](int index) {
			if (std::isspace(haystack[index]) || std::ispunct(haystack[index]))
				return true;

			if (index <= 0 || index >= haystack.size())
				return true;

			return false;
		};

		return not_part_of_word(index - 1) && not_part_of_word(index + needle.size());
	}

	/// find a word within strict conditions and returns a range of it.
	/// \param haystack
	/// \param needle
	/// \return position of needle.
	inline std::size_t find_word_range(const std::string& haystack,
									   const std::string& needle) noexcept
	{
		auto index = haystack.find(needle);

		// check for needle validity.
		if (index == std::string::npos)
			return false;

		if (!isalnum((haystack[index + needle.size() + 1])) &&
			!isdigit(haystack[index + needle.size() + 1]) &&
			!isalnum((haystack[index - needle.size() - 1])) &&
			!isdigit(haystack[index - needle.size() - 1]))
		{
			return index;
		}

		return false;
	}
} // namespace LibCompiler