xref: /Universal-ctags/parsers/rmarkdown.c (revision 3bbeaff45d748874f566350ab065b5510e382c16)
1*3bbeaff4SMasatake YAMATO /*
2*3bbeaff4SMasatake YAMATO  *
3*3bbeaff4SMasatake YAMATO  *  Copyright (c) 2022, Masatake YAMATO
4*3bbeaff4SMasatake YAMATO  *
5*3bbeaff4SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
6*3bbeaff4SMasatake YAMATO  *   GNU General Public License version 2 or (at your option) any later version.
7*3bbeaff4SMasatake YAMATO  *
8*3bbeaff4SMasatake YAMATO  * This module contains functions for generating tags for R Markdown files.
9*3bbeaff4SMasatake YAMATO  * https://bookdown.org/yihui/rmarkdown/
10*3bbeaff4SMasatake YAMATO  *
11*3bbeaff4SMasatake YAMATO  */
12*3bbeaff4SMasatake YAMATO 
13*3bbeaff4SMasatake YAMATO /*
14*3bbeaff4SMasatake YAMATO  *   INCLUDE FILES
15*3bbeaff4SMasatake YAMATO  */
16*3bbeaff4SMasatake YAMATO #include "general.h"	/* must always come first */
17*3bbeaff4SMasatake YAMATO #include "markdown.h"
18*3bbeaff4SMasatake YAMATO 
19*3bbeaff4SMasatake YAMATO #include "entry.h"
20*3bbeaff4SMasatake YAMATO #include "parse.h"
21*3bbeaff4SMasatake YAMATO 
22*3bbeaff4SMasatake YAMATO #include <ctype.h>
23*3bbeaff4SMasatake YAMATO #include <string.h>
24*3bbeaff4SMasatake YAMATO 
25*3bbeaff4SMasatake YAMATO /*
26*3bbeaff4SMasatake YAMATO  *   DATA DEFINITIONS
27*3bbeaff4SMasatake YAMATO  */
28*3bbeaff4SMasatake YAMATO typedef enum {
29*3bbeaff4SMasatake YAMATO 	K_CHUNK_LABEL = 0,
30*3bbeaff4SMasatake YAMATO } rmarkdownKind;
31*3bbeaff4SMasatake YAMATO 
32*3bbeaff4SMasatake YAMATO static kindDefinition RMarkdownKinds[] = {
33*3bbeaff4SMasatake YAMATO 	{ true, 'l', "chunklabel",       "chunk labels"},
34*3bbeaff4SMasatake YAMATO };
35*3bbeaff4SMasatake YAMATO 
36*3bbeaff4SMasatake YAMATO struct sRMarkdownSubparser {
37*3bbeaff4SMasatake YAMATO 	markdownSubparser markdown;
38*3bbeaff4SMasatake YAMATO };
39*3bbeaff4SMasatake YAMATO 
40*3bbeaff4SMasatake YAMATO /*
41*3bbeaff4SMasatake YAMATO *   FUNCTION DEFINITIONS
42*3bbeaff4SMasatake YAMATO */
43*3bbeaff4SMasatake YAMATO 
findRMarkdownTags(void)44*3bbeaff4SMasatake YAMATO static void findRMarkdownTags (void)
45*3bbeaff4SMasatake YAMATO {
46*3bbeaff4SMasatake YAMATO 	scheduleRunningBaseparser (0);
47*3bbeaff4SMasatake YAMATO }
48*3bbeaff4SMasatake YAMATO 
49*3bbeaff4SMasatake YAMATO #define skip_space(CP) 	while (*CP == ' ' || *CP == '\t') CP++;
50*3bbeaff4SMasatake YAMATO 
makeRMarkdownTag(vString * name,int kindIndex,bool anonymous)51*3bbeaff4SMasatake YAMATO static void makeRMarkdownTag (vString *name, int kindIndex, bool anonymous)
52*3bbeaff4SMasatake YAMATO {
53*3bbeaff4SMasatake YAMATO 	tagEntryInfo e;
54*3bbeaff4SMasatake YAMATO 	initTagEntry (&e, vStringValue (name), kindIndex);
55*3bbeaff4SMasatake YAMATO 	if (anonymous)
56*3bbeaff4SMasatake YAMATO 		markTagExtraBit (&e, XTAG_ANONYMOUS);
57*3bbeaff4SMasatake YAMATO 	makeTagEntry (&e);
58*3bbeaff4SMasatake YAMATO }
59*3bbeaff4SMasatake YAMATO 
extractLanguageForCodeBlock(markdownSubparser * s,const char * langMarker,vString * langName)60*3bbeaff4SMasatake YAMATO static bool extractLanguageForCodeBlock (markdownSubparser *s,
61*3bbeaff4SMasatake YAMATO 										 const char *langMarker,
62*3bbeaff4SMasatake YAMATO 										 vString *langName)
63*3bbeaff4SMasatake YAMATO {
64*3bbeaff4SMasatake YAMATO 	const char *cp = langMarker;
65*3bbeaff4SMasatake YAMATO 
66*3bbeaff4SMasatake YAMATO 	if (*cp != '{')
67*3bbeaff4SMasatake YAMATO 		return false;
68*3bbeaff4SMasatake YAMATO 	cp++;
69*3bbeaff4SMasatake YAMATO 
70*3bbeaff4SMasatake YAMATO 	const char *end = strpbrk(cp, " \t,}");
71*3bbeaff4SMasatake YAMATO 	if (!end)
72*3bbeaff4SMasatake YAMATO 		return false;
73*3bbeaff4SMasatake YAMATO 
74*3bbeaff4SMasatake YAMATO 	if (end - cp == 0)
75*3bbeaff4SMasatake YAMATO 		return false;
76*3bbeaff4SMasatake YAMATO 
77*3bbeaff4SMasatake YAMATO 	vStringNCatS (langName, cp, end - cp);
78*3bbeaff4SMasatake YAMATO 
79*3bbeaff4SMasatake YAMATO 	cp = end;
80*3bbeaff4SMasatake YAMATO 	if (*cp == ',' || *cp == '}')
81*3bbeaff4SMasatake YAMATO 	{
82*3bbeaff4SMasatake YAMATO 		vString *name = anonGenerateNew("__anon", K_CHUNK_LABEL);
83*3bbeaff4SMasatake YAMATO 		makeRMarkdownTag (name, K_CHUNK_LABEL, true);
84*3bbeaff4SMasatake YAMATO 		vStringDelete (name);
85*3bbeaff4SMasatake YAMATO 		return true;
86*3bbeaff4SMasatake YAMATO 	}
87*3bbeaff4SMasatake YAMATO 
88*3bbeaff4SMasatake YAMATO 	skip_space(cp);
89*3bbeaff4SMasatake YAMATO 
90*3bbeaff4SMasatake YAMATO 	vString *chunk_label  = vStringNew ();
91*3bbeaff4SMasatake YAMATO 	bool anonymous = false;
92*3bbeaff4SMasatake YAMATO 	while (isalnum((unsigned char)*cp) || *cp == '-')
93*3bbeaff4SMasatake YAMATO 		vStringPut (chunk_label, *cp++);
94*3bbeaff4SMasatake YAMATO 
95*3bbeaff4SMasatake YAMATO 	if (vStringLength (chunk_label) == 0)
96*3bbeaff4SMasatake YAMATO 	{
97*3bbeaff4SMasatake YAMATO 		anonGenerate (chunk_label, "__anon", K_CHUNK_LABEL);
98*3bbeaff4SMasatake YAMATO 		anonymous = true;
99*3bbeaff4SMasatake YAMATO 	}
100*3bbeaff4SMasatake YAMATO 
101*3bbeaff4SMasatake YAMATO 	skip_space(cp);
102*3bbeaff4SMasatake YAMATO 	if (*cp == ',' || *cp == '}')
103*3bbeaff4SMasatake YAMATO 		makeRMarkdownTag (chunk_label, K_CHUNK_LABEL, anonymous);
104*3bbeaff4SMasatake YAMATO 
105*3bbeaff4SMasatake YAMATO 	vStringDelete (chunk_label);
106*3bbeaff4SMasatake YAMATO 	return true;
107*3bbeaff4SMasatake YAMATO }
108*3bbeaff4SMasatake YAMATO 
RMarkdownParser(void)109*3bbeaff4SMasatake YAMATO extern parserDefinition* RMarkdownParser (void)
110*3bbeaff4SMasatake YAMATO {
111*3bbeaff4SMasatake YAMATO 	static const char *const extensions [] = { "rmd", NULL };
112*3bbeaff4SMasatake YAMATO 	static struct sRMarkdownSubparser rmarkdownSubparser = {
113*3bbeaff4SMasatake YAMATO 		.markdown = {
114*3bbeaff4SMasatake YAMATO 			.subparser = {
115*3bbeaff4SMasatake YAMATO 				.direction = SUBPARSER_SUB_RUNS_BASE,
116*3bbeaff4SMasatake YAMATO 			},
117*3bbeaff4SMasatake YAMATO 			.extractLanguageForCodeBlock = extractLanguageForCodeBlock,
118*3bbeaff4SMasatake YAMATO 		},
119*3bbeaff4SMasatake YAMATO 	};
120*3bbeaff4SMasatake YAMATO 	static parserDependency dependencies [] = {
121*3bbeaff4SMasatake YAMATO 		[0] = { DEPTYPE_SUBPARSER, "Markdown", &rmarkdownSubparser },
122*3bbeaff4SMasatake YAMATO 	};
123*3bbeaff4SMasatake YAMATO 
124*3bbeaff4SMasatake YAMATO 	parserDefinition* const def = parserNew ("RMarkdown");
125*3bbeaff4SMasatake YAMATO 
126*3bbeaff4SMasatake YAMATO 
127*3bbeaff4SMasatake YAMATO 	def->dependencies = dependencies;
128*3bbeaff4SMasatake YAMATO 	def->dependencyCount = ARRAY_SIZE(dependencies);
129*3bbeaff4SMasatake YAMATO 	def->kindTable      = RMarkdownKinds;
130*3bbeaff4SMasatake YAMATO 	def->kindCount  = ARRAY_SIZE (RMarkdownKinds);
131*3bbeaff4SMasatake YAMATO 	def->extensions = extensions;
132*3bbeaff4SMasatake YAMATO 	def->parser     = findRMarkdownTags;
133*3bbeaff4SMasatake YAMATO 	return def;
134*3bbeaff4SMasatake YAMATO }
135