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