xref: /Universal-ctags/parsers/fypp.c (revision 55919c582e891b1de6ab4d5ac7e8c124dbcde842)
197535021SMasatake YAMATO /*
297535021SMasatake YAMATO  *   Copyright (c) 2018 Masatake YAMATO
397535021SMasatake YAMATO  *   Copyright (c) 2018 Red Hat, Inc.
497535021SMasatake YAMATO  *
597535021SMasatake YAMATO  *   This source code is released for free distribution under the terms of the
697535021SMasatake YAMATO  *   GNU General Public License version 2 or (at your option) any later version.
797535021SMasatake YAMATO  *
897535021SMasatake YAMATO  *   This module contains functions to generate tags for Fypp, a Python powered
997535021SMasatake YAMATO  *   Fortran preprocessor.
1097535021SMasatake YAMATO  *   See: https://github.com/aradi/fypp
1197535021SMasatake YAMATO  */
1297535021SMasatake YAMATO 
1397535021SMasatake YAMATO #include "general.h"  /* must always come first */
1497535021SMasatake YAMATO 
1597535021SMasatake YAMATO #include "ctags.h"
1614781660SMasatake YAMATO #include "debug.h"
1797535021SMasatake YAMATO #include "entry.h"
1897535021SMasatake YAMATO #include "numarray.h"
190d502ef0SMasatake YAMATO #include "param.h"
2097535021SMasatake YAMATO #include "parse.h"
2197535021SMasatake YAMATO #include "promise.h"
2297535021SMasatake YAMATO #include "read.h"
23a219c98cSMasatake YAMATO #include "trace.h"
2497535021SMasatake YAMATO 
2597535021SMasatake YAMATO #include <string.h>
2697535021SMasatake YAMATO 
2797535021SMasatake YAMATO typedef enum {
2897535021SMasatake YAMATO 	K_MACRO
2997535021SMasatake YAMATO } fyppKind;
3097535021SMasatake YAMATO 
3197535021SMasatake YAMATO static kindDefinition FyppKinds[] = {
3297535021SMasatake YAMATO 	{ true, 'm', "macro", "macros" },
3397535021SMasatake YAMATO };
3497535021SMasatake YAMATO 
3597535021SMasatake YAMATO /* TODO
3697535021SMasatake YAMATO    If "guest" extra is disabled, we can reduce the codes to be processed. */
3797535021SMasatake YAMATO 
3897535021SMasatake YAMATO struct fyppParseCtx {
3997535021SMasatake YAMATO 	int macro_cork_index;
4097535021SMasatake YAMATO 
4197535021SMasatake YAMATO 	/* Areas surrounded by Fypp directive should be masked with white
4297535021SMasatake YAMATO 	   spaces when running a guest parser like Fortran parser.
4397535021SMasatake YAMATO 
4497535021SMasatake YAMATO 	   in_fypp_area field counts the depth of areas. Zero means the
4597535021SMasatake YAMATO 	   current line is not part of a Fypp area; the line should passed
4697535021SMasatake YAMATO 	   as is to the guest parser. Otherwise it should not.
4797535021SMasatake YAMATO 
4897535021SMasatake YAMATO 	   #:if/#:elif/#:else/#:endif areas are handled in a special way.
4997535021SMasatake YAMATO 	   #:if areas are passed to the guest parser.
5097535021SMasatake YAMATO 	   #:elif/#:else/#:endif areas are not.
5197535021SMasatake YAMATO 	   This approach follows what CPreProcessor parser does.
5297535021SMasatake YAMATO 	   Quoted from ctags.1 man page:
5397535021SMasatake YAMATO 
5497535021SMasatake YAMATO 	   If a preprocessor conditional is encountered within a statement
5597535021SMasatake YAMATO 	   which defines a tag, ctags follows only the first branch of
5697535021SMasatake YAMATO 	   that conditional (except in the special case of "#if 0", in
5797535021SMasatake YAMATO 	   which case it follows only the last branch).
5897535021SMasatake YAMATO 
5997535021SMasatake YAMATO 	   About the behavior about "#if 0" is not applicable to Fypp parser.
6097535021SMasatake YAMATO 	   if_tracker is for tracking "the first branch of that conditional".
6197535021SMasatake YAMATO 	   A scalar value is not enough to track the branch because branches
6297535021SMasatake YAMATO 	   can be nested:
6397535021SMasatake YAMATO 
6497535021SMasatake YAMATO 	   #:if COND0
6597535021SMasatake YAMATO 	   ***
6697535021SMasatake YAMATO 	   #:if COND1
6797535021SMasatake YAMATO 	   ***
6897535021SMasatake YAMATO 	   #:else
6997535021SMasatake YAMATO 	   ...
7097535021SMasatake YAMATO 	   #:endif
7197535021SMasatake YAMATO 	   ...
7297535021SMasatake YAMATO 	   #:else
7397535021SMasatake YAMATO 	   ...
7497535021SMasatake YAMATO 	   #:endif
7597535021SMasatake YAMATO 
7697535021SMasatake YAMATO 	   In the above example, Fypp parser passes only `***` lines to the
7797535021SMasatake YAMATO 	   guest parser.
7897535021SMasatake YAMATO 
7997535021SMasatake YAMATO 	   if_tracker field tracks the branches. When the parser enters #:if area,
8097535021SMasatake YAMATO 	   it appends 1 to if_tracker. When it enters #:elif or #:else area,
8197535021SMasatake YAMATO 	   it repalces 1 with 0. When it reaches at #:endif, remove the last
8297535021SMasatake YAMATO 	   element from the field. The product of if_tracker should be either
8397535021SMasatake YAMATO 	   0 or 1. In the case that the product is 1, we can say the current line
8497535021SMasatake YAMATO 	   is in the first if block.
8597535021SMasatake YAMATO 
8697535021SMasatake YAMATO 	   if_cont field is for tracking '&' at the end of #:if directive lines.
8797535021SMasatake YAMATO 	   If it is true, the last line is ended with &. We can know the
8897535021SMasatake YAMATO 	   current line is part of Fypp directive that should not be
8997535021SMasatake YAMATO 	   passed to the guest parser.
9097535021SMasatake YAMATO 
9197535021SMasatake YAMATO 	   other_cont field has the same purpose as if_cont but
9297535021SMasatake YAMATO 	   other_cont is for the other directives than #:if.
9397535021SMasatake YAMATO 	*/
9497535021SMasatake YAMATO 	int in_fypp_area;
9597535021SMasatake YAMATO 	intArray *if_tracker;
9697535021SMasatake YAMATO 	bool if_cont;
9797535021SMasatake YAMATO 	bool other_cont;
9897535021SMasatake YAMATO 
9997535021SMasatake YAMATO 	/* fypp_lines field records the line numbers for masking. */
10097535021SMasatake YAMATO 	ulongArray *fypp_lines;
10197535021SMasatake YAMATO };
10297535021SMasatake YAMATO 
10397535021SMasatake YAMATO static vString *fyppGuestParser;
10497535021SMasatake YAMATO 
fypp_does_line_continue(const char * line,const regexMatch * matches)10597535021SMasatake YAMATO static bool fypp_does_line_continue(const char *line,
10697535021SMasatake YAMATO 									const regexMatch *matches)
10797535021SMasatake YAMATO {
108ff077011SMasatake YAMATO 	if (matches[0].length == 0)
109ff077011SMasatake YAMATO 		return false;
11097535021SMasatake YAMATO 	return *(line + matches[0].start + matches[0].length - 1) == '&';
11197535021SMasatake YAMATO }
11297535021SMasatake YAMATO 
fypp_start_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)11397535021SMasatake YAMATO static bool fypp_start_cb(const char *line,
11497535021SMasatake YAMATO 						  const regexMatch *matches,
11597535021SMasatake YAMATO 						  unsigned int count,
11697535021SMasatake YAMATO 						  void *userData)
11797535021SMasatake YAMATO {
11897535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
11997535021SMasatake YAMATO 
12097535021SMasatake YAMATO 	TRACE_PRINT_PREFIX();
12197535021SMasatake YAMATO 	TRACE_PRINT_FMT("%04d - %s", getInputLineNumber(), line);
12297535021SMasatake YAMATO 
12397535021SMasatake YAMATO 	ulongArrayAdd (ctx->fypp_lines,
12497535021SMasatake YAMATO 				   getInputLineNumber());
12597535021SMasatake YAMATO 	ctx->in_fypp_area++;
12697535021SMasatake YAMATO 	ctx->if_cont = false;
12797535021SMasatake YAMATO 	ctx->other_cont = false;
12897535021SMasatake YAMATO 
12997535021SMasatake YAMATO 	return true;
13097535021SMasatake YAMATO }
13197535021SMasatake YAMATO 
fypp_end_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)13297535021SMasatake YAMATO static bool fypp_end_cb(const char *line,
13397535021SMasatake YAMATO 						const regexMatch *matches,
13497535021SMasatake YAMATO 						unsigned int count,
13597535021SMasatake YAMATO 						void *userData)
13697535021SMasatake YAMATO {
13797535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
13897535021SMasatake YAMATO 
13997535021SMasatake YAMATO 	TRACE_PRINT_PREFIX();
14097535021SMasatake YAMATO 	TRACE_PRINT_FMT("%04d - %s", getInputLineNumber(), line);
14197535021SMasatake YAMATO 
14297535021SMasatake YAMATO 	ulongArrayAdd (ctx->fypp_lines,
14397535021SMasatake YAMATO 				   getInputLineNumber());
14497535021SMasatake YAMATO 	ctx->in_fypp_area--;
14597535021SMasatake YAMATO 	ctx->if_cont = false;
14697535021SMasatake YAMATO 	ctx->other_cont = false;
14797535021SMasatake YAMATO 
14897535021SMasatake YAMATO 	return true;
14997535021SMasatake YAMATO }
15097535021SMasatake YAMATO 
fypp_line_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)15197535021SMasatake YAMATO static bool fypp_line_cb (const char *line,
15297535021SMasatake YAMATO 						  const regexMatch *matches,
15397535021SMasatake YAMATO 						  unsigned int count,
15497535021SMasatake YAMATO 						  void *userData)
15597535021SMasatake YAMATO {
15697535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
15797535021SMasatake YAMATO 
15897535021SMasatake YAMATO 	TRACE_PRINT_PREFIX();
15997535021SMasatake YAMATO 	TRACE_PRINT_FMT("%04d - %s", getInputLineNumber(), line);
16097535021SMasatake YAMATO 
16197535021SMasatake YAMATO 	ulongArrayAdd (ctx->fypp_lines,
16297535021SMasatake YAMATO 				   getInputLineNumber());
16397535021SMasatake YAMATO 	ctx->if_cont = false;
16497535021SMasatake YAMATO 	ctx->other_cont = fypp_does_line_continue (line, matches);
16597535021SMasatake YAMATO 
16697535021SMasatake YAMATO 	return true;
16797535021SMasatake YAMATO }
16897535021SMasatake YAMATO 
macro_start_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)16997535021SMasatake YAMATO static bool macro_start_cb (const char *line,
17097535021SMasatake YAMATO 							const regexMatch *matches,
17197535021SMasatake YAMATO 							unsigned int count,
17297535021SMasatake YAMATO 							void *userData)
17397535021SMasatake YAMATO {
17497535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
17597535021SMasatake YAMATO 	vString *macro = NULL;
17697535021SMasatake YAMATO 	vString *signature = NULL;
17797535021SMasatake YAMATO 
17897535021SMasatake YAMATO 	if (count > 0)
17997535021SMasatake YAMATO 	{
18097535021SMasatake YAMATO 		tagEntryInfo e;
18197535021SMasatake YAMATO 
18297535021SMasatake YAMATO 		macro = vStringNew ();
18397535021SMasatake YAMATO 		vStringNCopyS (macro,
18497535021SMasatake YAMATO 					   line + matches[1].start,
18597535021SMasatake YAMATO 					   matches[1].length);
18697535021SMasatake YAMATO 
18797535021SMasatake YAMATO 		initTagEntry (&e, vStringValue (macro), K_MACRO);
18897535021SMasatake YAMATO 
18997535021SMasatake YAMATO 		if (count > 1)
19097535021SMasatake YAMATO 		{
19197535021SMasatake YAMATO 			signature = vStringNew ();
19297535021SMasatake YAMATO 			vStringNCopyS (signature,
19397535021SMasatake YAMATO 						   line + matches[2].start,
19497535021SMasatake YAMATO 						   matches[2].length);
19597535021SMasatake YAMATO 			e.extensionFields.signature = vStringValue (signature);
19697535021SMasatake YAMATO 		}
19797535021SMasatake YAMATO 
19897535021SMasatake YAMATO 		ctx->macro_cork_index = makeTagEntry (&e);
19997535021SMasatake YAMATO 	}
20097535021SMasatake YAMATO 
20197535021SMasatake YAMATO 	if (macro)
20297535021SMasatake YAMATO 		vStringDelete (macro);
20397535021SMasatake YAMATO 	if (signature)
20497535021SMasatake YAMATO 		vStringDelete (signature);
20597535021SMasatake YAMATO 
20697535021SMasatake YAMATO 	fypp_start_cb (line, matches, count, userData);
20797535021SMasatake YAMATO 	return true;
20897535021SMasatake YAMATO }
20997535021SMasatake YAMATO 
macro_end_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)21097535021SMasatake YAMATO static bool macro_end_cb (const char *line,
21197535021SMasatake YAMATO 						  const regexMatch *matches,
21297535021SMasatake YAMATO 						  unsigned int count,
21397535021SMasatake YAMATO 						  void *userData)
21497535021SMasatake YAMATO {
21597535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
21697535021SMasatake YAMATO 
21797535021SMasatake YAMATO 	tagEntryInfo *e = getEntryInCorkQueue (ctx->macro_cork_index);
2183671ad72SMasatake YAMATO 	if (e)
21997535021SMasatake YAMATO 		e->extensionFields.endLine = getInputLineNumber ();
22097535021SMasatake YAMATO 	ctx->macro_cork_index = CORK_NIL;
22197535021SMasatake YAMATO 
22297535021SMasatake YAMATO 	fypp_end_cb (line, matches, count, userData);
22397535021SMasatake YAMATO 	return true;
22497535021SMasatake YAMATO }
22597535021SMasatake YAMATO 
if_start_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)22697535021SMasatake YAMATO static bool if_start_cb (const char *line,
22797535021SMasatake YAMATO 						 const regexMatch *matches,
22897535021SMasatake YAMATO 						 unsigned int count,
22997535021SMasatake YAMATO 						 void *userData)
23097535021SMasatake YAMATO {
23197535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
23297535021SMasatake YAMATO 
23397535021SMasatake YAMATO 	if (ctx->if_tracker == NULL)
23497535021SMasatake YAMATO 		ctx->if_tracker = intArrayNew ();
23597535021SMasatake YAMATO 
23697535021SMasatake YAMATO 	intArrayAdd (ctx->if_tracker, 1);
23797535021SMasatake YAMATO 
23897535021SMasatake YAMATO 	fypp_start_cb (line, matches, count, userData);
23997535021SMasatake YAMATO 
24097535021SMasatake YAMATO 	ctx->if_cont = fypp_does_line_continue (line, matches);
24197535021SMasatake YAMATO 	TRACE_PRINT("(count: %d, len: %d, ifCont: %d)",
24297535021SMasatake YAMATO 				count, matches[1].length, ctx->if_cont);
24397535021SMasatake YAMATO 
24497535021SMasatake YAMATO 	return true;
24597535021SMasatake YAMATO }
24697535021SMasatake YAMATO 
if_else_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)24797535021SMasatake YAMATO static bool if_else_cb (const char *line,
24897535021SMasatake YAMATO 						const regexMatch *matches,
24997535021SMasatake YAMATO 						unsigned int count,
25097535021SMasatake YAMATO 						void *userData)
25197535021SMasatake YAMATO {
25297535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
25397535021SMasatake YAMATO 
25497535021SMasatake YAMATO 	if (ctx->if_tracker)
25597535021SMasatake YAMATO 	{
25697535021SMasatake YAMATO 		intArrayRemoveLast (ctx->if_tracker);
25797535021SMasatake YAMATO 		intArrayAdd (ctx->if_tracker, 0);
25897535021SMasatake YAMATO 	}
25997535021SMasatake YAMATO 
26097535021SMasatake YAMATO 	fypp_line_cb(line, matches, count, userData);
26197535021SMasatake YAMATO 	return true;
26297535021SMasatake YAMATO }
26397535021SMasatake YAMATO 
if_end_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)26497535021SMasatake YAMATO static bool if_end_cb (const char *line,
26597535021SMasatake YAMATO 					   const regexMatch *matches,
26697535021SMasatake YAMATO 					   unsigned int count,
26797535021SMasatake YAMATO 					   void *userData)
26897535021SMasatake YAMATO {
26997535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
27097535021SMasatake YAMATO 
27197535021SMasatake YAMATO 	if (ctx->if_tracker)
27297535021SMasatake YAMATO 	{
27397535021SMasatake YAMATO 		intArrayRemoveLast (ctx->if_tracker);
27497535021SMasatake YAMATO 
27597535021SMasatake YAMATO 		if (intArrayCount(ctx->if_tracker) == 0)
27697535021SMasatake YAMATO 		{
27797535021SMasatake YAMATO 			intArrayDelete (ctx->if_tracker);
27897535021SMasatake YAMATO 			ctx->if_tracker = NULL;
27997535021SMasatake YAMATO 		}
28097535021SMasatake YAMATO 	}
28197535021SMasatake YAMATO 
28297535021SMasatake YAMATO 	fypp_end_cb (line, matches, count, userData);
28397535021SMasatake YAMATO 	return true;
28497535021SMasatake YAMATO }
28597535021SMasatake YAMATO 
is_in_first_if_block(struct fyppParseCtx * ctx)28697535021SMasatake YAMATO static bool is_in_first_if_block (struct fyppParseCtx *ctx)
28797535021SMasatake YAMATO {
28897535021SMasatake YAMATO 	int r = 1;
28997535021SMasatake YAMATO 
2904c64e833SMasatake YAMATO 	for (unsigned int i = 0; i < intArrayCount (ctx->if_tracker); i++)
29197535021SMasatake YAMATO 		r *= intArrayItem(ctx->if_tracker, i);
29297535021SMasatake YAMATO 
29397535021SMasatake YAMATO 	return r;
29497535021SMasatake YAMATO }
29597535021SMasatake YAMATO 
non_fypp_line_cb(const char * line,const regexMatch * matches,unsigned int count,void * userData)29697535021SMasatake YAMATO static bool non_fypp_line_cb (const char *line,
29797535021SMasatake YAMATO 							  const regexMatch *matches,
29897535021SMasatake YAMATO 							  unsigned int count,
29997535021SMasatake YAMATO 							  void *userData)
30097535021SMasatake YAMATO {
30197535021SMasatake YAMATO 	struct fyppParseCtx *ctx = userData;
30297535021SMasatake YAMATO 
30397535021SMasatake YAMATO 	if ((ctx->in_fypp_area > 0 && ((!ctx->if_tracker)
30497535021SMasatake YAMATO 								  || (! is_in_first_if_block (ctx))
30597535021SMasatake YAMATO 								  || ctx->if_cont))
30697535021SMasatake YAMATO 		|| ctx->other_cont )
30797535021SMasatake YAMATO 	{
30897535021SMasatake YAMATO 		ulongArrayAdd (ctx->fypp_lines,
30997535021SMasatake YAMATO 					   getInputLineNumber());
31097535021SMasatake YAMATO 
31197535021SMasatake YAMATO 		TRACE_PRINT_PREFIX();
31297535021SMasatake YAMATO 		TRACE_PRINT_FMT("%04d - %s", getInputLineNumber(), line);
31397535021SMasatake YAMATO 		TRACE_PRINT_PREFIX();
31497535021SMasatake YAMATO 		TRACE_PRINT_FMT("(inFyppArea: %d, ifTracker: %p, inFirstIfBlock: %d, ifCont: %d otherCont: %d/ ",
31597535021SMasatake YAMATO 						ctx->in_fypp_area, ctx->if_tracker,
31697535021SMasatake YAMATO 						ctx->if_tracker? is_in_first_if_block (ctx): -1,
31797535021SMasatake YAMATO 						ctx->if_cont,
31897535021SMasatake YAMATO 						ctx->other_cont);
31997535021SMasatake YAMATO #ifdef DO_TRACING
32097535021SMasatake YAMATO 		if (ctx->if_tracker)
32197535021SMasatake YAMATO 		{
32297535021SMasatake YAMATO 			for (int i = 0; i < intArrayCount (ctx->if_tracker); i++)
32397535021SMasatake YAMATO 				TRACE_PRINT_FMT("%d ", intArrayItem(ctx->if_tracker, i));
32497535021SMasatake YAMATO 		}
32597535021SMasatake YAMATO #endif	/* DO_TRACING */
32697535021SMasatake YAMATO 		TRACE_PRINT_FMT(")");
32797535021SMasatake YAMATO 		TRACE_PRINT_NEWLINE();
32897535021SMasatake YAMATO 
32997535021SMasatake YAMATO 		bool continued = fypp_does_line_continue(line, matches);
33097535021SMasatake YAMATO 		if (ctx->if_cont)
33197535021SMasatake YAMATO 		{
33297535021SMasatake YAMATO 			ctx->if_cont = continued;
33397535021SMasatake YAMATO 			TRACE_PRINT("(ifCont <= %d)", ctx->if_cont);
33497535021SMasatake YAMATO 		}
33597535021SMasatake YAMATO 		if (ctx->other_cont)
33697535021SMasatake YAMATO 		{
33797535021SMasatake YAMATO 			ctx->other_cont = continued;
33897535021SMasatake YAMATO 			TRACE_PRINT("(otherCont <= %d)", ctx->other_cont);
33997535021SMasatake YAMATO 		}
34097535021SMasatake YAMATO 	}
34197535021SMasatake YAMATO 	else
34297535021SMasatake YAMATO 	{
34397535021SMasatake YAMATO 		TRACE_PRINT_PREFIX();
34497535021SMasatake YAMATO 		TRACE_PRINT_FMT("%04d + %s", getInputLineNumber(), line);
34597535021SMasatake YAMATO 		TRACE_PRINT_PREFIX();
34697535021SMasatake YAMATO 		TRACE_PRINT_FMT("(inFyppArea: %d, ifTracker: %p, ifCont: %d / ",
34797535021SMasatake YAMATO 						ctx->in_fypp_area, ctx->if_tracker,
34897535021SMasatake YAMATO 						ctx->if_cont);
34997535021SMasatake YAMATO 		TRACE_PRINT_FMT(")");
35097535021SMasatake YAMATO 		TRACE_PRINT_NEWLINE();
35197535021SMasatake YAMATO 	}
35297535021SMasatake YAMATO 
35397535021SMasatake YAMATO 	return true;
35497535021SMasatake YAMATO }
35597535021SMasatake YAMATO 
35697535021SMasatake YAMATO 
35797535021SMasatake YAMATO static struct fyppParseCtx parseCtx;
35897535021SMasatake YAMATO 
findFyppTags(void)35997535021SMasatake YAMATO static void findFyppTags (void)
36097535021SMasatake YAMATO {
36197535021SMasatake YAMATO 	int promise;
36297535021SMasatake YAMATO 
36397535021SMasatake YAMATO 	parseCtx.macro_cork_index = CORK_NIL;
36497535021SMasatake YAMATO 	parseCtx.if_tracker = NULL;
36597535021SMasatake YAMATO 
36697535021SMasatake YAMATO 	if (fyppGuestParser)
36797535021SMasatake YAMATO 		parseCtx.fypp_lines = ulongArrayNew ();
36897535021SMasatake YAMATO 
36997535021SMasatake YAMATO 	findRegexTags ();
37097535021SMasatake YAMATO 
37197535021SMasatake YAMATO 
37297535021SMasatake YAMATO 	if (fyppGuestParser)
37397535021SMasatake YAMATO 	{
37497535021SMasatake YAMATO 		promise = makePromise (vStringValue(fyppGuestParser),
37597535021SMasatake YAMATO 							   1, 0,
37697535021SMasatake YAMATO 							   getInputLineNumber(), 0,
37797535021SMasatake YAMATO 							   0);
37897535021SMasatake YAMATO 		if (promise >= 0)
37997535021SMasatake YAMATO 			promiseAttachLineFiller (promise, parseCtx.fypp_lines);
38097535021SMasatake YAMATO 		else
38197535021SMasatake YAMATO 			ulongArrayDelete (parseCtx.fypp_lines);
38297535021SMasatake YAMATO 	}
38397535021SMasatake YAMATO 
38497535021SMasatake YAMATO 	if (parseCtx.if_tracker)
38597535021SMasatake YAMATO 	{
38697535021SMasatake YAMATO 		intArrayDelete (parseCtx.if_tracker);
38797535021SMasatake YAMATO 		parseCtx.if_tracker = NULL;
38897535021SMasatake YAMATO 	}
38997535021SMasatake YAMATO }
39097535021SMasatake YAMATO 
initializeFyppParser(langType language)39197535021SMasatake YAMATO static void initializeFyppParser (langType language)
39297535021SMasatake YAMATO {
39397535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*def[ \t]*([a-zA-Z][a-zA-Z0-9_]*)[ \t]*(\\(.*\\))",
39497535021SMasatake YAMATO 							  "{exclusive}", macro_start_cb, NULL, &parseCtx);
39597535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*enddef[ \t]*([a-zA-Z][a-zA-Z0-9_]*)[ \t]*$",
39697535021SMasatake YAMATO 							  "{exclusive}", macro_end_cb, NULL, &parseCtx);
39797535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*for[ \t].*$",
39897535021SMasatake YAMATO 							  "{exclusive}", fypp_start_cb, NULL, &parseCtx);
39997535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*endfor.*$",
40097535021SMasatake YAMATO 							  "{exclusive}", fypp_end_cb, NULL, &parseCtx);
40197535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*call[ \t].*$",
40297535021SMasatake YAMATO 							  "{exclusive}", fypp_start_cb, NULL, &parseCtx);
40397535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*endcall.*$",
40497535021SMasatake YAMATO 							  "{exclusive}", fypp_end_cb, NULL, &parseCtx);
40597535021SMasatake YAMATO 
40697535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*if[ \t].*$",
40797535021SMasatake YAMATO 							  "{exclusive}", if_start_cb, NULL, &parseCtx);
40897535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*el(se|if)[ \t].*$",
40997535021SMasatake YAMATO 							  "{exclusive}", if_else_cb, NULL, &parseCtx);
41097535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*#:[ \t]*endif.*",
41197535021SMasatake YAMATO 							  "{exclusive}", if_end_cb, NULL, &parseCtx);
41297535021SMasatake YAMATO 
41397535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^[ \t]*(#!|[#@$]:).*$",
41497535021SMasatake YAMATO 							  "{exclusive}", fypp_line_cb, NULL, &parseCtx);
41597535021SMasatake YAMATO 	addLanguageCallbackRegex (language,  "^.*$",
41697535021SMasatake YAMATO 							  "{exclusive}", non_fypp_line_cb, NULL, &parseCtx);
41797535021SMasatake YAMATO }
41897535021SMasatake YAMATO 
finalizeFyppParser(langType language,bool initialized)41997535021SMasatake YAMATO static void finalizeFyppParser (langType language, bool initialized)
42097535021SMasatake YAMATO {
42197535021SMasatake YAMATO 	if (fyppGuestParser)
42297535021SMasatake YAMATO 	{
42397535021SMasatake YAMATO 		vStringDelete (fyppGuestParser);
42497535021SMasatake YAMATO 		fyppGuestParser = NULL;
42597535021SMasatake YAMATO 	}
42697535021SMasatake YAMATO }
42797535021SMasatake YAMATO 
fyppSetGuestParser(const langType language CTAGS_ATTR_UNUSED,const char * optname CTAGS_ATTR_UNUSED,const char * arg)42897535021SMasatake YAMATO static void fyppSetGuestParser (const langType language CTAGS_ATTR_UNUSED,
42997535021SMasatake YAMATO 								const char *optname CTAGS_ATTR_UNUSED, const char *arg)
43097535021SMasatake YAMATO {
43197535021SMasatake YAMATO 	if (!strcmp (arg, RSV_NONE))
43297535021SMasatake YAMATO 	{
43397535021SMasatake YAMATO 		if (fyppGuestParser)
43497535021SMasatake YAMATO 		{
43597535021SMasatake YAMATO 			vStringDelete (fyppGuestParser);
43697535021SMasatake YAMATO 			fyppGuestParser = NULL;
43797535021SMasatake YAMATO 		}
43897535021SMasatake YAMATO 		return;
43997535021SMasatake YAMATO 	}
44097535021SMasatake YAMATO 
44197535021SMasatake YAMATO 	langType lang = getNamedLanguage (arg, strlen(arg));
44297535021SMasatake YAMATO 	if (lang == LANG_IGNORE)
44397535021SMasatake YAMATO 		error (FATAL, "Unknown language: %s", arg);
44497535021SMasatake YAMATO 
44597535021SMasatake YAMATO 	if (fyppGuestParser)
44697535021SMasatake YAMATO 		vStringClear(fyppGuestParser);
44797535021SMasatake YAMATO 	else
44897535021SMasatake YAMATO 		fyppGuestParser = vStringNew();
44997535021SMasatake YAMATO 	vStringCatS (fyppGuestParser, arg);
45097535021SMasatake YAMATO }
45197535021SMasatake YAMATO 
45297535021SMasatake YAMATO static parameterHandlerTable FyppParameterHandlerTable [] = {
453*55919c58SMasatake YAMATO 	{
454*55919c58SMasatake YAMATO 		.name = "guest",
45597535021SMasatake YAMATO 		.desc = "parser run after Fypp parser parses the original input (\"NONE\" or a parser name [Fortran])" ,
45697535021SMasatake YAMATO 		.handleParameter = fyppSetGuestParser,
45797535021SMasatake YAMATO 	},
45897535021SMasatake YAMATO };
45997535021SMasatake YAMATO 
FyppParser(void)46097535021SMasatake YAMATO extern parserDefinition* FyppParser (void)
46197535021SMasatake YAMATO {
46297535021SMasatake YAMATO 	static const char *const extensions [] = { "fy", NULL };
46397535021SMasatake YAMATO 	parserDefinition* const def = parserNew ("Fypp");
46497535021SMasatake YAMATO 	def->kindTable = FyppKinds;
46597535021SMasatake YAMATO 	def->kindCount = ARRAY_SIZE (FyppKinds);
46697535021SMasatake YAMATO 	def->extensions = extensions;
46797535021SMasatake YAMATO 	def->parser = findFyppTags;
46897535021SMasatake YAMATO 	def->initialize = initializeFyppParser;
46997535021SMasatake YAMATO 	def->finalize   = finalizeFyppParser;
47097535021SMasatake YAMATO 	def->method     = METHOD_REGEX;
47197535021SMasatake YAMATO 
47297535021SMasatake YAMATO 	def->parameterHandlerTable = FyppParameterHandlerTable;
47397535021SMasatake YAMATO 	def->parameterHandlerCount = ARRAY_SIZE(FyppParameterHandlerTable);
47497535021SMasatake YAMATO 
4756b1a862eSMasatake YAMATO 	def->useCork = CORK_QUEUE;
47697535021SMasatake YAMATO 
47797535021SMasatake YAMATO 	fyppGuestParser = vStringNewInit ("Fortran");
47897535021SMasatake YAMATO 
47997535021SMasatake YAMATO 	return def;
48097535021SMasatake YAMATO }
481