annotate osx/include/capnp/schema-parser.h @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
parents 0994c39f1e94
children
rev   line source
cannam@62 1 // Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
cannam@62 2 // Licensed under the MIT License:
cannam@62 3 //
cannam@62 4 // Permission is hereby granted, free of charge, to any person obtaining a copy
cannam@62 5 // of this software and associated documentation files (the "Software"), to deal
cannam@62 6 // in the Software without restriction, including without limitation the rights
cannam@62 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
cannam@62 8 // copies of the Software, and to permit persons to whom the Software is
cannam@62 9 // furnished to do so, subject to the following conditions:
cannam@62 10 //
cannam@62 11 // The above copyright notice and this permission notice shall be included in
cannam@62 12 // all copies or substantial portions of the Software.
cannam@62 13 //
cannam@62 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cannam@62 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cannam@62 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cannam@62 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cannam@62 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
cannam@62 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
cannam@62 20 // THE SOFTWARE.
cannam@62 21
cannam@62 22 #ifndef CAPNP_SCHEMA_PARSER_H_
cannam@62 23 #define CAPNP_SCHEMA_PARSER_H_
cannam@62 24
cannam@62 25 #if defined(__GNUC__) && !defined(CAPNP_HEADER_WARNINGS)
cannam@62 26 #pragma GCC system_header
cannam@62 27 #endif
cannam@62 28
cannam@62 29 #include "schema-loader.h"
cannam@62 30 #include <kj/string.h>
cannam@62 31
cannam@62 32 namespace capnp {
cannam@62 33
cannam@62 34 class ParsedSchema;
cannam@62 35 class SchemaFile;
cannam@62 36
cannam@62 37 class SchemaParser {
cannam@62 38 // Parses `.capnp` files to produce `Schema` objects.
cannam@62 39 //
cannam@62 40 // This class is thread-safe, hence all its methods are const.
cannam@62 41
cannam@62 42 public:
cannam@62 43 SchemaParser();
cannam@62 44 ~SchemaParser() noexcept(false);
cannam@62 45
cannam@62 46 ParsedSchema parseDiskFile(kj::StringPtr displayName, kj::StringPtr diskPath,
cannam@62 47 kj::ArrayPtr<const kj::StringPtr> importPath) const;
cannam@62 48 // Parse a file located on disk. Throws an exception if the file dosen't exist.
cannam@62 49 //
cannam@62 50 // Parameters:
cannam@62 51 // * `displayName`: The name that will appear in the file's schema node. (If the file has
cannam@62 52 // already been parsed, this will be ignored and the display name from the first time it was
cannam@62 53 // parsed will be kept.)
cannam@62 54 // * `diskPath`: The path to the file on disk.
cannam@62 55 // * `importPath`: Directories to search when resolving absolute imports within this file
cannam@62 56 // (imports that start with a `/`). Must remain valid until the SchemaParser is destroyed.
cannam@62 57 // (If the file has already been parsed, this will be ignored and the import path from the
cannam@62 58 // first time it was parsed will be kept.)
cannam@62 59 //
cannam@62 60 // This method is a shortcut, equivalent to:
cannam@62 61 // parser.parseFile(SchemaFile::newDiskFile(displayName, diskPath, importPath))`;
cannam@62 62 //
cannam@62 63 // This method throws an exception if any errors are encountered in the file or in anything the
cannam@62 64 // file depends on. Note that merely importing another file does not count as a dependency on
cannam@62 65 // anything in the imported file -- only the imported types which are actually used are
cannam@62 66 // "dependencies".
cannam@62 67
cannam@62 68 ParsedSchema parseFile(kj::Own<SchemaFile>&& file) const;
cannam@62 69 // Advanced interface for parsing a file that may or may not be located in any global namespace.
cannam@62 70 // Most users will prefer `parseDiskFile()`.
cannam@62 71 //
cannam@62 72 // If the file has already been parsed (that is, a SchemaFile that compares equal to this one
cannam@62 73 // was parsed previously), the existing schema will be returned again.
cannam@62 74 //
cannam@62 75 // This method reports errors by calling SchemaFile::reportError() on the file where the error
cannam@62 76 // is located. If that call does not throw an exception, `parseFile()` may in fact return
cannam@62 77 // normally. In this case, the result is a best-effort attempt to compile the schema, but it
cannam@62 78 // may be invalid or corrupt, and using it for anything may cause exceptions to be thrown.
cannam@62 79
cannam@62 80 template <typename T>
cannam@62 81 inline void loadCompiledTypeAndDependencies() {
cannam@62 82 // See SchemaLoader::loadCompiledTypeAndDependencies().
cannam@62 83 getLoader().loadCompiledTypeAndDependencies<T>();
cannam@62 84 }
cannam@62 85
cannam@62 86 private:
cannam@62 87 struct Impl;
cannam@62 88 class ModuleImpl;
cannam@62 89 kj::Own<Impl> impl;
cannam@62 90 mutable bool hadErrors = false;
cannam@62 91
cannam@62 92 ModuleImpl& getModuleImpl(kj::Own<SchemaFile>&& file) const;
cannam@62 93 SchemaLoader& getLoader();
cannam@62 94
cannam@62 95 friend class ParsedSchema;
cannam@62 96 };
cannam@62 97
cannam@62 98 class ParsedSchema: public Schema {
cannam@62 99 // ParsedSchema is an extension of Schema which also has the ability to look up nested nodes
cannam@62 100 // by name. See `SchemaParser`.
cannam@62 101
cannam@62 102 public:
cannam@62 103 inline ParsedSchema(): parser(nullptr) {}
cannam@62 104
cannam@62 105 kj::Maybe<ParsedSchema> findNested(kj::StringPtr name) const;
cannam@62 106 // Gets the nested node with the given name, or returns null if there is no such nested
cannam@62 107 // declaration.
cannam@62 108
cannam@62 109 ParsedSchema getNested(kj::StringPtr name) const;
cannam@62 110 // Gets the nested node with the given name, or throws an exception if there is no such nested
cannam@62 111 // declaration.
cannam@62 112
cannam@62 113 private:
cannam@62 114 inline ParsedSchema(Schema inner, const SchemaParser& parser): Schema(inner), parser(&parser) {}
cannam@62 115
cannam@62 116 const SchemaParser* parser;
cannam@62 117 friend class SchemaParser;
cannam@62 118 };
cannam@62 119
cannam@62 120 // =======================================================================================
cannam@62 121 // Advanced API
cannam@62 122
cannam@62 123 class SchemaFile {
cannam@62 124 // Abstract interface representing a schema file. You can implement this yourself in order to
cannam@62 125 // gain more control over how the compiler resolves imports and reads files. For the
cannam@62 126 // common case of files on disk or other global filesystem-like namespaces, use
cannam@62 127 // `SchemaFile::newDiskFile()`.
cannam@62 128
cannam@62 129 public:
cannam@62 130 class FileReader {
cannam@62 131 public:
cannam@62 132 virtual bool exists(kj::StringPtr path) const = 0;
cannam@62 133 virtual kj::Array<const char> read(kj::StringPtr path) const = 0;
cannam@62 134 };
cannam@62 135
cannam@62 136 class DiskFileReader final: public FileReader {
cannam@62 137 // Implementation of FileReader that uses the local disk. Files are read using mmap() if
cannam@62 138 // possible.
cannam@62 139
cannam@62 140 public:
cannam@62 141 static const DiskFileReader instance;
cannam@62 142
cannam@62 143 bool exists(kj::StringPtr path) const override;
cannam@62 144 kj::Array<const char> read(kj::StringPtr path) const override;
cannam@62 145 };
cannam@62 146
cannam@62 147 static kj::Own<SchemaFile> newDiskFile(
cannam@62 148 kj::StringPtr displayName, kj::StringPtr diskPath,
cannam@62 149 kj::ArrayPtr<const kj::StringPtr> importPath,
cannam@62 150 const FileReader& fileReader = DiskFileReader::instance);
cannam@62 151 // Construct a SchemaFile representing a file on disk (or located in the filesystem-like
cannam@62 152 // namespace represented by `fileReader`).
cannam@62 153 //
cannam@62 154 // Parameters:
cannam@62 155 // * `displayName`: The name that will appear in the file's schema node.
cannam@62 156 // * `diskPath`: The path to the file on disk.
cannam@62 157 // * `importPath`: Directories to search when resolving absolute imports within this file
cannam@62 158 // (imports that start with a `/`). The array content must remain valid as long as the
cannam@62 159 // SchemaFile exists (which is at least as long as the SchemaParser that parses it exists).
cannam@62 160 // * `fileReader`: Allows you to use a filesystem other than the actual local disk. Although,
cannam@62 161 // if you find yourself using this, it may make more sense for you to implement SchemaFile
cannam@62 162 // yourself.
cannam@62 163 //
cannam@62 164 // The SchemaFile compares equal to any other SchemaFile that has exactly the same disk path,
cannam@62 165 // after canonicalization.
cannam@62 166 //
cannam@62 167 // The SchemaFile will throw an exception if any errors are reported.
cannam@62 168
cannam@62 169 // -----------------------------------------------------------------
cannam@62 170 // For more control, you can implement this interface.
cannam@62 171
cannam@62 172 virtual kj::StringPtr getDisplayName() const = 0;
cannam@62 173 // Get the file's name, as it should appear in the schema.
cannam@62 174
cannam@62 175 virtual kj::Array<const char> readContent() const = 0;
cannam@62 176 // Read the file's entire content and return it as a byte array.
cannam@62 177
cannam@62 178 virtual kj::Maybe<kj::Own<SchemaFile>> import(kj::StringPtr path) const = 0;
cannam@62 179 // Resolve an import, relative to this file.
cannam@62 180 //
cannam@62 181 // `path` is exactly what appears between quotes after the `import` keyword in the source code.
cannam@62 182 // It is entirely up to the `SchemaFile` to decide how to map this to another file. Typically,
cannam@62 183 // a leading '/' means that the file is an "absolute" path and is searched for in some list of
cannam@62 184 // schema file repositories. On the other hand, a path that doesn't start with '/' is relative
cannam@62 185 // to the importing file.
cannam@62 186
cannam@62 187 virtual bool operator==(const SchemaFile& other) const = 0;
cannam@62 188 virtual bool operator!=(const SchemaFile& other) const = 0;
cannam@62 189 virtual size_t hashCode() const = 0;
cannam@62 190 // Compare two SchemaFiles to see if they refer to the same underlying file. This is an
cannam@62 191 // optimization used to avoid the need to re-parse a file to check its ID.
cannam@62 192
cannam@62 193 struct SourcePos {
cannam@62 194 uint byte;
cannam@62 195 uint line;
cannam@62 196 uint column;
cannam@62 197 };
cannam@62 198 virtual void reportError(SourcePos start, SourcePos end, kj::StringPtr message) const = 0;
cannam@62 199 // Report that the file contains an error at the given interval.
cannam@62 200
cannam@62 201 private:
cannam@62 202 class DiskSchemaFile;
cannam@62 203 };
cannam@62 204
cannam@62 205 } // namespace capnp
cannam@62 206
cannam@62 207 #endif // CAPNP_SCHEMA_PARSER_H_