xref: /Universal-ctags/parsers/tex-beamer.c (revision 3671ad7255885a0c8f6ff4979d80c70f201ea411)
1942142faSMasatake YAMATO /*
2942142faSMasatake YAMATO  *	 Copyright (c) 2020, Masatake YAMATO
3942142faSMasatake YAMATO  *
4942142faSMasatake YAMATO  *	 This source code is released for free distribution under the terms of the
5942142faSMasatake YAMATO  *	 GNU General Public License version 2 or (at your option) any later version.
6942142faSMasatake YAMATO  *
7942142faSMasatake YAMATO  *	 This module contains functions for generating tags for Beamer class of TeX.
8942142faSMasatake YAMATO  *   - https://github.com/josephwright/beamer
9942142faSMasatake YAMATO  *   - http://mirrors.ibiblio.org/CTAN/macros/latex/contrib/beamer/doc/beameruserguide.pdf
10942142faSMasatake YAMATO  *
11942142faSMasatake YAMATO  */
12942142faSMasatake YAMATO 
13942142faSMasatake YAMATO /*
14942142faSMasatake YAMATO  *	 INCLUDE FILES
15942142faSMasatake YAMATO  */
16942142faSMasatake YAMATO 
17942142faSMasatake YAMATO #include "general.h"  /* must always come first */
18942142faSMasatake YAMATO 
19942142faSMasatake YAMATO #include "entry.h"
20942142faSMasatake YAMATO #include "kind.h"
21942142faSMasatake YAMATO #include "parse.h"
22942142faSMasatake YAMATO #include "read.h"
23942142faSMasatake YAMATO #include "tex.h"
24942142faSMasatake YAMATO 
25942142faSMasatake YAMATO #include <string.h>
26942142faSMasatake YAMATO 
27942142faSMasatake YAMATO 
28942142faSMasatake YAMATO /*
29942142faSMasatake YAMATO  *	 DATA DECLARATIONS
30942142faSMasatake YAMATO  */
31942142faSMasatake YAMATO 
32942142faSMasatake YAMATO struct beamerSubparser {
33942142faSMasatake YAMATO 	texSubparser tex;
34942142faSMasatake YAMATO 	int lastTitleCorkIndex;
35942142faSMasatake YAMATO };
36942142faSMasatake YAMATO 
37942142faSMasatake YAMATO enum BamerKind {
38942142faSMasatake YAMATO 	K_FRAMETITLE,
39942142faSMasatake YAMATO 	K_FRAMESUBTITLE,
40942142faSMasatake YAMATO };
41942142faSMasatake YAMATO 
42942142faSMasatake YAMATO 
43942142faSMasatake YAMATO /*
44942142faSMasatake YAMATO  *	 DATA DEFINITIONS
45942142faSMasatake YAMATO  */
46942142faSMasatake YAMATO 
47942142faSMasatake YAMATO static kindDefinition beamerKinds[] = {
48942142faSMasatake YAMATO 	{ true, 'f', "frametitle", "frametitles" },
49942142faSMasatake YAMATO 	{ true, 'g', "framesubtitle", "framesubtitles"},
50942142faSMasatake YAMATO };
51942142faSMasatake YAMATO 
52942142faSMasatake YAMATO /* \frametitle<overlay specification>[short frame title]{frame title text} */
53942142faSMasatake YAMATO static struct TexParseStrategy frametitle_strategy[] = {
54942142faSMasatake YAMATO 	{
55942142faSMasatake YAMATO 		.type = '<',
56942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_OPTIONAL,
57942142faSMasatake YAMATO 		.kindIndex = KIND_GHOST_INDEX,
58942142faSMasatake YAMATO 		.name = NULL,
59942142faSMasatake YAMATO 	},
60942142faSMasatake YAMATO 	{
61942142faSMasatake YAMATO 		.type = '[',
62942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_OPTIONAL|TEX_NAME_FLAG_EXCLUSIVE,
63942142faSMasatake YAMATO 		.kindIndex = K_FRAMETITLE,
64993d4289SMasatake YAMATO 		.roleIndex = ROLE_DEFINITION_INDEX,
65942142faSMasatake YAMATO 		.name = NULL,
66f67e271cSMasatake YAMATO 		.unique = false,
67942142faSMasatake YAMATO 	},
68942142faSMasatake YAMATO 	{
69942142faSMasatake YAMATO 		.type = '{',
70942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
71942142faSMasatake YAMATO 		.kindIndex = K_FRAMETITLE,
72993d4289SMasatake YAMATO 		.roleIndex = ROLE_DEFINITION_INDEX,
73942142faSMasatake YAMATO 		.name = NULL,
74f67e271cSMasatake YAMATO 		.unique = true,
75f67e271cSMasatake YAMATO 		.scopeIndex = CORK_NIL,	/* root scope */
76942142faSMasatake YAMATO 	},
77942142faSMasatake YAMATO 	{
78942142faSMasatake YAMATO 		.type = 0
79942142faSMasatake YAMATO 	}
80942142faSMasatake YAMATO };
81942142faSMasatake YAMATO 
82942142faSMasatake YAMATO /* \framesubtitle<overlay specification>{frame subtitle text} */
83942142faSMasatake YAMATO static struct TexParseStrategy framesubtitle_strategy[] = {
84942142faSMasatake YAMATO 	{
85942142faSMasatake YAMATO 		.type = '<',
86942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_OPTIONAL,
87942142faSMasatake YAMATO 		.kindIndex = KIND_GHOST_INDEX,
88942142faSMasatake YAMATO 		.name = NULL,
89942142faSMasatake YAMATO 	},
90942142faSMasatake YAMATO 	{
91942142faSMasatake YAMATO 		.type = '{',
92942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
93942142faSMasatake YAMATO 		.kindIndex = K_FRAMESUBTITLE,
94993d4289SMasatake YAMATO 		.roleIndex = ROLE_DEFINITION_INDEX,
95942142faSMasatake YAMATO 		.name = NULL,
96f67e271cSMasatake YAMATO 		.unique = false,
97942142faSMasatake YAMATO 	},
98942142faSMasatake YAMATO 	{
99942142faSMasatake YAMATO 		.type = 0
100942142faSMasatake YAMATO 	}
101942142faSMasatake YAMATO };
102942142faSMasatake YAMATO 
103942142faSMasatake YAMATO /*  \begin{frame}<overlay specification>[<default overlay specification>][options]{title}{subtitle}*/
104942142faSMasatake YAMATO static struct TexParseStrategy frame_env_strategy [] = {
105942142faSMasatake YAMATO 	{
106942142faSMasatake YAMATO 		.type = '<',
107942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_OPTIONAL,
108942142faSMasatake YAMATO 		.kindIndex = KIND_GHOST_INDEX,
109942142faSMasatake YAMATO 		.name = NULL,
110942142faSMasatake YAMATO 	},
111942142faSMasatake YAMATO 	{
112942142faSMasatake YAMATO 		.type = '[',
113942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_OPTIONAL,
114942142faSMasatake YAMATO 		.kindIndex = KIND_GHOST_INDEX,
115942142faSMasatake YAMATO 		.name = NULL,
116942142faSMasatake YAMATO 	},
117942142faSMasatake YAMATO 	{
118942142faSMasatake YAMATO 		.type = '[',
119942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_OPTIONAL,
120942142faSMasatake YAMATO 		.kindIndex = KIND_GHOST_INDEX,
121942142faSMasatake YAMATO 		.name = NULL,
122942142faSMasatake YAMATO 	},
123942142faSMasatake YAMATO 	{
124942142faSMasatake YAMATO 		.type = '{',
125942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
126942142faSMasatake YAMATO 		.kindIndex = K_FRAMETITLE,
127993d4289SMasatake YAMATO 		.roleIndex = ROLE_DEFINITION_INDEX,
128f67e271cSMasatake YAMATO 		.unique = true,
129f67e271cSMasatake YAMATO 		.scopeIndex = CORK_NIL,	/* root scope */
130942142faSMasatake YAMATO 	},
131942142faSMasatake YAMATO 	{
132942142faSMasatake YAMATO 		/* This should not be optoinal. */
133942142faSMasatake YAMATO 		.type = '{',
134942142faSMasatake YAMATO 		.flags = TEX_NAME_FLAG_INCLUDING_WHITESPACE,
135942142faSMasatake YAMATO 		.kindIndex = K_FRAMESUBTITLE,
136993d4289SMasatake YAMATO 		.roleIndex = ROLE_DEFINITION_INDEX,
137942142faSMasatake YAMATO 		.name = NULL,
138f67e271cSMasatake YAMATO 		.unique = false,
139942142faSMasatake YAMATO 	},
140942142faSMasatake YAMATO 	{
141942142faSMasatake YAMATO 		.type = 0
142942142faSMasatake YAMATO 	}
143942142faSMasatake YAMATO };
144942142faSMasatake YAMATO 
145942142faSMasatake YAMATO 
146942142faSMasatake YAMATO /*
147942142faSMasatake YAMATO  *	 FUNCTION DEFINITIONS
148942142faSMasatake YAMATO  */
149942142faSMasatake YAMATO 
readIdentifierNotify(texSubparser * s,vString * identifier)150942142faSMasatake YAMATO static  struct TexParseStrategy *readIdentifierNotify (texSubparser *s,
151942142faSMasatake YAMATO 													   vString *identifier)
152942142faSMasatake YAMATO {
153942142faSMasatake YAMATO 	/* Reject uninteresting identifiers early. */
154942142faSMasatake YAMATO 	if (! (vStringLength (identifier) > 10
155942142faSMasatake YAMATO 		   && strncmp (vStringValue(identifier), "\\frame", 6) == 0))
156942142faSMasatake YAMATO 		return NULL;
157942142faSMasatake YAMATO 	else if (vStringLength (identifier) == 11
158942142faSMasatake YAMATO 		&& strcmp (vStringValue(identifier), "\\frametitle") == 0)
159942142faSMasatake YAMATO 		return frametitle_strategy;
160942142faSMasatake YAMATO 	/* strlen("\\framesubtitle") = 14 */
161942142faSMasatake YAMATO 	else if (vStringLength (identifier) == 14
162942142faSMasatake YAMATO 		&& strcmp (vStringValue(identifier), "\\framesubtitle") == 0)
163942142faSMasatake YAMATO 		return framesubtitle_strategy;
164942142faSMasatake YAMATO 	else
165942142faSMasatake YAMATO 		return NULL;
166942142faSMasatake YAMATO }
167942142faSMasatake YAMATO 
inputStart(subparser * s)168942142faSMasatake YAMATO static void inputStart (subparser *s)
169942142faSMasatake YAMATO {
170942142faSMasatake YAMATO 	struct beamerSubparser *b = (struct beamerSubparser *)s;
171942142faSMasatake YAMATO 	b->lastTitleCorkIndex = CORK_NIL;
172942142faSMasatake YAMATO }
173942142faSMasatake YAMATO 
reportStrategicParsing(texSubparser * s,const struct TexParseStrategy * strategy)174942142faSMasatake YAMATO static void reportStrategicParsing (texSubparser *s,
175942142faSMasatake YAMATO 									const struct TexParseStrategy *strategy)
176942142faSMasatake YAMATO {
177942142faSMasatake YAMATO 	struct beamerSubparser *b = (struct beamerSubparser *)s;
178942142faSMasatake YAMATO 
179942142faSMasatake YAMATO 	if (strategy == frametitle_strategy)
180942142faSMasatake YAMATO 	{
181942142faSMasatake YAMATO 		if (strategy [1].corkIndex != CORK_NIL)
182942142faSMasatake YAMATO 			b->lastTitleCorkIndex = strategy [1].corkIndex;
183942142faSMasatake YAMATO 		else if (strategy [2].corkIndex != CORK_NIL)
184942142faSMasatake YAMATO 			b->lastTitleCorkIndex = strategy [2].corkIndex;
185942142faSMasatake YAMATO 	}
186942142faSMasatake YAMATO 	else if (strategy == framesubtitle_strategy)
187942142faSMasatake YAMATO 	{
188942142faSMasatake YAMATO 		tagEntryInfo *e = getEntryInCorkQueue (strategy [1].corkIndex);
189*3671ad72SMasatake YAMATO 		if (e)
190942142faSMasatake YAMATO 			e->extensionFields.scopeIndex = b->lastTitleCorkIndex;
191942142faSMasatake YAMATO 	}
192942142faSMasatake YAMATO 	else if (strategy == frame_env_strategy)
193942142faSMasatake YAMATO 	{
194942142faSMasatake YAMATO 		b->lastTitleCorkIndex = CORK_NIL;
195942142faSMasatake YAMATO 
196942142faSMasatake YAMATO 		if (strategy [3].corkIndex != CORK_NIL)
197942142faSMasatake YAMATO 			b->lastTitleCorkIndex = strategy [3].corkIndex;
198*3671ad72SMasatake YAMATO 
199942142faSMasatake YAMATO 		tagEntryInfo *e = getEntryInCorkQueue (strategy [4].corkIndex);
200*3671ad72SMasatake YAMATO 		if (e && b->lastTitleCorkIndex != CORK_NIL)
201942142faSMasatake YAMATO 			e->extensionFields.scopeIndex = b->lastTitleCorkIndex;
202942142faSMasatake YAMATO 	}
203942142faSMasatake YAMATO }
204942142faSMasatake YAMATO 
readEnviromentBeginNotify(texSubparser * s,vString * env)205942142faSMasatake YAMATO static struct TexParseStrategy *readEnviromentBeginNotify (texSubparser *s,
206942142faSMasatake YAMATO 														   vString *env)
207942142faSMasatake YAMATO {
208942142faSMasatake YAMATO 	if (strcmp (vStringValue (env), "frame") == 0)
209942142faSMasatake YAMATO        return frame_env_strategy;
210942142faSMasatake YAMATO 	return NULL;
211942142faSMasatake YAMATO }
212942142faSMasatake YAMATO 
readEnviromentEndNotify(texSubparser * s,vString * env)213942142faSMasatake YAMATO static bool readEnviromentEndNotify (texSubparser *s,
214942142faSMasatake YAMATO 									 vString *env)
215942142faSMasatake YAMATO {
216942142faSMasatake YAMATO 	if (strcmp (vStringValue (env), "frame") == 0)
217942142faSMasatake YAMATO 	{
218942142faSMasatake YAMATO 		struct beamerSubparser *b = (struct beamerSubparser *)s;
219942142faSMasatake YAMATO 		tagEntryInfo *e = getEntryInCorkQueue (b->lastTitleCorkIndex);
220942142faSMasatake YAMATO 		if (e)
221942142faSMasatake YAMATO 			e->extensionFields.endLine = getInputLineNumber ();
222942142faSMasatake YAMATO 		return true;
223942142faSMasatake YAMATO 	}
224942142faSMasatake YAMATO 	return false;
225942142faSMasatake YAMATO }
226942142faSMasatake YAMATO 
227942142faSMasatake YAMATO static struct beamerSubparser beamerSubparser = {
228942142faSMasatake YAMATO 	.tex = {
229942142faSMasatake YAMATO 		.subparser = {
230942142faSMasatake YAMATO 			.direction = SUBPARSER_BI_DIRECTION,
231942142faSMasatake YAMATO 			.inputStart = inputStart,
232942142faSMasatake YAMATO 		},
233942142faSMasatake YAMATO 		.readIdentifierNotify = readIdentifierNotify,
234942142faSMasatake YAMATO 		.readEnviromentBeginNotify = readEnviromentBeginNotify,
235942142faSMasatake YAMATO 		.readEnviromentEndNotify = readEnviromentEndNotify,
236942142faSMasatake YAMATO 		.reportStrategicParsing = reportStrategicParsing,
237942142faSMasatake YAMATO 	},
238942142faSMasatake YAMATO };
239942142faSMasatake YAMATO 
findBeamerTags(void)240942142faSMasatake YAMATO static void findBeamerTags(void)
241942142faSMasatake YAMATO {
242942142faSMasatake YAMATO 	scheduleRunningBaseparser (RUN_DEFAULT_SUBPARSERS);
243942142faSMasatake YAMATO }
244942142faSMasatake YAMATO 
TexBeamerParser(void)245942142faSMasatake YAMATO extern parserDefinition* TexBeamerParser (void)
246942142faSMasatake YAMATO {
247942142faSMasatake YAMATO 	parserDefinition* const def = parserNew("TeXBeamer");
248942142faSMasatake YAMATO 
249942142faSMasatake YAMATO 	static parserDependency dependencies [] = {
250942142faSMasatake YAMATO 		[0] = { DEPTYPE_SUBPARSER, "Tex", &beamerSubparser },
251942142faSMasatake YAMATO 	};
252942142faSMasatake YAMATO 
253942142faSMasatake YAMATO 	def->dependencies = dependencies;
254942142faSMasatake YAMATO 	def->dependencyCount = ARRAY_SIZE (dependencies);
255942142faSMasatake YAMATO 
256942142faSMasatake YAMATO 	def->kindTable = beamerKinds;
257942142faSMasatake YAMATO 	def->kindCount = ARRAY_SIZE(beamerKinds);
258942142faSMasatake YAMATO 
259942142faSMasatake YAMATO 	def->parser = findBeamerTags;
2606b1a862eSMasatake YAMATO 	def->useCork = CORK_QUEUE;
261942142faSMasatake YAMATO 
262942142faSMasatake YAMATO 	return def;
263942142faSMasatake YAMATO }
264