summaryrefslogtreecommitdiff
path: root/tiger-compiler/src/parse/tiger-driver.cc
diff options
context:
space:
mode:
authorMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
committerMartial Simon <msimon_fr@hotmail.com>2025-09-15 01:07:58 +0200
commit967be9e750221ab2ab783f95df79bb26d290a45e (patch)
tree6802900a5e975f9f68b169f0f503f040056d6952 /tiger-compiler/src/parse/tiger-driver.cc
add: added projectsHEADmain
Diffstat (limited to 'tiger-compiler/src/parse/tiger-driver.cc')
-rw-r--r--tiger-compiler/src/parse/tiger-driver.cc215
1 files changed, 215 insertions, 0 deletions
diff --git a/tiger-compiler/src/parse/tiger-driver.cc b/tiger-compiler/src/parse/tiger-driver.cc
new file mode 100644
index 0000000..d26d11d
--- /dev/null
+++ b/tiger-compiler/src/parse/tiger-driver.cc
@@ -0,0 +1,215 @@
+/**
+ ** \file parse/tiger-driver.cc
+ ** \brief Implementation of parse::TigerDriver.
+ */
+
+#include <cstdlib>
+#include <fstream>
+
+#include <parse/parsetiger.hh>
+#include <parse/scantiger.hh>
+#include <parse/tiger-driver.hh>
+
+namespace parse
+{
+ TigerDriver::TigerDriver(const misc::file_library& lib)
+ : library_(lib)
+ {}
+
+ // Yes, this is exactly the default dtor. But because it is defined
+ // here, in the *.cc file, instead of "= default" in the *.hh file,
+ // there is no need for all the members to be complete defined in
+ // the header. In particular, the scanner_ member acts as a Pimpl,
+ // so we really want the generation of the dtor to be delayed to
+ // here, not in the header.
+ TigerDriver::~TigerDriver() = default;
+
+ /// Set the scanner traces.
+ TigerDriver& TigerDriver::scan_trace(bool b)
+ {
+ scan_trace_p_ = b;
+ return *this;
+ }
+
+ /// Set the parser traces.
+ TigerDriver& TigerDriver::parse_trace(bool b)
+ {
+ parse_trace_p_ = b;
+ return *this;
+ }
+
+ /// Enable object extensions.
+ TigerDriver& TigerDriver::enable_object_extensions(bool b)
+ {
+ enable_object_extensions_p_ = b;
+ return *this;
+ }
+
+ /// Enable assert extensions.
+ TigerDriver& TigerDriver::enable_assert_extensions(bool b)
+ {
+ enable_assert_extensions_p_ = b;
+ return *this;
+ }
+
+ /// Enable syntax extensions.
+ TigerDriver& TigerDriver::enable_extensions(bool b)
+ {
+ enable_extensions_p_ = b;
+ return *this;
+ }
+
+ /// Parse a Tiger file or string.
+ ast_type TigerDriver::parse_()
+ {
+ std::string* fn = std::get_if<std::string>(&input_);
+
+ /* The (address of) the string behind the symbol FILENAME is
+ guaranteed to remain valid even after the symbol has been
+ destroyed, so we can safely pass `&filename.name_get()' to
+ `location_.initialize()'. As for other symbols, the
+ corresponding string will be deallocated at the end of the
+ program. */
+ misc::symbol filename(fn == nullptr ? ""
+ : *fn == "-" ? "standard input"
+ : *fn);
+ location_.initialize(&filename.get());
+
+ std::shared_ptr<std::istream> in;
+ if (fn == nullptr)
+ // Parse a Tweast.
+ in = (std::make_shared<std::stringstream>(
+ std::get<Tweast*>(input_)->input_get()));
+ else if (*fn == "-")
+ // Parse from the standard input.
+ in.reset(&std::cin, [](...) {});
+ else
+ {
+ // Parse from a file.
+ in = std::make_shared<std::ifstream>(*fn);
+ if (in->fail())
+ error_ << misc::error::error_type::failure << program_name
+ << ": cannot open `" << filename << "': " << strerror(errno)
+ << std::endl
+ << &misc::error::exit;
+ }
+
+ // FIXME DONE: Some code was deleted here (Initialize Lexer and enable scan traces).
+ Lexer lexer(*in);
+ lexer.set_debug(scan_trace_p_);
+
+ // FIXME DONE: Some code was deleted here (Initialize the parser and enable parse traces).
+ parser parser(*this, lexer);
+ parser.set_debug_level(parse_trace_p_);
+
+ // FIXME DONE: Some code was deleted here (Run the parser).
+ parser.parse();
+
+ ast_type res = ast_;
+ ast_ = static_cast<ast::Exp*>(nullptr);
+
+ return res;
+ }
+
+ /*---------------.
+ | Parse a file. |
+ `---------------*/
+
+ ast_type TigerDriver::parse_file(const misc::path& name)
+ {
+ if (parse_trace_p_)
+ std::cerr << "Parsing file: " << name << '\n';
+ input_ = name.string();
+ return parse_();
+ }
+
+ /*----------------.
+ | Parse a Tweast. |
+ `----------------*/
+
+ ast_type TigerDriver::parse_input(Tweast& s, bool extensions)
+ {
+ std::swap(extensions, enable_extensions_p_);
+ // Merge all aggregated Tweasts into a single one.
+ s.flatten();
+ if (parse_trace_p_)
+ std::cerr << "Parsing string: " << s.input_get() << '\n';
+ input_ = &s;
+ ast_type res = parse_();
+ std::swap(extensions, enable_extensions_p_);
+ return res;
+ }
+
+ ast_type TigerDriver::parse(Tweast& s) { return parse_input(s, true); }
+
+ /*-----------------.
+ | Parse a string. |
+ `-----------------*/
+
+ ast_type TigerDriver::parse(const std::string& s)
+ {
+ Tweast in(s);
+ return parse_input(in, false);
+ }
+
+ /*-----------------------.
+ | Parse a Tiger import. |
+ `-----------------------*/
+
+ ast::ChunkList* TigerDriver::parse_import(const std::string& name,
+ const location& loc)
+ {
+ // Try to find directory containing the file to import.
+ misc::path directory_path = library_.find_file(name);
+
+ if (directory_path.empty())
+ {
+ error_ << misc::error::error_type::failure << loc << ": " << name
+ << ": file not found.\n";
+ return nullptr;
+ }
+
+ // Complete path of file (directory + filename).
+ misc::path absolute_path =
+ directory_path / misc::path(misc::path(name).filename());
+
+ // Detect recursive inclusion.
+ if (open_files_.find(absolute_path) != open_files_.end())
+ {
+ error_ << misc::error::error_type::failure << loc << ": " << name
+ << ": recursive inclusion.\n"
+ << open_files_[absolute_path]
+ << ": initial inclusion was here.\n";
+ return nullptr;
+ }
+
+ library_.push_current_directory(directory_path);
+ open_files_[absolute_path] = loc;
+ // Save the inputs, and reset them.
+ input_type saved_input = input_;
+ location saved_location = location_;
+ // Parse the imported file.
+ ast::ChunkList* res = nullptr;
+ try
+ {
+ res = parse_file(absolute_path);
+ }
+ catch (const std::bad_variant_access& e)
+ {
+ error_ << misc::error::error_type::parse << absolute_path
+ << ": imported from " << loc
+ << ": syntax error, unexpected exp, expecting chunks.\n";
+ error_.exit();
+ }
+ // Set the inputs back to their original values.
+ input_ = saved_input;
+ location_ = saved_location;
+
+ open_files_.erase(absolute_path);
+ library_.pop_current_directory();
+ return res;
+ }
+
+ const misc::error& TigerDriver::error_get() const { return error_; }
+
+} // namespace parse