|
|
|
/**
|
|
|
|
* lisp-compiler: Compiles LISP using LLVM.
|
|
|
|
* Copyright (C) 2022 Clyne Sullivan
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify it under
|
|
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
|
|
* Foundation, either version 3 of the License, or (at your option) any later
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
|
|
* details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along with
|
|
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
|
|
|
* @file parser.hpp
|
|
|
|
* @brief Source code parser to produce AST.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PARSER_HPP
|
|
|
|
#define PARSER_HPP
|
|
|
|
|
|
|
|
#include "ast.hpp"
|
|
|
|
|
|
|
|
#include <deque>
|
|
|
|
#include <optional>
|
|
|
|
#include <string>
|
|
|
|
#include <variant>
|
|
|
|
|
|
|
|
class Parser {
|
|
|
|
public:
|
|
|
|
enum Error {
|
|
|
|
ExpectedProcedureCallOpen,
|
|
|
|
ExpectedIdentifier,
|
|
|
|
ExpectedProcedureCallClose,
|
|
|
|
ExpectedArgumentList,
|
|
|
|
UnknownIdentifier,
|
|
|
|
InvalidExpression,
|
|
|
|
InvalidOperand,
|
|
|
|
InvalidCondition,
|
|
|
|
InvalidThenBranch,
|
|
|
|
InvalidElseBranch,
|
|
|
|
InvalidInitializer,
|
|
|
|
InvalidAssignValue,
|
|
|
|
InvalidArgumentName,
|
|
|
|
InvalidLambdaBody
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Appends the given string to the end of the text queue.
|
|
|
|
* Call parse() after adding text to produce the AST.
|
|
|
|
*/
|
|
|
|
void addString(const std::string&);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempts to parse all text in the text queue, stopping if there is an
|
|
|
|
* error.
|
|
|
|
* @return An iterable collection of produced AST nodes.
|
|
|
|
*/
|
|
|
|
std::deque<AST::Node *> parse();
|
|
|
|
|
|
|
|
std::string describeErrors() noexcept;
|
|
|
|
|
|
|
|
bool hasErrors() const noexcept {
|
|
|
|
return !errors.empty();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::deque<char> text;
|
|
|
|
std::deque<Error> errors;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Advances through the text queue until a non-whitespace character is
|
|
|
|
* found.
|
|
|
|
*/
|
|
|
|
void consumeWhitespace() noexcept;
|
|
|
|
/**
|
|
|
|
* Attempts to consume an identifier from the text queue.
|
|
|
|
* @return A string containing the identifier if one is found.
|
|
|
|
*/
|
|
|
|
std::optional<std::string> consumeIdentifier() noexcept;
|
|
|
|
/**
|
|
|
|
* Attempts to consume a literal number from the text queue.
|
|
|
|
* @return The number if one is found: an integer if there is no decimal
|
|
|
|
* point; otherwise, a double.
|
|
|
|
* TODO Ensure and add noexcept.
|
|
|
|
*/
|
|
|
|
std::optional<std::variant<int, double>> consumeLiteralNumber();
|
|
|
|
|
|
|
|
AST::Node *parseExpression();
|
|
|
|
AST::Node *parseProcedureCall();
|
|
|
|
AST::Node *parseConditional();
|
|
|
|
AST::Node *parseDefinition();
|
|
|
|
AST::Node *parseAssignment();
|
|
|
|
AST::Node *parseLambdaExpression();
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif // PARSER_HPP
|
|
|
|
|