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