#
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
set(sources ast.cpp
+ generate.cpp
generate_spirv_parser.cpp
parser.cpp)
add_executable(generate_spirv_parser ${sources})
--- /dev/null
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include "generate.h"
+
+namespace vulkan_cpu
+{
+namespace generate_spirv_parser
+{
+namespace generate
+{
+Generator::Generator_state::Generator_state(const Generator *generator,
+ Generator_args &generator_args)
+ : generator_args(generator_args),
+ indent_level(0),
+ full_output_file_name(generator_args.output_directory + "/"
+ + generator->output_base_file_name),
+ os()
+{
+ os.exceptions(std::ios::badbit | std::ios::failbit);
+}
+
+void Generator::Generator_state::open_output_file()
+{
+ os.open(full_output_file_name);
+}
+
+constexpr Generator::Indent_t Generator::indent;
+
+void Generator::write_indent(Generator_state &state)
+{
+ static constexpr auto indent_string = " ";
+ for(std::size_t i = state.indent_level; i > 0; i--)
+ state << indent_string;
+}
+
+void Generator::write_automatically_generated_file_warning(Generator_state &state)
+{
+ state << "/* This file is automatically generated by "
+ "generate_spirv_parser. DO NOT MODIFY. */\n";
+}
+
+void Generator::write_copyright_comment(Generator_state &state, const ast::Copyright ©right)
+{
+ state << "/*\n";
+ for(auto &line : copyright.lines)
+ {
+ if(line.empty())
+ {
+ state << " *\n";
+ continue;
+ }
+ state << " * ";
+ bool was_last_star = false;
+ for(char ch : line)
+ {
+ if(was_last_star && ch == '/')
+ state << ' ';
+ was_last_star = (ch == '*');
+ state << ch;
+ }
+ state << "\n";
+ }
+ state << " */\n";
+}
+
+struct Spirv_header_generator final : public Generator
+{
+ Spirv_header_generator() : Generator("spirv.h")
+ {
+ }
+ virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const override
+ {
+ Generator_state state(this, generator_args);
+ state.open_output_file();
+ write_file_comments(state, top_level.copyright);
+#warning finish
+ }
+};
+
+std::unique_ptr<Generator> Generators::make_spirv_header_generator()
+{
+ return std::unique_ptr<Generator>(new Spirv_header_generator);
+}
+}
+}
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef GENERATE_SPIRV_PARSER_GENERATE_H_
+#define GENERATE_SPIRV_PARSER_GENERATE_H_
+
+#include "ast.h"
+#include <fstream>
+#include <memory>
+#include <string>
+#include <cassert>
+#include <type_traits>
+
+namespace vulkan_cpu
+{
+namespace generate_spirv_parser
+{
+namespace generate
+{
+class Generator
+{
+public:
+ struct Generator_args
+ {
+ std::string output_directory;
+ explicit Generator_args(std::string output_directory) noexcept
+ : output_directory(std::move(output_directory))
+ {
+ }
+ Generator_args(Generator_args &&) = default;
+ Generator_args &operator=(Generator_args &&) = default;
+ Generator_args(const Generator_args &) = delete;
+ Generator_args &operator=(const Generator_args &) = delete;
+ };
+
+protected:
+ struct Generator_state
+ {
+ Generator_args &generator_args;
+ std::size_t indent_level;
+ std::string full_output_file_name;
+ std::ofstream os;
+ explicit Generator_state(const Generator *generator, Generator_args &generator_args);
+ void open_output_file();
+ template <typename T, typename = decltype(os << std::declval<T>())>
+ Generator_state &operator<<(T &&v)
+ {
+ os << std::forward<T>(v);
+ return *this;
+ }
+ };
+ class Push_indent final
+ {
+ Push_indent(const Push_indent &) = delete;
+ Push_indent &operator=(const Push_indent &) = delete;
+
+ private:
+ Generator_state *state;
+
+ public:
+ explicit Push_indent(Generator_state &state) noexcept : state(&state)
+ {
+ state.indent_level++;
+ }
+ Push_indent(Push_indent &&rt) noexcept : state(rt.state)
+ {
+ rt.state = nullptr;
+ }
+ void finish() noexcept
+ {
+ assert(state);
+ state->indent_level--;
+ state = nullptr;
+ }
+ ~Push_indent()
+ {
+ if(state)
+ state->indent_level--;
+ }
+ };
+ struct Indent_t
+ {
+ explicit Indent_t() = default;
+ friend Generator_state &operator<<(Generator_state &state, Indent_t)
+ {
+ write_indent(state);
+ return state;
+ }
+ };
+ static constexpr Indent_t indent{};
+
+protected:
+ const char *const output_base_file_name;
+
+protected:
+ static void write_indent(Generator_state &state);
+ static void write_automatically_generated_file_warning(Generator_state &state);
+ static void write_copyright_comment(Generator_state &state, const ast::Copyright ©right);
+ static void write_file_comments(Generator_state &state, const ast::Copyright ©right)
+ {
+ write_automatically_generated_file_warning(state);
+ write_copyright_comment(state, copyright);
+ }
+
+public:
+ explicit Generator(const char *output_base_file_name) noexcept
+ : output_base_file_name(output_base_file_name)
+ {
+ }
+ virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const = 0;
+ void run(Generator_args &&generator_args, const ast::Top_level &top_level) const
+ {
+ run(generator_args, top_level);
+ }
+
+public:
+ virtual ~Generator() = default;
+};
+
+struct Spirv_header_generator;
+
+struct Generators
+{
+ static std::unique_ptr<Generator> make_spirv_header_generator();
+};
+}
+}
+}
+
+#endif /* GENERATE_SPIRV_PARSER_GENERATE_H_ */
\ No newline at end of file
#include "../json/parser.h"
#include "parser.h"
#include "../util/optional.h"
-#include <fstream>
+#include "generate.h"
namespace vulkan_cpu
{
int generate_spirv_parser_main(int argc, char **argv)
{
std::string file_name;
+ std::string output_directory;
if(argc >= 2)
file_name = argv[1];
- if(argc != 2 || (file_name.size() > 1 && file_name[0] == '-'))
+ if(argc >= 3)
+ output_directory = argv[2];
+ if(argc != 3 || (file_name.size() > 1 && file_name[0] == '-')
+ || (output_directory.size() > 1 && output_directory[0] == '-'))
{
- std::cerr << "usage: " << argv[0] << " <input.json>" << std::endl;
+ std::cerr << "usage: " << argv[0] << " <input.json> <output-directory>" << std::endl;
return 1;
}
try
{
auto json_in = json::parse(&source);
auto ast = parser::parse(json_in.duplicate());
- std::ofstream os("out.json");
- auto json_out = ast.to_json();
- json::write(os, json_out, json::Write_options::pretty());
- os.close();
- auto difference = json::Difference::find_difference(json_in, json_out);
- if(difference)
+ for(auto &generator : {
+ generate::Generators::make_spirv_header_generator(),
+ })
{
- std::cerr << "differs at " << difference->append_to_string("root") << std::endl;
- }
- else
- {
- std::cerr << "no difference" << std::endl;
+ generator->run(generate::Generator::Generator_args(output_directory), ast);
}
#warning finish
std::cerr << "generate_spirv_parser is not finished being implemented" << std::endl;
set(sources spirv.cpp)
if(${do_generate_spirv_parser})
- set(spirv_parser_generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/src)
+ set(spirv_parser_generated_include_dir ${CMAKE_CURRENT_BINARY_DIR}/generated)
set(spirv_parser_generated_dir ${spirv_parser_generated_include_dir}/spirv)
- set(spirv_parser_source ${spirv_parser_generated_dir}/parser.cpp)
- set(spirv_parser_header ${spirv_parser_generated_dir}/parser.h)
+ set(spirv_parser_sources ${spirv_parser_generated_dir}/parser.cpp)
+ set(spirv_parser_headers ${spirv_parser_generated_dir}/parser.h ${spirv_parser_generated_dir}/spirv.h)
set(spirv_core_grammar_json ${CMAKE_CURRENT_SOURCE_DIR}/../khronos-spirv/spirv.core.grammar.json)
+ message(STATUS "spirv_parser_generated_dir: " ${spirv_parser_generated_dir})
- add_custom_command(OUTPUT ${spirv_parser_source} ${spirv_parser_header}
+ add_custom_command(OUTPUT ${spirv_parser_sources} ${spirv_parser_headers}
COMMAND ${CMAKE_COMMAND} -E make_directory ${spirv_parser_generated_dir}
- COMMAND ${CMAKE_COMMAND} -E chdir ${spirv_parser_generated_dir} $<TARGET_FILE:generate_spirv_parser> ${spirv_core_grammar_json}
+ COMMAND ${CMAKE_COMMAND} -E chdir ${spirv_parser_generated_dir} $<TARGET_FILE:generate_spirv_parser> ${spirv_core_grammar_json} ${spirv_parser_generated_dir}
MAIN_DEPENDENCY ${spirv_core_grammar_json}
DEPENDS $<TARGET_FILE:generate_spirv_parser>
VERBATIM
COMMENT "Generating SPIR-V Parser")
- set(sources ${sources} ${spirv_parser_source})
+ set(sources ${sources} ${spirv_parser_sources})
endif()
add_library(spirv STATIC ${sources})
target_link_libraries(spirv util)