Path: blob/a-new-beginning/SharedDependencies/Sources/nihstro/preprocessor.cpp
2 views
// Copyright 2015 Tony Wasserka1// All rights reserved.2//3// Redistribution and use in source and binary forms, with or without4// modification, are permitted provided that the following conditions are met:5//6// * Redistributions of source code must retain the above copyright7// notice, this list of conditions and the following disclaimer.8// * Redistributions in binary form must reproduce the above copyright9// notice, this list of conditions and the following disclaimer in the10// documentation and/or other materials provided with the distribution.11// * Neither the name of the owner nor the names of its contributors may12// be used to endorse or promote products derived from this software13// without specific prior written permission.14//15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS16// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT17// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR18// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT19// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT21// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,22// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY23// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT24// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE25// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.2627#include <nihstro/parser_assembly_private.h>28#include <nihstro/preprocessor.h>29#include <nihstro/source_tree.h>3031#include <boost/spirit/include/qi.hpp>3233#include <fstream>3435namespace nihstro {3637template<typename Iterator>38struct IncludeParser : qi::grammar<Iterator, std::string(), AssemblySkipper<Iterator>> {39using Skipper = AssemblySkipper<Iterator>;4041IncludeParser() : IncludeParser::base_type(include) {42include = qi::lexeme[qi::lit(".include") >> &qi::ascii::space]43> qi::lexeme[qi::lit("\"") > +qi::char_("a-zA-Z0-9./_\\-") > qi::lit("\"")]44> qi::omit[qi::eol | qi::eoi];45}4647qi::rule<Iterator, std::string(), Skipper> include;48};495051SourceTree PreprocessAssemblyFile(const std::string& filename) {52SourceTree tree;53tree.file_info.filename = filename;5455std::ifstream input_file(filename);56if (!input_file) {57throw std::runtime_error("Could not open input file " + filename);58}5960std::string prefix;61{62auto last_slash = filename.find_last_of("/");63if (last_slash != std::string::npos)64prefix = filename.substr(0, last_slash + 1);65}6667input_file.seekg(0, std::ios::end);68tree.code.resize(input_file.tellg());6970input_file.seekg(0, std::ios::beg);71input_file.read(&tree.code[0], tree.code.size());72input_file.close();7374auto cursor = tree.code.begin();7576IncludeParser<decltype(cursor)> include_parser;77AssemblySkipper<decltype(cursor)> skipper;7879while (cursor != tree.code.end()) {80std::string parsed_filename;81auto cursor_prev = cursor;82if (qi::phrase_parse(cursor, tree.code.end(), include_parser, skipper, parsed_filename)) {83if (parsed_filename[0] == '/')84throw std::runtime_error("Given filename must be relative to the path of the including file");8586// TODO: Protect against circular inclusions87auto newtree = PreprocessAssemblyFile(prefix + parsed_filename);88tree.Attach(newtree, cursor_prev - tree.code.begin());89cursor = tree.code.erase(cursor_prev, cursor);90cursor = tree.code.insert(cursor, '\n');91} else {92// Skip this line93qi::parse(cursor, tree.code.end(), *(qi::char_ - (qi::eol | qi::eoi)) >> (qi::eol | qi::eoi));94}95}96return tree;97}9899} // namespace100101102