summaryrefslogtreecommitdiffhomepage
path: root/dev/LibCompiler/Parser.h
blob: 6baff7e9e370e98b4d491211bcd0cd2c5a7c979f (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
/* -------------------------------------------

  Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved

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

#pragma once

#include <LibCompiler/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, 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

    SyntaxLeaf() = default;

    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(std::string haystack, 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(std::string haystack, 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