yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Ellie Hermaszewskaformatf65d756bf

master
5.1 KiB158 linesraw
1// perfect-hash-main.cpp
2
3#include "../../source/compiler-core/slang-json-parser.h"
4#include "../../source/compiler-core/slang-json-value.h"
5#include "../../source/compiler-core/slang-lexer.h"
6#include "../../source/compiler-core/slang-perfect-hash-codegen.h"
7#include "../../source/core/slang-io.h"
8#include "../../source/core/slang-secure-crt.h"
9#include "../../source/core/slang-string-util.h"
10
11#include <stdio.h>
12
13using namespace Slang;
14
15static SlangResult parseJson(const char* inputPath, DiagnosticSink* sink, JSONListener& listener)
16{
17    auto sourceManager = sink->getSourceManager();
18
19    String contents;
20    SLANG_RETURN_ON_FAIL(File::readAllText(inputPath, contents));
21    PathInfo pathInfo = PathInfo::makeFromString(inputPath);
22    SourceFile* sourceFile = sourceManager->createSourceFileWithString(pathInfo, contents);
23    SourceView* sourceView = sourceManager->createSourceView(sourceFile, nullptr, SourceLoc());
24    JSONLexer lexer;
25    lexer.init(sourceView, sink);
26    JSONParser parser;
27    SLANG_RETURN_ON_FAIL(parser.parse(&lexer, sourceView, &listener, sink));
28    return SLANG_OK;
29}
30
31// Extract from a json value, the "opname" member from all the objects in the
32// "instructions" array.
33// Returns the empty list on failure
34static List<String> extractOpNames(
35    UnownedStringSlice& error,
36    const JSONValue& v,
37    JSONContainer& container)
38{
39    List<String> opnames;
40
41    // Wish we could just write à la jq
42    // List<String> result = match(myJSONValue, "instructions", AsArray, "opname", AsString);
43    const auto instKey = container.findKey(UnownedStringSlice("instructions"));
44    const auto opnameKey = container.findKey(UnownedStringSlice("opname"));
45    const auto aliasesKey = container.findKey(UnownedStringSlice("aliases"));
46    if (!instKey)
47    {
48        error = UnownedStringSlice("JSON parsing failed, no \"instructions\" key\n");
49        return {};
50    }
51    if (!opnameKey)
52    {
53        error = UnownedStringSlice("JSON parsing failed, no \"opname\" key\n");
54        return {};
55    }
56
57    const auto instructions = container.findObjectValue(v, instKey);
58    if (!instructions.isValid() || instructions.type != JSONValue::Type::Array)
59    {
60        error =
61            UnownedStringSlice("JSON parsing failed, no \"instructions\" member of array type\n");
62        return {};
63    }
64    for (const auto& inst : container.getArray(instructions))
65    {
66        const auto opname = container.findObjectValue(inst, opnameKey);
67        if (!opname.isValid() || opname.getKind() != JSONValue::Kind::String)
68        {
69            error = UnownedStringSlice(
70                "JSON parsing failed, no \"opname\" member of string type for instruction\n");
71            return {};
72        }
73        opnames.add(container.getString(opname));
74
75        if (aliasesKey)
76        {
77            auto aliases = container.findObjectValue(inst, aliasesKey);
78            if (aliases.isValid() && aliases.type == JSONValue::Type::Array)
79            {
80                for (auto& alias : container.getArray(aliases))
81                {
82                    opnames.add(container.getString(alias));
83                }
84            }
85        }
86    }
87
88    return opnames;
89}
90
91int main(int argc, const char* const* argv)
92{
93    using namespace Slang;
94
95    if (argc != 6)
96    {
97        fprintf(
98            stderr,
99            "Usage: %s input.grammar.json output.cpp enum-name enumerant-prefix enum-header-file\n",
100            argc >= 1 ? argv[0] : "slang-lookup-generator");
101        return 1;
102    }
103
104    const char* const inPath = argv[1];
105    const char* const outCppPath = argv[2];
106    const char* const enumName = argv[3];
107    const char* const enumerantPrefix = argv[4];
108    const char* const enumHeader = argv[5];
109
110    RefPtr<FileWriter> writer(new FileWriter(stderr, WriterFlag::AutoFlush));
111    SourceManager sourceManager;
112    sourceManager.initialize(nullptr, nullptr);
113    DiagnosticSink sink(&sourceManager, Lexer::sourceLocationLexer);
114    sink.writer = writer;
115
116    List<String> opnames;
117
118    if (String(inPath).endsWith("json"))
119    {
120        // If source is a json file parse it.
121        JSONContainer container(sink.getSourceManager());
122        JSONBuilder builder(&container);
123        if (SLANG_FAILED(parseJson(inPath, &sink, builder)))
124        {
125            sink.diagnoseRaw(Severity::Error, "Json parsing failed\n");
126            return 1;
127        }
128
129        UnownedStringSlice error;
130        opnames = extractOpNames(error, builder.getRootValue(), container);
131        if (error.getLength())
132        {
133            sink.diagnoseRaw(Severity::Error, error);
134            return 1;
135        }
136    }
137    else
138    {
139        // Otherwise, we assume the input is a text file with one name per line.
140        String content;
141        File::readAllText(inPath, content);
142        List<UnownedStringSlice> words;
143        StringUtil::split(content.getUnownedSlice(), '\n', words);
144        for (auto w : words)
145            opnames.add(w);
146    }
147
148    if (SLANG_FAILED(writePerfectHashLookupCppFile(
149            outCppPath,
150            opnames,
151            enumName,
152            enumerantPrefix,
153            enumHeader,
154            &sink)))
155        return -1;
156
157    return 0;
158}