1 /*
2 *
3 * Copyright (c) 2022, Masatake YAMATO
4 * Copyright (c) 2022, Red Hat, K.K.
5 *
6 * This source code is released for free distribution under the terms of the
7 * GNU General Public License version 2 or (at your option) any later version.
8 *
9 * This module contains functions for extracting language objects in FrontMatter
10 * using Yaml.
11 *
12 * https://gohugo.io/content-management/front-matter
13 */
14
15 /*
16 * INCLUDE FILES
17 */
18 #include "general.h" /* must always come first */
19
20 #include "frontmatter.h"
21 #include "yaml.h"
22
23 #include "entry.h"
24 #include "gcc-attr.h"
25 #include "parse.h"
26 #include "read.h"
27 #include "subparser.h"
28 #include "trace.h"
29
30
31 /*
32 * DATA DECLARATIONS
33 */
34 enum yamlfrontmatterDetectingState {
35 DSTAT_LAST_KEY,
36 DSTAT_LAST_VALUE,
37 DSTAT_INITIAL,
38 };
39
40 struct sYamlFrontMatterSubparser {
41 yamlSubparser yaml;
42 enum yamlfrontmatterDetectingState detection_state;
43 };
44
45
46 /*
47 * FUNCTION PROTOTYPES
48 */
49 static bool yamlFrontmattterInitTagEntry (tagEntryInfo *e, char *name, void *data);
50
51
52 /*
53 * DATA DEFINITIONS
54 */
55
56 static langType frontMatterLang;
57
58 static tagYpathTable ypathTables [] = {
59 {
60 "title",
61 DSTAT_LAST_VALUE,
62 .initTagEntry = yamlFrontmattterInitTagEntry,
63 },
64 };
65
66
67 /*
68 * FUNCTION DEFINITIONS
69 */
70
yamlfrontmatterStateMachine(struct sYamlFrontMatterSubparser * yamlfrontmatter,yaml_token_t * token)71 static void yamlfrontmatterStateMachine (struct sYamlFrontMatterSubparser *yamlfrontmatter,
72 yaml_token_t *token)
73 {
74 #ifdef DO_TRACING
75 ypathPrintTypeStack (YAML(yamlfrontmatter));
76 #endif
77
78 switch (token->type)
79 {
80 case YAML_KEY_TOKEN:
81 yamlfrontmatter->detection_state = DSTAT_LAST_KEY;
82 break;
83 case YAML_SCALAR_TOKEN:
84 switch (yamlfrontmatter->detection_state)
85 {
86 case DSTAT_LAST_KEY:
87 ypathFillKeywordOfTokenMaybe (YAML(yamlfrontmatter), token, getInputLanguage ());
88 /* FALL THROUGH */
89 case DSTAT_LAST_VALUE:
90 TRACE_PRINT("token-callback: %s: %s",
91 (yamlfrontmatter->detection_state == DSTAT_LAST_KEY)? "key": "value",
92 (char*)token->data.scalar.value);
93 ypathHandleToken (YAML(yamlfrontmatter), token, yamlfrontmatter->detection_state,
94 ypathTables, ARRAY_SIZE (ypathTables));
95 break;
96 default:
97 break;
98 }
99
100 yamlfrontmatter->detection_state = DSTAT_INITIAL;
101
102 break;
103 case YAML_VALUE_TOKEN:
104 yamlfrontmatter->detection_state = DSTAT_LAST_VALUE;
105 break;
106
107 default:
108 yamlfrontmatter->detection_state = DSTAT_INITIAL;
109 break;
110 }
111 }
112
newTokenCallback(yamlSubparser * s,yaml_token_t * token)113 static void newTokenCallback (yamlSubparser *s, yaml_token_t *token)
114 {
115 if (token->type == YAML_BLOCK_SEQUENCE_START_TOKEN
116 || token->type == YAML_BLOCK_MAPPING_START_TOKEN)
117 ypathPushType (s, token);
118
119 yamlfrontmatterStateMachine ((struct sYamlFrontMatterSubparser *)s, token);
120
121 if (token->type == YAML_BLOCK_END_TOKEN)
122 ypathPopType (s);
123 else if (token->type == YAML_STREAM_END_TOKEN)
124 ypathPopAllTypes (s);
125 }
126
yamlFrontmattterInitTagEntry(tagEntryInfo * e,char * name,void * data CTAGS_ATTR_UNUSED)127 static bool yamlFrontmattterInitTagEntry (tagEntryInfo *e, char *name, void * data CTAGS_ATTR_UNUSED)
128 {
129 initForeignTagEntry (e, name, frontMatterLang, FRONTMATTER_TITLE_KIND);
130 return true;
131 }
132
yamlFrontMatterInputStart(subparser * s)133 static void yamlFrontMatterInputStart(subparser *s)
134 {
135 ((struct sYamlFrontMatterSubparser*)s)->detection_state = DSTAT_INITIAL;
136 ((yamlSubparser*)s)->ypathTypeStack = NULL;
137 }
138
yamlFrontMatterInputEnd(subparser * s)139 static void yamlFrontMatterInputEnd(subparser *s)
140 {
141 Assert (((yamlSubparser*)s)->ypathTypeStack == NULL);
142 }
143
findYamlFrontMatterTags(void)144 static void findYamlFrontMatterTags (void)
145 {
146 scheduleRunningBaseparser (0);
147 }
148
yamlFrontMatterInitialize(langType language)149 static void yamlFrontMatterInitialize (langType language)
150 {
151 ypathCompileTables (language, ypathTables, ARRAY_SIZE (ypathTables), 0);
152 frontMatterLang = getNamedLanguage ("FrontMatter", 0);
153 }
154
yamlFrontMatterFinalize(langType language,bool initialized)155 static void yamlFrontMatterFinalize (langType language, bool initialized)
156 {
157 if (initialized)
158 ypathCompiledCodeDelete (ypathTables, ARRAY_SIZE (ypathTables));
159 }
160
YamlFrontMatter(void)161 extern parserDefinition* YamlFrontMatter (void)
162 {
163 static struct sYamlFrontMatterSubparser yamlfrontmatterSubparser = {
164 .yaml = {
165 .subparser = {
166 .direction = SUBPARSER_SUB_RUNS_BASE,
167 .inputStart = yamlFrontMatterInputStart,
168 .inputEnd = yamlFrontMatterInputEnd,
169 },
170 .newTokenNotfify = newTokenCallback
171 },
172 };
173 static parserDependency dependencies [] = {
174 { DEPTYPE_SUBPARSER, "Yaml", &yamlfrontmatterSubparser },
175 { DEPTYPE_FOREIGNER, "FrontMatter", NULL },
176 };
177
178 parserDefinition* const def = parserNew ("YamlFrontMatter");
179
180 def->dependencies = dependencies;
181 def->dependencyCount = ARRAY_SIZE (dependencies);
182
183 def->kindTable = NULL;
184 def->kindCount = 0;
185 def->parser = findYamlFrontMatterTags;
186 def->initialize = yamlFrontMatterInitialize;
187 def->finalize = yamlFrontMatterFinalize;
188
189 /* This parser runs ONLY as a part of FrontMatter parser.
190 * User may not want to enable/disable this parser directly. */
191 def->invisible = true;
192
193 return def;
194 }
195