Skip to content

Commit ffa6193

Browse files
committed
Yaml,OpenAPI: make the OpenAPI parser's stack related code reusable
The technique used in the OpenAPI may be helpful to implement another YAML subparser. So, I moved the code implementing the technique to the YAML parser experimentally in this change. The original code uses an array of keywords for pointing out interesting tokens. This change uses a string for the same purpose. The routines in this change convert the string to an array of keywords. Till a real specification and its implementation becomes available, we call the format of the string Ypath. Signed-off-by: Masatake YAMATO <[email protected]>
1 parent 63383cc commit ffa6193

File tree

3 files changed

+248
-276
lines changed

3 files changed

+248
-276
lines changed

parsers/openapi.c

Lines changed: 47 additions & 276 deletions
Original file line numberDiff line numberDiff line change
@@ -41,41 +41,6 @@ static kindDefinition OpenAPIKinds [] = {
4141
{ true, 's', "server", "servers (or hosts in swagger)" },
4242
};
4343

44-
#define KEY_UNKNOWN KEYWORD_NONE
45-
enum openapiKeys {
46-
KEY_PATHS,
47-
KEY_COMPONENTS,
48-
KEY_SCHEMAS,
49-
KEY_PARAMETERS,
50-
KEY_RESPONSES,
51-
KEY_DEFINITIONS,
52-
KEY_INFO,
53-
KEY_TITLE,
54-
KEY_SERVERS,
55-
KEY_URL,
56-
KEY_HOST,
57-
};
58-
59-
static const keywordTable OpenAPIKeywordTable[] = {
60-
{ "paths", KEY_PATHS },
61-
{ "components", KEY_COMPONENTS },
62-
{ "schemas", KEY_SCHEMAS },
63-
{ "parameters", KEY_PARAMETERS },
64-
{ "responses", KEY_RESPONSES },
65-
{ "definitions", KEY_DEFINITIONS },
66-
{ "info", KEY_INFO },
67-
{ "title", KEY_TITLE },
68-
{ "servers", KEY_SERVERS },
69-
{ "url", KEY_URL },
70-
{ "host", KEY_HOST },
71-
};
72-
73-
struct yamlBlockTypeStack {
74-
yaml_token_type_t type;
75-
enum openapiKeys key;
76-
struct yamlBlockTypeStack *next;
77-
};
78-
7944
/* - name: "THE NAME" */
8045
enum openapiPlayDetectingState {
8146
DSTAT_LAST_KEY,
@@ -86,238 +51,37 @@ enum openapiPlayDetectingState {
8651

8752
struct sOpenAPISubparser {
8853
yamlSubparser yaml;
89-
struct yamlBlockTypeStack *type_stack;
9054
enum openapiPlayDetectingState play_detection_state;
9155
};
9256

93-
static void pushBlockType (struct sOpenAPISubparser *openapi, yaml_token_type_t t)
94-
{
95-
struct yamlBlockTypeStack *s;
96-
97-
s = xMalloc (1, struct yamlBlockTypeStack);
98-
99-
s->next = openapi->type_stack;
100-
openapi->type_stack = s;
101-
102-
s->type = t;
103-
s->key = KEY_UNKNOWN;
104-
}
105-
106-
static void popBlockType (struct sOpenAPISubparser *openapi)
107-
{
108-
struct yamlBlockTypeStack *s;
109-
110-
s = openapi->type_stack;
111-
openapi->type_stack = s->next;
112-
113-
s->next = NULL;
114-
115-
eFree (s);
116-
}
117-
118-
static void popAllBlockType (struct sOpenAPISubparser *openapi)
119-
{
120-
while (openapi->type_stack)
121-
popBlockType (openapi);
122-
}
123-
124-
static bool stateStackMatch (struct yamlBlockTypeStack *stack,
125-
const enum openapiKeys *expectation,
126-
unsigned int length)
127-
{
128-
if (length == 0)
129-
{
130-
if (stack == NULL)
131-
return true;
132-
else
133-
return false;
134-
}
135-
136-
if (stack == NULL)
137-
return false;
138-
139-
if (stack->key == expectation[0])
140-
return stateStackMatch (stack->next, expectation + 1, length - 1);
141-
else
142-
return false;
143-
}
144-
145-
static enum openapiKeys parseKey(yaml_token_t *token)
146-
{
147-
static langType langType = LANG_IGNORE;
148-
if (langType == LANG_IGNORE)
149-
langType = getInputLanguage ();
150-
151-
return lookupKeyword ((char *)token->data.scalar.value, langType);
152-
}
153-
154-
#ifdef DO_TRACING
155-
static void printStack(struct yamlBlockTypeStack* stack)
156-
{
157-
if (!stack)
158-
{
159-
TRACE_PRINT_NEWLINE();
160-
return;
161-
}
162-
163-
tracePrintFmt("[%d] - ", stack->key);
164-
printStack(stack->next);
165-
}
166-
#endif
167-
168-
struct tagSource {
169-
openapiKind kind;
170-
const enum openapiKeys* keys;
171-
size_t countKeys;
172-
};
173-
174-
static const enum openapiKeys pathKeys[] = {
175-
KEY_UNKNOWN,
176-
KEY_PATHS,
177-
};
178-
179-
static const enum openapiKeys responses3Keys[] = {
180-
KEY_UNKNOWN,
181-
KEY_RESPONSES,
182-
KEY_COMPONENTS,
183-
};
184-
185-
static const enum openapiKeys responses2Keys[] = {
186-
KEY_UNKNOWN,
187-
KEY_RESPONSES,
188-
};
189-
190-
static const enum openapiKeys parameters3Keys[] = {
191-
KEY_UNKNOWN,
192-
KEY_PARAMETERS,
193-
KEY_COMPONENTS,
194-
};
195-
196-
static const enum openapiKeys parameters2Keys[] = {
197-
KEY_UNKNOWN,
198-
KEY_PARAMETERS,
57+
static tagYpathTable ypathTables [] = {
58+
{ "paths/*",
59+
DSTAT_LAST_KEY, KIND_PATH, },
60+
{ "components/responses/*",
61+
DSTAT_LAST_KEY, KIND_RESPONSE, },
62+
{ "responses/*",
63+
DSTAT_LAST_KEY, KIND_RESPONSE, },
64+
{ "components/parameters/*",
65+
DSTAT_LAST_KEY, KIND_PARAMETER, },
66+
{ "parameters/*",
67+
DSTAT_LAST_KEY, KIND_PARAMETER, },
68+
{ "components/schemas/*",
69+
DSTAT_LAST_KEY, KIND_SCHEMA, },
70+
{ "definitions/*",
71+
DSTAT_LAST_KEY, KIND_SCHEMA, },
72+
{ "info/title",
73+
DSTAT_LAST_VALUE, KIND_TITLE, },
74+
{ "servers/*/url",
75+
DSTAT_LAST_VALUE, KIND_SERVER, },
76+
{ "host",
77+
DSTAT_LAST_VALUE, KIND_SERVER, },
19978
};
20079

201-
static const enum openapiKeys schemas3Keys[] = {
202-
KEY_UNKNOWN,
203-
KEY_SCHEMAS,
204-
KEY_COMPONENTS,
205-
};
206-
207-
static const enum openapiKeys definitions2Keys[] = {
208-
KEY_UNKNOWN,
209-
KEY_DEFINITIONS,
210-
};
211-
212-
static const enum openapiKeys title3Keys[] = {
213-
KEY_TITLE,
214-
KEY_INFO,
215-
};
216-
217-
static const enum openapiKeys server3Keys[] = {
218-
KEY_URL,
219-
KEY_UNKNOWN,
220-
KEY_SERVERS,
221-
};
222-
223-
static const enum openapiKeys host2Keys[] = {
224-
KEY_HOST,
225-
};
226-
227-
static const struct tagSource tagSources[] = {
228-
{
229-
KIND_PATH,
230-
pathKeys,
231-
ARRAY_SIZE (pathKeys),
232-
},
233-
{
234-
KIND_RESPONSE,
235-
responses3Keys,
236-
ARRAY_SIZE (responses3Keys),
237-
},
238-
{
239-
KIND_RESPONSE,
240-
responses2Keys,
241-
ARRAY_SIZE (responses2Keys),
242-
},
243-
{
244-
KIND_PARAMETER,
245-
parameters3Keys,
246-
ARRAY_SIZE (parameters3Keys),
247-
},
248-
{
249-
KIND_PARAMETER,
250-
parameters2Keys,
251-
ARRAY_SIZE (parameters2Keys),
252-
},
253-
{
254-
KIND_SCHEMA,
255-
schemas3Keys,
256-
ARRAY_SIZE (schemas3Keys),
257-
},
258-
{
259-
KIND_SCHEMA,
260-
definitions2Keys,
261-
ARRAY_SIZE (definitions2Keys),
262-
},
263-
};
264-
265-
static const struct tagSource tagValueSources[] = {
266-
{
267-
KIND_TITLE,
268-
title3Keys,
269-
ARRAY_SIZE (title3Keys),
270-
},
271-
{
272-
KIND_SERVER,
273-
server3Keys,
274-
ARRAY_SIZE (server3Keys),
275-
},
276-
{
277-
KIND_SERVER,
278-
host2Keys,
279-
ARRAY_SIZE (host2Keys),
280-
}
281-
};
282-
283-
static void handleToken(struct sOpenAPISubparser *openapi, yaml_token_t *token,
284-
const struct tagSource *tss, size_t ts_count)
285-
{
286-
for (int i = 0; i < ts_count; i++)
287-
{
288-
const struct tagSource* ts = &tss[i];
289-
290-
if (stateStackMatch(openapi->type_stack,
291-
ts->keys, ts->countKeys))
292-
{
293-
294-
tagEntryInfo tag;
295-
initTagEntry (&tag, (char *)token->data.scalar.value, ts->kind);
296-
attachYamlPosition (&tag, token, false);
297-
298-
makeTagEntry (&tag);
299-
break;
300-
}
301-
}
302-
}
303-
304-
static void handleKey(struct sOpenAPISubparser *openapi,
305-
yaml_token_t *token)
306-
{
307-
handleToken (openapi, token, tagSources, ARRAY_SIZE (tagSources));
308-
}
309-
310-
static void handleValue(struct sOpenAPISubparser *openapi,
311-
yaml_token_t *token)
312-
{
313-
handleToken (openapi, token, tagValueSources, ARRAY_SIZE (tagValueSources));
314-
}
315-
31680
static void openapiPlayStateMachine (struct sOpenAPISubparser *openapi,
31781
yaml_token_t *token)
31882
{
31983
#ifdef DO_TRACING
320-
printStack(openapi->type_stack);
84+
ypathPrintTypeStack (YAML(openapi));
32185
#endif
32286

32387
switch (token->type)
@@ -329,17 +93,14 @@ static void openapiPlayStateMachine (struct sOpenAPISubparser *openapi,
32993
switch (openapi->play_detection_state)
33094
{
33195
case DSTAT_LAST_KEY:
332-
TRACE_PRINT(" key: %s", (char*)token->data.scalar.value);
333-
if (openapi->type_stack)
334-
{
335-
openapi->type_stack->key = parseKey(token);
336-
handleKey (openapi, token);
337-
}
338-
break;
96+
ypathFillKeywordOfTokenMaybe (YAML(openapi), token, getInputLanguage ());
97+
/* FALL THROUGH */
33998
case DSTAT_LAST_VALUE:
340-
TRACE_PRINT(" value: %s", (char*)token->data.scalar.value);
341-
if (openapi->type_stack)
342-
handleValue (openapi, token);
99+
TRACE_PRINT("token-callback: %s: %s",
100+
(openapi->play_detection_state == DSTAT_LAST_KEY)? "key": "value",
101+
(char*)token->data.scalar.value);
102+
ypathHandleToken (YAML(openapi), token, openapi->play_detection_state,
103+
ypathTables, ARRAY_SIZE (ypathTables));
343104
break;
344105
default:
345106
break;
@@ -362,32 +123,43 @@ static void newTokenCallback (yamlSubparser *s, yaml_token_t *token)
362123
{
363124
if (token->type == YAML_BLOCK_SEQUENCE_START_TOKEN
364125
|| token->type == YAML_BLOCK_MAPPING_START_TOKEN)
365-
pushBlockType ((struct sOpenAPISubparser *)s, token->type);
126+
ypathPushType (s, token);
366127

367128
openapiPlayStateMachine ((struct sOpenAPISubparser *)s, token);
368129

369130
if (token->type == YAML_BLOCK_END_TOKEN)
370-
popBlockType ((struct sOpenAPISubparser *)s);
131+
ypathPopType (s);
371132
else if (token->type == YAML_STREAM_END_TOKEN)
372-
popAllBlockType ((struct sOpenAPISubparser *)s);
133+
ypathPopAllTypes (s);
373134
}
374135

375136
static void inputStart(subparser *s)
376137
{
377138
((struct sOpenAPISubparser*)s)->play_detection_state = DSTAT_INITIAL;
378-
((struct sOpenAPISubparser*)s)->type_stack = NULL;
139+
((yamlSubparser*)s)->ypathTypeStack = NULL;
379140
}
380141

381142
static void inputEnd(subparser *s)
382143
{
383-
Assert (((struct sOpenAPISubparser*)s)->type_stack == NULL);
144+
Assert (((yamlSubparser*)s)->ypathTypeStack == NULL);
384145
}
385146

386147
static void findOpenAPITags (void)
387148
{
388149
scheduleRunningBaseparser (0);
389150
}
390151

152+
static void initialize (langType language)
153+
{
154+
ypathCompileTables (language, ypathTables, ARRAY_SIZE (ypathTables), 0);
155+
}
156+
157+
static void finalize (langType language, bool initialized)
158+
{
159+
if (initialized)
160+
ypathCompiledCodeDelete (ypathTables, ARRAY_SIZE (ypathTables));
161+
}
162+
391163
extern parserDefinition* OpenAPIParser (void)
392164
{
393165
static const char *const patterns [] = { "openapi.yaml", NULL };
@@ -412,11 +184,10 @@ extern parserDefinition* OpenAPIParser (void)
412184
def->dependencies = dependencies;
413185
def->dependencyCount = ARRAY_SIZE (dependencies);
414186

415-
def->keywordTable = OpenAPIKeywordTable;
416-
def->keywordCount = ARRAY_SIZE (OpenAPIKeywordTable);
417-
418187
def->kindTable = OpenAPIKinds;
419188
def->kindCount = ARRAY_SIZE (OpenAPIKinds);
420189
def->parser = findOpenAPITags;
190+
def->initialize = initialize;
191+
def->finalize = finalize;
421192
return def;
422193
}

0 commit comments

Comments
 (0)