diff --git a/compiler/ast/ast.cc b/compiler/ast/ast.cc index ee9d90e..ed2a3ce 100644 --- a/compiler/ast/ast.cc +++ b/compiler/ast/ast.cc @@ -4,4 +4,4 @@ #include "compiler/ast/ast.h" -/// TODO: AST \ No newline at end of file +/// \todo AST \ No newline at end of file diff --git a/compiler/compiler.cc b/compiler/compiler.cc index 36cdc06..1d391ee 100644 --- a/compiler/compiler.cc +++ b/compiler/compiler.cc @@ -17,7 +17,7 @@ namespace Aq { Compiler::Compiler(const char* filename) { - /// TODO(Aq::Compiler): For testing purposes only, modifications will be made + /// \todo Aq::Compiler: For testing purposes only, modifications will be made /// after other components have been developed. auto start = std::chrono::high_resolution_clock::now(); std::ifstream file; @@ -40,7 +40,7 @@ Compiler::Compiler(const char* filename) { Token token; while (true) { lexer.LexToken(token); - if (token.type == Token::Type::NONE || lexer.IsReadEnd()) { + if (lexer.IsReadEnd()) { break; } } diff --git a/compiler/compiler.h b/compiler/compiler.h index 57eda95..28695c0 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -8,31 +8,197 @@ #include namespace Aq { +/// \class Compiler +/// \brief Compile the file to bytecode class Compiler { public: + /// \fn Compiler + /// \brief compile the file + /// \param filename const char* Type Compiler(const char* filename); ~Compiler(); private: + /// \brief The source code to be analyzed. char* buffer_ptr_; + /// \class Lexer + /// \brief The `Lexer` class performs the first stage of a compiler's + /// processing pipeline: lexical analysis. It takes raw source code as input + /// and transforms it into a sequence of meaningful tokens, which serve as the + /// input for subsequent stages, such as parsing. + /// \details + /// - **Input**: The lexer accepts source code written in a specific + /// programming language, usually provided as a character stream or an input + /// file. + /// - **Tokenization**: It scans the input character-by-character, identifying + /// and categorizing lexemes (sequences of characters with a distinct meaning) + /// according to the language's syntax rules. These lexemes are then converted + /// into discrete tokens, each consisting of a token type (e.g., identifier, + /// keyword, operator, literal) and an optional associated value. class Lexer; + + /// \class Parser + /// \brief The `Parser` class constitutes the second phase of a compiler or + /// interpreter's processing pipeline, following lexical analysis. Its primary + /// responsibility is to construct an Abstract Syntax Tree (AST) from the + /// token stream produced by the `Lexer`. + /// \details + /// - **Input**: The parser receives a well-formed sequence of tokens, + /// typically generated by a `Lexer` instance, representing the analyzed + /// source code. + /// - **Syntax Analysis**: It applies context-free grammar rules defined for + /// the target programming language to validate the token sequence's + /// structural correctness. This involves recognizing higher-level language + /// constructs (such as expressions, statements, blocks, and declarations), + /// ensuring they adhere to the prescribed syntactic organization. class Parser; + + /// \class Pair + /// \brief The `Pair` template class encapsulates two heterogeneous objects, + /// `T1` and `T2`, into a single entity. It serves as a convenient way to + /// associate and manipulate two related values together, especially when + /// there is no inherent hierarchical relationship between them. + /// \details + /// - **Template Parameters**: + /// - `T1`: The type of the first component (or "first" value) of the pair. + /// - `T2`: The type of the second component (or "second" value) of the + /// pair. + /// - **Member Variables**: + /// - `first`: An instance of type `T1`, representing the first component of + /// the pair. + /// - `second`: An instance of type `T2`, representing the second component + /// of the pair. + /// - **Construction**: Pairs can be constructed explicitly by specifying both + /// `T1` and `T2` values, or implicitly through type inference when + /// initializing with an initializer list or brace-enclosed values. + /// - **Accessors**: The individual components of the pair can be accessed + /// directly via the public `first` and `second` members. + /// \tparam T1 The type of the first value stored in the pair. + /// \tparam T2 The type of the second value stored in the pair. template struct Pair; + + /// \class HashMap + /// \brief Stores ValueType in hash map + /// \details + /// - **Key Type**: The key is of type `std::string`, allowing string-based + /// lookup for stored elements. + /// - **Value Type**: The value associated with each key is of the template + /// parameter type `ValueType`. + /// Users can instantiate `HashMap` with any desired value type to suit + /// their specific use case. + /// - **Hash-Based Storage**: Internally, the class employs a hash map + /// implementation (e.g., `std::unordered_map`) + /// to store and organize key-value pairs. Hashing ensures constant-time + /// average complexity for most operations, making `HashMap` particularly + /// suitable for large datasets where fast access is crucial. + /// - **Operations**: + /// - **Insertion**: New key-value pairs can be inserted into the map using + /// appropriate member functions. + /// - **Retrieval**: Given a key, users can efficiently retrieve the + /// corresponding value. + /// - **Deletion**: Individual entries or entire ranges of entries can be + /// removed from the map. + /// - **Iteration**: The container supports iteration over its elements, + /// enabling traversal or modification of all stored key-value pairs. + /// \tparam ValueType template class HashMap; + + /// \class LinkedList + /// \brief The `LinkedList` template class implements a linear collection of + /// nodes, where each node contains a value of type `DataType` and one or two + /// pointers to adjacent nodes. Linked lists offer dynamic size, efficient + /// insertion/deletion at arbitrary positions, and sequential access to + /// elements. + /// \details + /// - **Template Parameter**: + /// - `DataType`: The type of the data stored in each node of the list. + /// - **Node Structure**: + /// - Depending on whether the list is singly or doubly linked, nodes + /// contain a `DataType` value and either one (`next`) or two (`next` and + /// `prev`) pointers to other nodes. + /// - **Methods**: + /// - **Construction/Destruction**: The list can be created empty or + /// initialized with a range of elements. Destruction recursively frees all + /// nodes in the list. + /// - **Element Access**: + /// - `Size()`: Returns the number of elements in the list. + /// - **Modifiers**: + /// - `Insert()`, `Remove()`: Inserts/Removes elements at arbitrary + /// positions. + /// - `Clear()`: Removes all elements from the list. + /// - **Traversal/Iteration**: Supports forward iteration over elements + /// using iterators or ranged-for loops. + /// - **Performance Characteristics**: + /// - **Time Complexity**: + /// - Accessing an element by index: O(n) + /// - Insertion/Deletion at beginning/end: O(1) (amortized) + /// - Insertion/Deletion at arbitrary position: O(n) + /// - Traversal: O(n) + /// \tparam DataType The type of the data stored in each node of the linked + /// list. template class LinkedList; + + /// \class DynArray + /// \brief The `DynArray` template class provides a contiguous memory buffer + /// capable of holding elements of type `ArrayType`. It combines the + /// performance benefits of traditional arrays (constant-time random access) + /// with the flexibility of dynamically resizing to accommodate varying + /// numbers of elements. + /// \details + /// - **Template Parameter**: + /// - `ArrayType`: The type of the data stored in the dynamic array. + /// - **Memory Management**: + /// - The array internally manages its own memory, automatically growing or + /// shrinking as needed to accommodate changes in the number of stored + /// elements. + /// - **Methods**: + /// - **Construction/Destruction**: The array can be created with an initial + /// capacity or default-constructed with zero elements. Destruction releases + /// the underlying memory. + /// - **Size**: + /// - `Size()`: Returns the current number of elements in the array. + /// - **Element Access**: + /// - `operator[]`: Allows direct read/write access to elements by index + /// (bounds-checked in debug builds). + /// - **Modifiers**: + /// - `Insert()`, `Remove()`: Inserts/Removes elements at arbitrary + /// positions, shifting subsequent elements as needed. + /// - `Resize()`: Explicitly sets the number of elements in the array, + /// either truncating or appending default-constructed elements. + /// - `Clear()`: Removes all elements from the array, resetting its size + /// to zero. + /// - **Iterators**: Supports bidirectional iteration over elements using + /// iterator or ranged-for loops. + /// - **Performance Characteristics**: + /// - **Time Complexity**: + /// - Accessing an element by index: O(1) + /// - Insertion/Deletion at end: amortized O(1) + /// - Insertion/Deletion at arbitrary position: O(n) + /// - Traversal: O(n) + /// \tparam ArrayType The type of the data stored in the dynamic array. template class DynArray; + + /// \class TokenMap + /// \brief The `TokenMap` class serves as an efficient data structure for + /// associating unique tokens, typically strings or integer values + /// representing lexemes in the source code, + /// with their corresponding token kinds. This mapping is crucial for + /// compilers, interpreters, and other language processing tools that require + /// quick lookups of token types during lexical analysis or parsing stages. class TokenMap; + + /// \class Token + /// \brief Stores token information class Token; - class Ast; - /// Will be replaced by HashMap. - template - class LexMap; + /// \class Ast + /// \brief Stores ast information + class Ast; }; } // namespace Aq diff --git a/compiler/dyn_array/dyn_array.cc b/compiler/dyn_array/dyn_array.cc index cc5178e..583dd12 100644 --- a/compiler/dyn_array/dyn_array.cc +++ b/compiler/dyn_array/dyn_array.cc @@ -83,6 +83,22 @@ std::size_t Compiler::DynArray::Size() const { return size_; } +template +void Compiler::DynArray::Remove(std::size_t index) { + for (std::size_t i = index; i < size_ - 1; ++i) { + data_[i] = data_[i + 1]; + } + --size_; +} + +template +void Compiler::DynArray::Clear() { + delete[] data_; + data_ = nullptr; + capacity_ = 0; + size_ = 0; +} + template Compiler::DynArray::Iterator::Iterator(DynArray* array, std::size_t index) @@ -213,4 +229,15 @@ bool Compiler::DynArray::Iterator::operator>=( return index_ >= other.index_; } +template +typename Compiler::DynArray::Iterator +Compiler::DynArray::Begin() { + return Iterator(this, 0); +} + +template +typename Compiler::DynArray::Iterator +Compiler::DynArray::End() { + return Iterator(this, size_); +} } // namespace Aq \ No newline at end of file diff --git a/compiler/dyn_array/dyn_array.h b/compiler/dyn_array/dyn_array.h index 51e9b7d..0f55c0a 100644 --- a/compiler/dyn_array/dyn_array.h +++ b/compiler/dyn_array/dyn_array.h @@ -14,39 +14,56 @@ namespace Aq { template class Compiler::DynArray { public: + /// \brief Creates and initialize a dynamic array. The default capacity is 1. + /// \param InitCapacity DynArray(std::size_t InitCapacity = 1); ~DynArray(); + /// \bug These functions have many bugs when called. + /// \todo Fix these bugs. DynArray(const DynArray&) = default; DynArray(DynArray&&) noexcept = default; DynArray& operator=(const DynArray&) = default; DynArray& operator=(DynArray&&) noexcept = default; - /// Returns the data reference of the corresponding index. + /// \fn operator[] + /// \brief Returns the data reference of the corresponding index. + /// \return The data reference of the corresponding index. ArrayType& operator[](std::size_t index); - /// Adds an element to the end of the container. No return value. + /// \fn Insert + /// \brief Adds an element to the end of the dynamic array. void Insert(ArrayType data); - /// Increase the container capacity. - /// If |new_capacity| is 0, it is increased to 2 times |capacity_|. If - /// greater than 0, the container capacity is increased to |new_capacity|. - /// A return of 0 indicates a successful allocation, a return of -1 indicates - /// an error in the allocation. + /// \fn Remove + /// \brief Removes an element from the end of the dynamic array. + /// \param index std::size_t Type + void Remove(std::size_t index); + + /// \fn Resize + /// \brief Increase the dynamaic array capacity. + /// \details If `new_capacity` is `0`, `capacity_` is increased to `1`. If + /// greater than `0`, the container capacity is increased to `new_capacity`. + /// \param new_capacity + /// \return A return of `0` indicates a successful allocation. + /// A return of `-1` indicates an error in the allocation. int Resize(std::size_t new_capacity = 0); - /// Returns the number of elements in the container. + /// \fn Size + /// \brief Returns the number of elements in the container. + /// \return the number of elements in the container. std::size_t Size() const; - /// The iterator of the container. + /// \fn Clear + /// \brief Clears the contents of the dynamic array. + void Clear(); + + /// \class Iterator + /// \brief The iterator of the dynamic array. class Iterator { public: using iterator_category = std::random_access_iterator_tag; - Iterator(DynArray* array, std::size_t index = 0); - - ~Iterator(); - Iterator operator+(std::size_t size) const; Iterator& operator++(); Iterator operator++(int); @@ -66,19 +83,44 @@ class Compiler::DynArray { bool operator>=(const Iterator& other) const; private: + /// \fn Iterator + /// \brief Creates and initialize a dynamic array iterator. + /// \param array DynArray* Type + /// \param index std::size_t Type, optional, default value is 0 + /// \note Generally, it is created by the Begin and End functions. It should + /// not be created by others. + Iterator(DynArray* array, std::size_t index = 0); + + /// \fn ~Iterator + /// \brief Destroys the iterator. + /// \note Generally, it is called by the system. + ~Iterator(); + + /// \brief The dynamic array pointer. DynArray* array_; + + /// @brief The index of the iterator. std::size_t index_; }; - /// Returns an iterator to the beginning of the container. - Iterator Begin() { return Iterator(this, 0); } + /// \fn Begin + /// \brief Returns an iterator to the beginning of the container. + /// \return an iterator to the beginning of the container. + Iterator Begin(); - /// Returns an iterator to the end of the container. - Iterator End() { return Iterator(this, size_); } + /// \fn End + /// \brief Returns an iterator to the end of the container. + /// \return an iterator to the end of the container. + Iterator End(); private: + /// @brief The data of the dynamic array. ArrayType* data_; + + /// @brief The capacity of the dynamic array. std::size_t capacity_; + + /// @brief The size of the dynamic array. std::size_t size_; }; } // namespace Aq diff --git a/compiler/hash_map/hash_map.cc b/compiler/hash_map/hash_map.cc index 891e7d5..56b2b5a 100644 --- a/compiler/hash_map/hash_map.cc +++ b/compiler/hash_map/hash_map.cc @@ -30,16 +30,11 @@ Compiler::HashMap::~HashMap() { template void Compiler::HashMap::Insert(std::string key, ValueType value) { auto hash = static_cast(Hash(key)); - - /// Increase the size of the hash table. ++size_; if (size_ / capacity_ > 0.8) { Resize(); } - LinkedList> insert_list = pair_list_[hash]; - - /// Insert key-value pairs into the linked list. insert_list.Insert(insert_list.End(), {key, value}); } @@ -49,8 +44,6 @@ bool Compiler::HashMap::Find(std::string key, ValueType& value) { LinkedList> find_list = pair_list_[hash]; typename LinkedList>::Iterator temp_node = find_list.Begin(); - - /// Compare keys one by one to find the corresponding value. while (temp_node != find_list.End()) { if (key == *temp_node.first) { value = *temp_node.second; @@ -66,7 +59,6 @@ template unsigned int Compiler::HashMap::Hash(std::string key) const { unsigned int hash = 5381; for (char character : key) { - /// hash = hash * 33 + static_cast(character) hash = ((hash << 5) + hash) + static_cast(character); } hash = hash % capacity_; @@ -79,16 +71,12 @@ int Compiler::HashMap::Resize() { std::size_t new_capacity = capacity_ * 1.5; pair_list_ = new DynArray>>[new_capacity]; - - /// Memory allocation failed. if (!pair_list_) { Debugger error(Debugger::Level::ERROR, "Aq::Compiler::Lexer::HashMap::Resize", "Resize_MemoryError", "Memory allocation failed.", nullptr); return -1; } - - /// Copy data. for (std::size_t i = 0; i < capacity_; ++i) { LinkedList>& origin_list = temp[i]; typename LinkedList>::Iterator temp_node = @@ -100,10 +88,7 @@ int Compiler::HashMap::Resize() { ++temp_node; } } - - /// Release the memory of the original linked list. delete[] temp; - capacity_ = new_capacity; return 0; } diff --git a/compiler/hash_map/hash_map.h b/compiler/hash_map/hash_map.h index 59394b8..03aad0e 100644 --- a/compiler/hash_map/hash_map.h +++ b/compiler/hash_map/hash_map.h @@ -16,36 +16,52 @@ namespace Aq { template class Compiler::HashMap { public: + /// \fn HashMap + /// \brief Creates and initialize a hash table. + /// \param init_capacity std::size_t Type, optional, default value is 1024 HashMap(std::size_t init_capacity = 1024); ~HashMap(); + /// \bug These functions have many bugs when called. + /// \todo Fix these bugs. HashMap(const HashMap&) = default; HashMap(HashMap&&) noexcept = default; HashMap& operator=(const HashMap&) = default; HashMap& operator=(HashMap&&) noexcept = default; - /// Insert a new value into the hash table. + /// \fn Insert + /// \brief Insert a new value into the hash table. + /// \param key std::string Type + /// \param value ValueType Type void Insert(std::string key, ValueType value); - /// Find the key in a hash table and store the corresponding value in value. - /// Returns true if found, false otherwise. + /// \fn Find + /// \brief Find the key in a hash table and store the corresponding value in value. + /// \param key std::string Type + /// \param value ValueType& Type, Get the corresponding value + /// \return true if found, false otherwise. bool Find(std::string key, ValueType& value); private: - /// The memory size of the hash table. + /// \brief The memory size of the hash table. The default capacity is 0. std::size_t capacity_ = 0; - /// The number of elements in the hash table. + /// \brief The number of elements in the hash table. The default size is 0. std::size_t size_ = 0; - /// The data collection of the hash table is stored in a linked list of type - /// PairList. + /// \brief The data collection of the hash table is stored in a linked list. DynArray>>* pair_list_ = nullptr; - /// The hash function. Based on DJB2 hashing algorithm. + /// \fn Hash + /// \brief Get hash value of the key. + /// \details Based on DJB2 hashing algorithm. + /// \param key std::string Type + /// \return hash value of the key. unsigned int Type. unsigned int Hash(std::string key) const; - /// Re-allocate the memory of the hash table. + /// \fn Resize + /// \brief Re-allocate the memory of the hash table. + /// \return 0 if success, -1 if failed. int Resize(); }; } // namespace Aq diff --git a/compiler/lexer/lexer.cc b/compiler/lexer/lexer.cc index 0c5a0c1..9ba8c54 100644 --- a/compiler/lexer/lexer.cc +++ b/compiler/lexer/lexer.cc @@ -11,6 +11,7 @@ #include "compiler/token/keyword.h" #include "compiler/token/operator.h" #include "compiler/token/token.h" +#include "compiler/token/token_kind.h" #include "debugger/debugger.h" namespace Aq { @@ -19,16 +20,11 @@ Compiler::Lexer::Lexer(char* source_code, size_t length) Compiler::Lexer::~Lexer() = default; int Compiler::Lexer::LexToken(Token& return_token) { - using Tok = Token::Type; - - /// Set the return token type to start. - return_token.type = Tok::START; - - /// Set the reading position pointer equal to the buffer pointer. + using Tok = Token::Kind; + return_token.SetKind(Tok::UNKNOWN); char* read_ptr = buffer_ptr_; LexStart: - /// Memory out of bounds occurred. Return an error. if (read_ptr > buffer_end_) { buffer_ptr_ = read_ptr; Debugger error(Debugger::Level::ERROR, "Aq::Compiler::Lexer::LexToken", @@ -37,9 +33,7 @@ int Compiler::Lexer::LexToken(Token& return_token) { return -1; } - /// Start lexical analysis. switch (*read_ptr) { - /// General operators. case '!': case '#': case '$': @@ -69,44 +63,44 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexEnd; - /// The string flag. + // The string flag. case '"': if (ProcessToken(return_token, Tok::STRING, 2, Tok::STRING, Tok::COMMENT)) { goto LexNext; } - /// End of string. - if (return_token.type == Tok::STRING) { + // End of string. + if (return_token.GetKind() == Tok::STRING) { ++read_ptr; } goto LexEnd; - /// The character flag. + // The character flag. case '\'': if (ProcessToken(return_token, Tok::CHARACTER, 2, Tok::STRING, Tok::COMMENT)) { goto LexNext; } - /// End of character. - if (return_token.type == Tok::CHARACTER) { + // End of character. + if (return_token.GetKind() == Tok::CHARACTER) { ++read_ptr; } goto LexEnd; - /// Escape character. + // Escape character. case '\\': if (ProcessToken(return_token, Tok::OPERATOR, 2, Tok::OPERATOR, Tok::COMMENT)) { goto LexNext; } - /// Skip escape characters. - if (return_token.type == Tok::CHARACTER || - return_token.type == Tok::STRING) { + // Skip escape characters. + if (return_token.GetKind() == Tok::CHARACTER || + return_token.GetKind() == Tok::STRING) { if (read_ptr + 2 <= buffer_end_) { ++read_ptr; } @@ -115,17 +109,17 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexEnd; - /// Positive and negative numbers. + // Positive and negative numbers. case '+': case '-': - /// Signed numbers. - if (return_token.type == Tok::START && *(read_ptr + 1) == '0' || + // Signed numbers. + if (return_token.GetKind() == Tok::UNKNOWN && *(read_ptr + 1) == '0' || *(read_ptr + 1) == '1' || *(read_ptr + 1) == '2' || *(read_ptr + 1) == '3' || *(read_ptr + 1) == '4' || *(read_ptr + 1) == '5' || *(read_ptr + 1) == '6' || *(read_ptr + 1) == '7' || *(read_ptr + 1) == '8' || *(read_ptr + 1) == '9') { - return_token.type = Tok::NUMBER; + return_token.SetKind(Tok::NUMBER); goto LexNext; } @@ -134,15 +128,15 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexNext; } - /// Dealing with scientific notation. - if (return_token.type == Tok::NUMBER && + // Dealing with scientific notation. + if (return_token.GetKind() == Tok::NUMBER && (*(read_ptr - 1) == 'E' || *(read_ptr - 1) == 'e')) { goto LexNext; } goto LexEnd; - /// Decimal point. + // Decimal point. case '.': if (ProcessToken(return_token, Tok::OPERATOR, 5, Tok::OPERATOR, Tok::NUMBER, Tok::CHARACTER, Tok::STRING, @@ -152,12 +146,12 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexEnd; - /// The comment flag. + // The comment flag. case '/': - /// Comment start. - if (return_token.type == Tok::START && *(buffer_ptr_ + 1) == '/' || + // Comment start. + if (return_token.GetKind() == Tok::UNKNOWN && *(buffer_ptr_ + 1) == '/' || *(buffer_ptr_ + 1) == '*') { - return_token.type = Tok::COMMENT; + return_token.SetKind(Tok::COMMENT); if (read_ptr + 2 <= buffer_end_) { ++read_ptr; } @@ -169,8 +163,8 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexNext; } - if (return_token.type == Tok::OPERATOR) { - /// Comment. + if (return_token.GetKind() == Tok::OPERATOR) { + // Comment. if (*(read_ptr + 1) == '/' || *(read_ptr + 1) == '*') { goto LexEnd; } else { @@ -178,22 +172,22 @@ int Compiler::Lexer::LexToken(Token& return_token) { } } - if (return_token.type == Tok::COMMENT) { + if (return_token.GetKind() == Tok::COMMENT) { if (*(buffer_ptr_ + 1) == '*' && *(read_ptr - 1) == '*') { - /// /**/ style comments, skip all comments. + // /**/ style comments, skip all comments. buffer_ptr_ = ++read_ptr; - return_token.type = Tok::START; + return_token.SetKind(Tok::UNKNOWN); goto LexStart; } else { - /// /// style comments or Non-end comment mark, continue reading until - /// the end mark of the comment. + // // style comments or Non-end comment mark, continue reading until + // the end mark of the comment. goto LexNext; } } goto LexEnd; - /// Numbers. + // Numbers. case '0': case '1': case '2': @@ -212,56 +206,56 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexEnd; - /// Whitespace characters. + // Whitespace characters. case '\f': case '\r': case '\t': case '\v': case ' ': - if (return_token.type == Tok::START) { - /// Skip whitespace characters. + if (return_token.GetKind() == Tok::UNKNOWN) { + // Skip whitespace characters. ++buffer_ptr_; goto LexNext; } - if (ProcessToken(return_token, Tok::START, 3, Tok::CHARACTER, Tok::STRING, - Tok::COMMENT)) { + if (ProcessToken(return_token, Tok::UNKNOWN, 3, Tok::CHARACTER, + Tok::STRING, Tok::COMMENT)) { goto LexNext; } goto LexEnd; - /// Newlines. + // Newlines. case '\n': - if (return_token.type == Tok::START) { - /// Skip newlines. + if (return_token.GetKind() == Tok::UNKNOWN) { + // Skip newlines. ++buffer_ptr_; goto LexNext; } - if (return_token.type == Tok::COMMENT && *(buffer_ptr_ + 1) == '/') { - /// /// style comments, skip all comments. + if (return_token.GetKind() == Tok::COMMENT && *(buffer_ptr_ + 1) == '/') { + // // style comments, skip all comments. buffer_ptr_ = ++read_ptr; - return_token.type = Tok::START; + return_token.SetKind(Tok::UNKNOWN); goto LexStart; } - if (ProcessToken(return_token, Tok::START, 3, Tok::CHARACTER, Tok::STRING, - Tok::COMMENT)) { + if (ProcessToken(return_token, Tok::UNKNOWN, 3, Tok::CHARACTER, + Tok::STRING, Tok::COMMENT)) { goto LexNext; } goto LexEnd; - /// EOF. + // EOF. case '\0': goto LexEnd; - /// Separator flag. + // Separator flag. case ',': case ';': - if (return_token.type == Tok::START) { - return_token.type = Tok::OPERATOR; + if (return_token.GetKind() == Tok::UNKNOWN) { + return_token.SetKind(Tok::OPERATOR); ++read_ptr; goto LexEnd; } @@ -288,30 +282,32 @@ int Compiler::Lexer::LexToken(Token& return_token) { goto LexStart; LexEnd: - /// Meaningless token. - if (return_token.type == Tok::START || return_token.type == Tok::COMMENT) { - return_token.type = Tok::NONE; + /// \todo Wait development. + // Meaningless token. + if (return_token.GetKind() == Tok::UNKNOWN || + return_token.GetKind() == Tok::COMMENT) { + return_token.SetKind(Tok::UNKNOWN); buffer_ptr_ = read_ptr; return 0; } else { - /// Meaningful token. Determine the specific token information. + // Meaningful token. Determine the specific token information. char* location = buffer_ptr_; size_t length = read_ptr - buffer_ptr_; buffer_ptr_ = read_ptr; - /// Handle the detailed information of tokens. + // Handle the detailed information of tokens. Token::ValueStr value; value.location = location; value.length = length; - switch (return_token.type) { + switch (return_token.GetKind()) { case Tok::IDENTIFIER: return_token.value.keyword = token_map_.GetKeywordValue(std::string(location, length)); - if (return_token.value.keyword == Token::Keyword::NONE) { + if (return_token.value.keyword == Token::Kind::UNKNOWN) { return_token.value.identifier = value; break; } - return_token.type = Tok::KEYWORD; + return_token.SetKind(Tok::KEYWORD); break; case Tok::CHARACTER: @@ -325,8 +321,7 @@ int Compiler::Lexer::LexToken(Token& return_token) { case Tok::OPERATOR: return_token.value._operator = token_map_.GetOperatorValue(std::string(location, length)); - while (return_token.value._operator == Token::Operator::NONE && - length > 1) { + while (return_token.GetKind() == Token::Kind::UNKNOWN && length > 1) { length--; buffer_ptr_--; return_token.value._operator = @@ -357,16 +352,16 @@ bool Compiler::Lexer::IsReadEnd() const { return false; } -bool Compiler::Lexer::ProcessToken(Token& token, Token::Type start_type, - int next_type_size, ...) const { - if (token.type == Token::Type::START) { - token.type = start_type; +bool Compiler::Lexer::ProcessToken(Token& token, Token::Kind start_kind, + int next_kind_size, ...) const { + if (token.GetKind() == Token::Kind::UNKNOWN) { + token.SetKind(start_kind); return true; } - std::va_list next_type_list; - va_start(next_type_list, next_type_size); - for (int i = 0; i < next_type_size; ++i) { - if (token.type == va_arg(next_type_list, Token::Type)) { + std::va_list next_kind_list; + va_start(next_kind_list, next_kind_size); + for (int i = 0; i < next_kind_size; ++i) { + if (token.GetKind() == va_arg(next_kind_list, Token::Kind)) { return true; } } diff --git a/compiler/lexer/lexer.h b/compiler/lexer/lexer.h index cb9c429..a731ecf 100644 --- a/compiler/lexer/lexer.h +++ b/compiler/lexer/lexer.h @@ -14,42 +14,61 @@ namespace Aq { class Compiler::Lexer { public: - /// Initialize the Lexer class and store |source_code| to |buffer_ptr_|. + /// \fn Lexer + /// \brief Creates and initialize a Lexer. + /// \details Initialize the Lexer class and store `source_code` to + /// `buffer_ptr_`. Lexer(char* source_code, size_t length); ~Lexer(); - Lexer(const Lexer&) = default; - Lexer(Lexer&&) noexcept = default; - Lexer& operator=(const Lexer&) = default; - Lexer& operator=(Lexer&&) noexcept = default; + Lexer(const Lexer&) = delete; + Lexer(Lexer&&) noexcept = delete; + Lexer& operator=(const Lexer&) = delete; + Lexer& operator=(Lexer&&) noexcept = delete; - /// Lexically analyze |buffer_ptr_| and store the analyzed token to - /// |return_token|. Reads one character at a time and analyzes the token for - /// completeness except for that character, and repeatedly reads the characters - /// of |buffer_ptr_| until the token is complete, then returns a token. a - /// normal read returns 0, and a read error returns -1. + /// \fn LexToken + /// \brief Lexically analyze `buffer_ptr_` and store the analyzed token to + /// `return_token`. + /// \details Reads one character at a time and analyzes the token for + /// completeness except for that character, and repeatedly reads the + /// characters of `buffer_ptr_` until the token is complete, then returns a + /// token. + /// \param return_token Token& Type. + /// \return A normal read returns `0`, and a read error returns `-1`. int LexToken(Token& return_token); - /// Returns whether the source code has finished reading. + /// \fn IsReadEnd + /// \brief Returns whether the source code has finished reading. + /// \return true if the source code has finished reading, false otherwise. bool IsReadEnd() const; private: + /// @brief The source code to be analyzed. char* buffer_ptr_; + + /// @brief The end of the source code to be analyzed. char* buffer_end_; + + /// @brief A token map to get the analyzed tokens' kinds. TokenMap token_map_; - /// Process the token being lexically analyzed and determine if the token is + /// \fn ProcessToken + /// \brief Process the token being lexically analyzed and determine if the token is /// complete in the general case. - // This function is only applicable to the general case, special cases require - /// additional judgment logic. In general, if |token| belongs to the - /// Token::Type::START type, the type of |token| will be modified to - /// |start_type| and true will be returned. if |token| matches one of the - /// variable parameters (i.e., |next_type_list|), then true will be returned, + /// \details This function is only applicable to the general case, special cases + /// require additional judgment logic. In general, if `token` belongs to the + /// Token::Kind::UNKNOWN type, the type of `token` will be modified to + /// `start_kind` and true will be returned. if `token` matches one of the + /// variable parameters (i.e., `next_kind_list`), then true will be returned, /// otherwise false will be returned. - /// In general, returning true means that |token| is incomplete except for that - /// character, and returning false means that |token| is complete except for - /// that character. - bool ProcessToken(Token& token, Token::Type start_type, int next_type_size, + /// \param token Token& Type + /// \param start_kind Token::Kind Type + /// \param next_kind_size int Type + /// \param ... Token::Kind Type + /// \return In general, returning true means that `token` is incomplete except for + /// that character, and returning false means that `token` is complete except + /// for that character. + bool ProcessToken(Token& token, Token::Kind start_kind, int next_kind_size, ...) const; }; } // namespace Aq diff --git a/compiler/lexer/token_map.cc b/compiler/lexer/token_map.cc index 4ba69dc..cfab3b4 100644 --- a/compiler/lexer/token_map.cc +++ b/compiler/lexer/token_map.cc @@ -8,141 +8,136 @@ #include "compiler/token/keyword.h" #include "compiler/token/operator.h" #include "compiler/token/token.h" +#include "compiler/token/token_kind.h" #include "debugger/debugger.h" namespace Aq { Compiler::TokenMap::TokenMap() { /// TODO: Should be improved - keyword_map_.Insert("auto", Token::Keyword::Auto); - keyword_map_.Insert("and", Token::Keyword::And); - keyword_map_.Insert("bitand", Token::Keyword::Bitand); - keyword_map_.Insert("bitor", Token::Keyword::Bitor); - keyword_map_.Insert("bool", Token::Keyword::Bool); - keyword_map_.Insert("break", Token::Keyword::Break); - keyword_map_.Insert("case", Token::Keyword::Case); - keyword_map_.Insert("catch", Token::Keyword::Catch); - keyword_map_.Insert("char", Token::Keyword::Char); - keyword_map_.Insert("class", Token::Keyword::Class); - keyword_map_.Insert("const", Token::Keyword::Const); - keyword_map_.Insert("continue", Token::Keyword::Continue); - keyword_map_.Insert("default", Token::Keyword::Default); - keyword_map_.Insert("do", Token::Keyword::Do); - keyword_map_.Insert("double", Token::Keyword::Double); - keyword_map_.Insert("else", Token::Keyword::Else); - keyword_map_.Insert("enum", Token::Keyword::Enum); - keyword_map_.Insert("export", Token::Keyword::Export); - keyword_map_.Insert("extern", Token::Keyword::Extern); - keyword_map_.Insert("false", Token::Keyword::False); - keyword_map_.Insert("float", Token::Keyword::Float); - keyword_map_.Insert("for", Token::Keyword::For); - keyword_map_.Insert("friend", Token::Keyword::Friend); - keyword_map_.Insert("goto", Token::Keyword::Goto); - keyword_map_.Insert("import", Token::Keyword::Import); - keyword_map_.Insert("inline", Token::Keyword::Inline); - keyword_map_.Insert("int", Token::Keyword::Int); - keyword_map_.Insert("long", Token::Keyword::Long); - keyword_map_.Insert("namespace", Token::Keyword::Namespace); - keyword_map_.Insert("new", Token::Keyword::New); - keyword_map_.Insert("not", Token::Keyword::Not); - keyword_map_.Insert("number", Token::Keyword::Number); - keyword_map_.Insert("operator", Token::Keyword::Operator); - keyword_map_.Insert("or", Token::Keyword::Or); - keyword_map_.Insert("private", Token::Keyword::Private); - keyword_map_.Insert("protected", Token::Keyword::Protected); - keyword_map_.Insert("public", Token::Keyword::Public); - keyword_map_.Insert("return", Token::Keyword::Return); - keyword_map_.Insert("short", Token::Keyword::Short); - keyword_map_.Insert("signed", Token::Keyword::Signed); - keyword_map_.Insert("sizeof", Token::Keyword::Sizeof); - keyword_map_.Insert("static", Token::Keyword::Static); - keyword_map_.Insert("string", Token::Keyword::String); - keyword_map_.Insert("struct", Token::Keyword::Struct); - keyword_map_.Insert("switch", Token::Keyword::Switch); - keyword_map_.Insert("template", Token::Keyword::Template); - keyword_map_.Insert("this", Token::Keyword::This); - keyword_map_.Insert("thread", Token::Keyword::Thread); - keyword_map_.Insert("true", Token::Keyword::True); - keyword_map_.Insert("try", Token::Keyword::Try); - keyword_map_.Insert("typedef", Token::Keyword::Typedef); - keyword_map_.Insert("typeid", Token::Keyword::Typeid); - keyword_map_.Insert("typename", Token::Keyword::Typename); - keyword_map_.Insert("union", Token::Keyword::Union); - keyword_map_.Insert("unsigned", Token::Keyword::Unsigned); - keyword_map_.Insert("using", Token::Keyword::Using); - keyword_map_.Insert("virtual", Token::Keyword::Virtual); - keyword_map_.Insert("void", Token::Keyword::Void); - keyword_map_.Insert("wchar_t", Token::Keyword::Wchar_t); - keyword_map_.Insert("while", Token::Keyword::While); - keyword_map_.Insert("xor", Token::Keyword::Xor); + token_map_.Insert("auto", Token::Kind::kAuto); + token_map_.Insert("and", Token::Kind::kAnd); + token_map_.Insert("bitand", Token::Kind::kBitand); + token_map_.Insert("bitor", Token::Kind::kBitor); + token_map_.Insert("bool", Token::Kind::kBool); + token_map_.Insert("break", Token::Kind::kBreak); + token_map_.Insert("case", Token::Kind::kCase); + token_map_.Insert("catch", Token::Kind::kCatch); + token_map_.Insert("char", Token::Kind::kChar); + token_map_.Insert("class", Token::Kind::kClass); + token_map_.Insert("const", Token::Kind::kConst); + token_map_.Insert("continue", Token::Kind::kContinue); + token_map_.Insert("default", Token::Kind::kDefault); + token_map_.Insert("do", Token::Kind::kDo); + token_map_.Insert("double", Token::Kind::kDouble); + token_map_.Insert("else", Token::Kind::kElse); + token_map_.Insert("enum", Token::Kind::kEnum); + token_map_.Insert("export", Token::Kind::kExport); + token_map_.Insert("extern", Token::Kind::kExtern); + token_map_.Insert("false", Token::Kind::kFalse); + token_map_.Insert("float", Token::Kind::kFloat); + token_map_.Insert("for", Token::Kind::kFor); + token_map_.Insert("friend", Token::Kind::kFriend); + token_map_.Insert("goto", Token::Kind::kGoto); + token_map_.Insert("import", Token::Kind::kImport); + token_map_.Insert("inline", Token::Kind::kInline); + token_map_.Insert("int", Token::Kind::kInt); + token_map_.Insert("long", Token::Kind::kLong); + token_map_.Insert("namespace", Token::Kind::kNamespace); + token_map_.Insert("new", Token::Kind::kNew); + token_map_.Insert("not", Token::Kind::kNot); + token_map_.Insert("number", Token::Kind::kNumber); + token_map_.Insert("operator", Token::Kind::kOperator); + token_map_.Insert("or", Token::Kind::kOr); + token_map_.Insert("private", Token::Kind::kPrivate); + token_map_.Insert("protected", Token::Kind::kProtected); + token_map_.Insert("public", Token::Kind::kPublic); + token_map_.Insert("return", Token::Kind::kReturn); + token_map_.Insert("short", Token::Kind::kShort); + token_map_.Insert("signed", Token::Kind::kSigned); + token_map_.Insert("sizeof", Token::Kind::kSizeof); + token_map_.Insert("static", Token::Kind::kStatic); + token_map_.Insert("string", Token::Kind::kString); + token_map_.Insert("struct", Token::Kind::kStruct); + token_map_.Insert("switch", Token::Kind::kSwitch); + token_map_.Insert("template", Token::Kind::kTemplate); + token_map_.Insert("this", Token::Kind::kThis); + token_map_.Insert("thread", Token::Kind::kThread); + token_map_.Insert("true", Token::Kind::kTrue); + token_map_.Insert("try", Token::Kind::kTry); + token_map_.Insert("typedef", Token::Kind::kTypedef); + token_map_.Insert("typeid", Token::Kind::kTypeid); + token_map_.Insert("typename", Token::Kind::kTypename); + token_map_.Insert("union", Token::Kind::kUnion); + token_map_.Insert("unsigned", Token::Kind::kUnsigned); + token_map_.Insert("using", Token::Kind::kUsing); + token_map_.Insert("virtual", Token::Kind::kVirtual); + token_map_.Insert("void", Token::Kind::kVoid); + token_map_.Insert("wchar_t", Token::Kind::kWcharT); + token_map_.Insert("while", Token::Kind::kWhile); + token_map_.Insert("xor", Token::Kind::kXor); - operator_map_.Insert("[", Token::Operator::l_square); - operator_map_.Insert("]", Token::Operator::r_square); - operator_map_.Insert("(", Token::Operator::l_paren); - operator_map_.Insert(")", Token::Operator::r_paren); - operator_map_.Insert("{", Token::Operator::l_brace); - operator_map_.Insert("}", Token::Operator::r_brace); - operator_map_.Insert(".", Token::Operator::period); - operator_map_.Insert("...", Token::Operator::ellipsis); - operator_map_.Insert("&", Token::Operator::amp); - operator_map_.Insert("&&", Token::Operator::ampamp); - operator_map_.Insert("&=", Token::Operator::ampequal); - operator_map_.Insert("*", Token::Operator::star); - operator_map_.Insert("*=", Token::Operator::starequal); - operator_map_.Insert("+", Token::Operator::plus); - operator_map_.Insert("++", Token::Operator::plusplus); - operator_map_.Insert("+=", Token::Operator::plusequal); - operator_map_.Insert("-", Token::Operator::minus); - operator_map_.Insert("->", Token::Operator::arrow); - operator_map_.Insert("--", Token::Operator::minusminus); - operator_map_.Insert("-=", Token::Operator::minusequal); - operator_map_.Insert("~", Token::Operator::tilde); - operator_map_.Insert("!", Token::Operator::exclaim); - operator_map_.Insert("!=", Token::Operator::exclaimequal); - operator_map_.Insert("/", Token::Operator::slash); - operator_map_.Insert("/=", Token::Operator::slashequal); - operator_map_.Insert("%", Token::Operator::percent); - operator_map_.Insert("%=", Token::Operator::percentequal); - operator_map_.Insert("<", Token::Operator::less); - operator_map_.Insert("<<", Token::Operator::lessless); - operator_map_.Insert("<=", Token::Operator::lessequal); - operator_map_.Insert("<<=", Token::Operator::lesslessequal); - operator_map_.Insert("<=>", Token::Operator::spaceship); - operator_map_.Insert(">", Token::Operator::greater); - operator_map_.Insert(">>", Token::Operator::greatergreater); - operator_map_.Insert(">=", Token::Operator::greaterequal); - operator_map_.Insert(">>=", Token::Operator::greatergreaterequal); - operator_map_.Insert("^", Token::Operator::caret); - operator_map_.Insert("^=", Token::Operator::caretequal); - operator_map_.Insert("|", Token::Operator::pipe); - operator_map_.Insert("||", Token::Operator::pipepipe); - operator_map_.Insert("|=", Token::Operator::pipeequal); - operator_map_.Insert("?", Token::Operator::question); - operator_map_.Insert(":", Token::Operator::colon); - operator_map_.Insert(";", Token::Operator::semi); - operator_map_.Insert("=", Token::Operator::equal); - operator_map_.Insert("==", Token::Operator::equalequal); - operator_map_.Insert(",", Token::Operator::comma); - operator_map_.Insert("#", Token::Operator::hash); - operator_map_.Insert("##", Token::Operator::hashhash); - operator_map_.Insert("#@", Token::Operator::hashat); - operator_map_.Insert(".*", Token::Operator::periodstar); - operator_map_.Insert("->*", Token::Operator::arrowstar); - operator_map_.Insert("::", Token::Operator::coloncolon); - operator_map_.Insert("@", Token::Operator::at); - operator_map_.Insert("<<<", Token::Operator::lesslessless); - operator_map_.Insert(">>>", Token::Operator::greatergreatergreater); - operator_map_.Insert("^^", Token::Operator::caretcaret); + token_map_.Insert("[", Token::Kind::kLSquare); + token_map_.Insert("]", Token::Kind::kRSquare); + token_map_.Insert("(", Token::Kind::kLParen); + token_map_.Insert(")", Token::Kind::kRParen); + token_map_.Insert("{", Token::Kind::kLBrace); + token_map_.Insert("}", Token::Kind::kRBrace); + token_map_.Insert(".", Token::Kind::kPeriod); + token_map_.Insert("...", Token::Kind::kEllipsis); + token_map_.Insert("&", Token::Kind::kAmp); + token_map_.Insert("&&", Token::Kind::kAmpAmp); + token_map_.Insert("&=", Token::Kind::kAmpEqual); + token_map_.Insert("*", Token::Kind::kStar); + token_map_.Insert("*=", Token::Kind::kStarEqual); + token_map_.Insert("+", Token::Kind::kPlus); + token_map_.Insert("++", Token::Kind::kPlusPlus); + token_map_.Insert("+=", Token::Kind::kPlusEqual); + token_map_.Insert("-", Token::Kind::kMinus); + token_map_.Insert("->", Token::Kind::kArrow); + token_map_.Insert("--", Token::Kind::kMinusMinus); + token_map_.Insert("-=", Token::Kind::kMinusEqual); + token_map_.Insert("~", Token::Kind::kTilde); + token_map_.Insert("!", Token::Kind::kExclaim); + token_map_.Insert("!=", Token::Kind::kExclaimEqual); + token_map_.Insert("/", Token::Kind::kSlash); + token_map_.Insert("/=", Token::Kind::kSlashEqual); + token_map_.Insert("%", Token::Kind::kPercent); + token_map_.Insert("%=", Token::Kind::kPercentEqual); + token_map_.Insert("<", Token::Kind::kLess); + token_map_.Insert("<<", Token::Kind::kLessLess); + token_map_.Insert("<=", Token::Kind::kLessEqual); + token_map_.Insert("<<=", Token::Kind::kLessLessEqual); + token_map_.Insert("<=>", Token::Kind::kSpaceship); + token_map_.Insert(">", Token::Kind::kGreater); + token_map_.Insert(">>", Token::Kind::kGreaterGreater); + token_map_.Insert(">=", Token::Kind::kGreaterEqual); + token_map_.Insert(">>=", Token::Kind::kGreaterGreaterEqual); + token_map_.Insert("^", Token::Kind::kCaret); + token_map_.Insert("^=", Token::Kind::kCaretEqual); + token_map_.Insert("|", Token::Kind::kPipe); + token_map_.Insert("||", Token::Kind::kPipePipe); + token_map_.Insert("|=", Token::Kind::kPipeEqual); + token_map_.Insert("?", Token::Kind::kQuestion); + token_map_.Insert(":", Token::Kind::kColon); + token_map_.Insert(";", Token::Kind::kSemi); + token_map_.Insert("=", Token::Kind::kEqual); + token_map_.Insert("==", Token::Kind::kEqualEqual); + token_map_.Insert(",", Token::Kind::kComma); + token_map_.Insert("#", Token::Kind::kHash); + token_map_.Insert("##", Token::Kind::kHashHash); + token_map_.Insert("#@", Token::Kind::kHashAt); + token_map_.Insert(".*", Token::Kind::kPeriodStar); + token_map_.Insert("->*", Token::Kind::kArrowStar); + token_map_.Insert("::", Token::Kind::kColonColon); + token_map_.Insert("@", Token::Kind::kAt); + token_map_.Insert("<<<", Token::Kind::kLessLessLess); + token_map_.Insert(">>>", Token::Kind::kGreaterGreaterGreater); + token_map_.Insert("^^", Token::Kind::kCaretCaret); } Compiler::TokenMap::~TokenMap() = default; -Compiler::Token::Keyword Compiler::TokenMap::GetKeywordValue( - std::string keyword) { +Compiler::Token::Kind Compiler::TokenMap::GetKind(std::string key) { /// TODO: Should be improved - /// return keyword_map_.Find(keyword); -} -Compiler::Token::Operator Compiler::TokenMap::GetOperatorValue( - std::string _operator) { - /// TODO: Should be improved - /// return operator_map_.Find(_operator); + /// return token_map_.Find(_operator); } } // namespace Aq \ No newline at end of file diff --git a/compiler/lexer/token_map.h b/compiler/lexer/token_map.h index 87485bf..7cfa060 100644 --- a/compiler/lexer/token_map.h +++ b/compiler/lexer/token_map.h @@ -10,14 +10,18 @@ #include "compiler/token/token.h" namespace Aq { -/// TODO: Should be improved +/// \class TokenMap +/// \brief Maps tokens to kinds. class Compiler::TokenMap { public: TokenMap(); ~TokenMap(); - Token::Keyword GetKeywordValue(std::string keyword); - Token::Operator GetOperatorValue(std::string _operator); + /// \fn GetKind + /// \brief Gets the kind of a token's key. + /// \param key std::string Type + /// \return Token::Kind Type of the token's key + Token::Kind GetKind(std::string key); TokenMap(const TokenMap&) = default; TokenMap(TokenMap&&) noexcept = default; @@ -25,8 +29,8 @@ class Compiler::TokenMap { TokenMap& operator=(TokenMap&&) noexcept = default; private: - HashMap keyword_map_; - HashMap operator_map_; + /// \brief Maps tokens to kinds. + HashMap token_map_; }; } // namespace Aq diff --git a/compiler/linked_list/linked_list.cc b/compiler/linked_list/linked_list.cc index c34ba5b..f52e4ad 100644 --- a/compiler/linked_list/linked_list.cc +++ b/compiler/linked_list/linked_list.cc @@ -143,6 +143,15 @@ void Compiler::LinkedList::Remove(Iterator* delete_node) { delete delete_node->node_; } +template +void Compiler::LinkedList::Clear() { + while (head_ != nullptr) { + Node* temp = head_; + head_ = head_->location.second; + delete temp; + } +} + template typename Compiler::LinkedList::Iterator Compiler::LinkedList::Begin() const { diff --git a/compiler/linked_list/linked_list.h b/compiler/linked_list/linked_list.h index 6c9fb1b..ab5b8f1 100644 --- a/compiler/linked_list/linked_list.h +++ b/compiler/linked_list/linked_list.h @@ -12,7 +12,9 @@ #include "debugger/debugger.h" namespace Aq { - +/// \class LinkedList +/// \brief linked list +/// \tparam DataType template class Compiler::LinkedList { public: @@ -24,15 +26,24 @@ class Compiler::LinkedList { LinkedList& operator=(const LinkedList&) = delete; LinkedList& operator=(LinkedList&&) noexcept = delete; - /// The node type of the linked list. + /// \struct Node + /// \brief linked list node + /// \warning Node shouldn't be used by other classes. struct Node { + /// \brief First is prev node, second is next node. Pair location; + + /// \brief The data of the node. DataType data; }; - /// The iterator type of the linked list. + /// \class Iterator + /// \brief The iterator type of the linked list. class Iterator { public: + /// \fn Iterator + /// @brief Creates and initialize a linked list iterator. + /// @param node Node* Type Iterator(Node* node); ~Iterator(); @@ -54,24 +65,41 @@ class Compiler::LinkedList { bool operator!=(const Iterator& other) const; private: + /// @brief The node of the iterator. The default value is `nullptr`. Node* node_ = nullptr; }; - /// Inserts |new_data| after |prev_node|. If |prev_node| is |nullptr|, - /// |new_data| will be inserted at the beginning of the list. + /// \fn Insert + /// \brief Inserts `new_data` after `prev_node`. If `prev_node` is `nullptr`, + /// `new_data` will be inserted at the beginning of the list. + /// \param prev_node Iterator Type + /// \param new_data DataType Type void Insert(Iterator prev_node, DataType new_data); - /// Removes |delete_node| from the list. + /// \fn Remove + /// \brief Removes `delete_node` from the list. + /// \param delete_node Iterator Type void Remove(Iterator* delete_node); - /// Returns the beginning iterator of the linked list. + /// \fn Clear + /// \brief Removes all nodes from the list. + void Clear(); + + /// \fn Size + /// \brief Returns the number of elements in the linked list. + /// \return the beginning iterator of the linked list. Iterator Type. Iterator Begin() const; - /// Returns the end iterator of the linked list. + /// \fn End + /// \return the end iterator of the linked list. + /// \return the beginning iterator of the linked list. Iterator Type. Iterator End() const; private: + /// @brief The head node pointer of the linked list. Node* head_ = nullptr; + + /// @brief The tail node pointer of the linked list. Node* tail_ = nullptr; }; diff --git a/compiler/parser/parser.cc b/compiler/parser/parser.cc index 4041edb..dfe1694 100644 --- a/compiler/parser/parser.cc +++ b/compiler/parser/parser.cc @@ -4,4 +4,4 @@ #include "compiler/parser/parser.h" -/// TODO: Parser \ No newline at end of file +/// \todo Parser \ No newline at end of file diff --git a/compiler/parser/parser.h b/compiler/parser/parser.h index cf20704..2b8af3c 100644 --- a/compiler/parser/parser.h +++ b/compiler/parser/parser.h @@ -7,6 +7,6 @@ #include "compiler/ast/ast.h" -/// TODO: Parser +/// \todo Parser #endif \ No newline at end of file diff --git a/compiler/token/keyword.h b/compiler/token/keyword.h deleted file mode 100644 index 8637ddc..0000000 --- a/compiler/token/keyword.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2024 AQ authors, All Rights Reserved. -// This program is licensed under the AQ License. You can find the AQ license in -// the root directory. - -#ifndef AQ_COMPILER_TOKEN_KEYWORD_H_ -#define AQ_COMPILER_TOKEN_KEYWORD_H_ - -#include "compiler/compiler.h" -#include "compiler/token/token.h" - -namespace Aq { -enum class Compiler::Token::Keyword { - NONE = 0, - Auto, - And, - Bitand, - Bitor, - Bool, - Break, - Case, - Catch, - Char, - Class, - Const, - Continue, - Default, - Do, - Double, - Else, - Enum, - Export, - Extern, - False, - Float, - For, - Friend, - Goto, - Import, - Inline, - Int, - Long, - Namespace, - New, - Not, - Number, - Operator, - Or, - Private, - Protected, - Public, - Return, - Short, - Signed, - Sizeof, - Static, - String, - Struct, - Switch, - Template, - This, - Thread, - True, - Try, - Typedef, - Typeid, - Typename, - Union, - Unsigned, - Using, - Virtual, - Void, - Wchar_t, - While, - Xor, -}; -} - -#endif \ No newline at end of file diff --git a/compiler/token/operator.h b/compiler/token/operator.h deleted file mode 100644 index 0dd9449..0000000 --- a/compiler/token/operator.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2024 AQ authors, All Rights Reserved. -// This program is licensed under the AQ License. You can find the AQ license in -// the root directory. - -#ifndef AQ_COMPILER_TOKEN_OPERATOR_H_ -#define AQ_COMPILER_TOKEN_OPERATOR_H_ - -#include "compiler/compiler.h" -#include "compiler/token/token.h" - -namespace Aq{ -enum class Compiler::Token::Operator { - NONE = 0, - l_square, - r_square, - l_paren, - r_paren, - l_brace, - r_brace, - period, - ellipsis, - amp, - ampamp, - ampequal, - star, - starequal, - plus, - plusplus, - plusequal, - minus, - arrow, - minusminus, - minusequal, - tilde, - exclaim, - exclaimequal, - slash, - slashequal, - percent, - percentequal, - less, - lessless, - lessequal, - lesslessequal, - spaceship, - greater, - greatergreater, - greaterequal, - greatergreaterequal, - caret, - caretequal, - pipe, - pipepipe, - pipeequal, - question, - colon, - semi, - equal, - equalequal, - comma, - hash, - hashhash, - hashat, - periodstar, - arrowstar, - coloncolon, - at, - lesslessless, - greatergreatergreater, - caretcaret, -}; -} - -#endif \ No newline at end of file diff --git a/compiler/token/token.cc b/compiler/token/token.cc index e26c836..d48af4c 100644 --- a/compiler/token/token.cc +++ b/compiler/token/token.cc @@ -8,7 +8,22 @@ #include "debugger/debugger.h" namespace Aq { -/// TODO: Should be improved Compiler::Token::Token() = default; Compiler::Token::~Token() = default; + +void Compiler::Token::SetKind(Kind kind) { + this->kind_ = kind; +} + +Compiler::Token::Kind Compiler::Token::GetKind() const { + return kind_; +} + +void Compiler::Token::SetDataPtr(void* data_ptr) { + this->data_ptr_ = data_ptr; +} + +void* Compiler::Token::GetDataPtr() const { + return data_ptr_; +} } // namespace Aq \ No newline at end of file diff --git a/compiler/token/token.h b/compiler/token/token.h index 04e8abb..efe6193 100644 --- a/compiler/token/token.h +++ b/compiler/token/token.h @@ -10,7 +10,6 @@ #include "compiler/compiler.h" namespace Aq { -/// TODO: Should be improved class Compiler::Token { public: Token(); @@ -23,6 +22,11 @@ class Compiler::Token { enum class Kind; + void SetKind(Kind kind); + Kind GetKind() const; + void SetDataPtr(void* data_ptr); + void* GetDataPtr() const; + private: Kind kind_; void* data_ptr_; diff --git a/compiler/token/token_kind.h b/compiler/token/token_kind.h index afd9119..7d938ec 100644 --- a/compiler/token/token_kind.h +++ b/compiler/token/token_kind.h @@ -10,8 +10,7 @@ namespace Aq { enum class Compiler::Token::Kind { - NONE, - START, + UNKNOWN, KEYWORD, kAuto, kAnd, @@ -76,63 +75,63 @@ enum class Compiler::Token::Kind { kXor, IDENTIFIER, OPERATOR, - kLsquare, - kRsquare, - kLparen, - kRparen, - kLbrace, - kRbrace, + kLSquare, + kRSquare, + kLParen, + kRParen, + kLBrace, + kRBrace, kPeriod, kEllipsis, kAmp, - kAmpamp, - kAmpequal, + kAmpAmp, + kAmpEqual, kStar, - kStarequal, + kStarEqual, kPlus, - kPlusplus, - kPlusequal, + kPlusPlus, + kPlusEqual, kMinus, kArrow, - kMinusminus, - kMinusequal, + kMinusMinus, + kMinusEqual, kTilde, kExclaim, - kExclaimequal, + kExclaimEqual, kSlash, - kSlashequal, + kSlashEqual, kPercent, - kPercentequal, + kPercentEqual, kLess, - kLessless, - kLessequal, - kLesslessequal, + kLessLess, + kLessEqual, + kLessLessEqual, kSpaceship, kGreater, - kGreatergreater, - kGreaterequal, - kGreatergreaterequal, + kGreaterGreater, + kGreaterEqual, + kGreaterGreaterEqual, kCaret, - kCaretequal, + kCaretEqual, kPipe, - kPipepipe, - kPipeequal, + kPipePipe, + kPipeEqual, kQuestion, kColon, kSemi, kEqual, - kEqualequal, + kEqualEqual, kComma, kHash, - kHashhash, - kHashat, - kPeriodstar, - kArrowstar, - kColoncolon, + kHashHash, + kHashAt, + kPeriodStar, + kArrowStar, + kColonColon, kAt, - kLesslessless, - kGreatergreatergreater, - kCaretcaret, + kLessLessLess, + kGreaterGreaterGreater, + kCaretCaret, NUMBER, CHARACTER, STRING, diff --git a/debugger/debugger.h b/debugger/debugger.h index 426aeb9..d7fb62d 100644 --- a/debugger/debugger.h +++ b/debugger/debugger.h @@ -14,8 +14,17 @@ class Debugger { public: enum class Level { ERROR = 0, WARNING = 1, INFO = 2 }; - /// Output a debug message. If |other_info| has no content, nullptr can be - /// filled in. Others must be filled in with strings and cannot be nullptr. + /// \fn Debugger + /// \brief Output a debug message. + /// \param level Level Type. The debug message's level. + /// \param location `const char*` Type. The debug message's location. + /// \param debug_code `const char*` Type. The debug message's code. + /// \param debug_message `const char*` Type. The debug message's content. + /// \param other_info `const char*` Type. Optional. The default value is + /// `nullptr`. The debug message's other information. + /// \note Output a debug message. If `other_info` has no content, `nullptr` + /// can be filled in. Others must be filled in with strings and cannot be + /// `nullptr`. Debugger(Level level, const char* location, const char* debug_code, const char* debug_message, const char* other_info = nullptr); ~Debugger(); @@ -26,20 +35,36 @@ class Debugger { Debugger& operator=(Debugger&&) = default; private: + /// \brief The debug happened time. time_t timestamp_ = 0; + + /// \brief The debug message's level. Level level_; + + /// \brief The debug happened location. const char* location_; + + /// \brief The debug message's code. const char* debug_code_; + + /// \brief The debug message's content. const char* debug_message_; + + /// \brief The debug message's other information. Default value is `nullptr`. const char* other_info_ = nullptr; + /// \brief The debug happened errno. int errno_ = 0; + /// \brief The debug happened errno message. const char* errno_message_; - /// Output a debug message. + /// \fn OutputMessage + /// \brief Output a debug message. void OutputMessage() const; - /// Get the current time string. Based on ISO 8601 standard. + /// \fn GetTimeString + /// \brief Get the current time string. Based on ISO 8601 standard. + /// \return The current time string. std::string Type. std::string GetTimeString() const; }; } // namespace Aq