yum-mirror/slang

Making it easier to work with shaders

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

Ellie HermaszewskaMove switch statement bodies to their own lines (#5493)b118451e3

master
6.6 KiB239 linesraw
1// slang-json-parser.h
2#ifndef SLANG_JSON_PARSER_H
3#define SLANG_JSON_PARSER_H
4
5#include "slang-json-lexer.h"
6
7
8namespace Slang
9{
10
11class JSONListener
12{
13public:
14    /// Start an object
15    virtual void startObject(SourceLoc loc) = 0;
16    /// End an object
17    virtual void endObject(SourceLoc loc) = 0;
18    /// Start an array
19    virtual void startArray(SourceLoc loc) = 0;
20    /// End and array
21    virtual void endArray(SourceLoc loc) = 0;
22
23
24    /// Add the key. Must be followed by addXXXValue.
25    virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) = 0;
26    virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) = 0;
27    /// Can be performed in an array or after an addLexemeKey in an object
28    virtual void addLexemeValue(
29        JSONTokenType type,
30        const UnownedStringSlice& value,
31        SourceLoc loc) = 0;
32
33    /// An integer value
34    virtual void addIntegerValue(int64_t value, SourceLoc loc) = 0;
35    /// Add a floating point value
36    virtual void addFloatValue(double value, SourceLoc loc) = 0;
37    /// Add a boolean value
38    virtual void addBoolValue(bool value, SourceLoc loc) = 0;
39
40    /// Add a string value. NOTE! string is unescaped/quoted
41    virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) = 0;
42
43    /// Add a null value
44    virtual void addNullValue(SourceLoc loc) = 0;
45};
46
47class JSONWriter : public JSONListener
48{
49public:
50    /*
51    https://en.wikipedia.org/wiki/Indentation_style
52    */
53    enum class IndentationStyle
54    {
55        Allman, ///< After every value, and opening, closing all other types
56        KNR,    ///< K&R like. Fields have CR.
57    };
58
59    enum class LocationType : uint8_t
60    {
61        Object,
62        Array,
63        Comma,
64    };
65
66    // NOTE! Order must be kept the same without fixing is functions below
67    enum class Location
68    {
69        BeforeOpenObject,
70        BeforeCloseObject,
71        AfterOpenObject,
72        AfterCloseObject,
73
74        BeforeOpenArray,
75        BeforeCloseArray,
76        AfterOpenArray,
77        AfterCloseArray,
78
79        FieldComma,
80        Comma,
81
82        CountOf,
83    };
84
85    static LocationType getLocationType(Location loc)
86    {
87        return isObject(loc) ? LocationType::Object
88                             : (isComma(loc) ? LocationType::Comma : LocationType::Array);
89    }
90
91    static bool isObjectLike(Location loc)
92    {
93        return Index(loc) <= Index(Location::AfterCloseArray);
94    }
95    static bool isObject(Location loc) { return Index(loc) <= Index(Location::AfterCloseObject); }
96    static bool isArray(Location loc)
97    {
98        return Index(loc) >= Index(Location::BeforeOpenArray) &&
99               Index(loc) <= Index(Location::AfterCloseArray);
100    }
101    static bool isComma(Location loc) { return Index(loc) >= Index(Location::FieldComma); }
102    static bool isOpen(Location loc) { return isObjectLike(loc) && (Index(loc) & 1) == 0; }
103    static bool isClose(Location loc) { return isObjectLike(loc) && (Index(loc) & 1) != 0; }
104    static bool isBefore(Location loc) { return isObjectLike(loc) && (Index(loc) & 2) == 0; }
105    static bool isAfter(Location loc) { return isObjectLike(loc) && (Index(loc) & 2) != 0; }
106
107    // Implement JSONListener
108    virtual void startObject(SourceLoc loc) SLANG_OVERRIDE;
109    virtual void endObject(SourceLoc loc) SLANG_OVERRIDE;
110    virtual void startArray(SourceLoc loc) SLANG_OVERRIDE;
111    virtual void endArray(SourceLoc loc) SLANG_OVERRIDE;
112    virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE;
113    virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE;
114    virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc)
115        SLANG_OVERRIDE;
116    virtual void addIntegerValue(int64_t value, SourceLoc loc) SLANG_OVERRIDE;
117    virtual void addFloatValue(double value, SourceLoc loc) SLANG_OVERRIDE;
118    virtual void addBoolValue(bool value, SourceLoc loc) SLANG_OVERRIDE;
119    virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) SLANG_OVERRIDE;
120    virtual void addNullValue(SourceLoc loc) SLANG_OVERRIDE;
121
122    /// Get the builder
123    StringBuilder& getBuilder() { return m_builder; }
124
125    JSONWriter(IndentationStyle format, Index lineLengthLimit = -1)
126    {
127        m_format = format;
128        m_lineLengthLimit = lineLengthLimit;
129
130        m_state.m_kind = State::Kind::Root;
131        m_state.m_flags = 0;
132    }
133
134protected:
135    struct State
136    {
137        enum class Kind : uint8_t
138        {
139            Root,
140            Object,
141            Array,
142        };
143
144        typedef uint8_t Flags;
145        struct Flag
146        {
147            enum Enum : Flags
148            {
149                HasPrevious = 0x01,
150                HasKey = 0x02,
151            };
152        };
153
154        bool canEmitValue() const
155        {
156            switch (m_kind)
157            {
158            case Kind::Root:
159                return (m_flags & Flag::HasPrevious) == 0;
160            case Kind::Array:
161                return true;
162            case Kind::Object:
163                return (m_flags & Flag::HasKey) != 0;
164            default:
165                return false;
166            }
167        }
168
169        Kind m_kind;
170        Flags m_flags;
171    };
172
173    void _maybeNextLine();
174    void _nextLine();
175    void _handleFormat(Location loc);
176
177    Index _getLineLengthAfterIndent();
178
179    /// Only emits the indent if at start of line
180    void _maybeEmitIndent();
181    void _emitIndent();
182
183    void _maybeEmitComma();
184    void _maybeEmitFieldComma();
185
186    void _preValue(SourceLoc loc);
187    void _postValue();
188
189    void _indent() { m_currentIndent++; }
190    void _dedent()
191    {
192        --m_currentIndent;
193        SLANG_ASSERT(m_currentIndent >= 0);
194    }
195
196    /// True if the line is indented at the required level
197    bool _hasIndent() { return m_emittedIndent >= 0 && m_emittedIndent == m_currentIndent; }
198
199    Index m_currentIndent = 0;
200    char m_indentChar = ' ';
201    Index m_indentCharCount = 4;
202
203    Index m_lineIndex = 0;
204    Index m_lineStart = 0;
205    Index m_emittedIndent = -1; /// If -1 for current line there is no indent emitted
206
207    Index m_lineLengthLimit = -1; /// The limit is only applied *AFTER* indentation
208
209    IndentationStyle m_format;
210
211    StringBuilder m_builder;
212    List<State> m_stack;
213    State m_state;
214};
215
216class JSONParser
217{
218public:
219    SlangResult parse(
220        JSONLexer* lexer,
221        SourceView* sourceView,
222        JSONListener* listener,
223        DiagnosticSink* sink);
224
225protected:
226    SlangResult _parseValue();
227    SlangResult _parseObject();
228    SlangResult _parseArray();
229
230    SourceView* m_sourceView;
231    DiagnosticSink* m_sink;
232    JSONListener* m_listener;
233    JSONLexer* m_lexer;
234};
235
236
237} // namespace Slang
238
239#endif