Skip to content

Commit

Permalink
CPreProcessor: run subparsers for extrating interesting language obje…
Browse files Browse the repository at this point in the history
…cts in C comments
  • Loading branch information
masatake committed Jan 5, 2023
1 parent 98e1a8e commit 0a045aa
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 8 deletions.
6 changes: 4 additions & 2 deletions main/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -4030,7 +4030,8 @@ static unsigned int parserCorkFlags (parserDefinition *parser)
return r;
}

static void setupLanguageSubparsersInUse (const langType language)
/* NOTE: Exported only for CPreProcessor */
extern void setupLanguageSubparsersInUse (const langType language)
{
subparser *tmp;

Expand All @@ -4044,7 +4045,8 @@ static void setupLanguageSubparsersInUse (const langType language)
}
}

static subparser* teardownLanguageSubparsersInUse (const langType language)
/* NOTE: Exported only for CPreProcessor */
extern subparser* teardownLanguageSubparsersInUse (const langType language)
{
subparser *tmp;

Expand Down
130 changes: 124 additions & 6 deletions parsers/cpreprocessor.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "general.h" /* must always come first */

#include <string.h>
#include <ctype.h>

#include "debug.h"
#include "entry.h"
Expand All @@ -30,6 +31,12 @@

#include "cxx/cxx_debug.h"

/* Ideally these two should be private in "main" part.
* Because the CPreProcessor parser is imperfect as a base parser, the
* parser must call them directly. */
extern subparser* teardownLanguageSubparsersInUse (const langType language);
extern void setupLanguageSubparsersInUse (const langType language);

/*
* MACROS
*/
Expand Down Expand Up @@ -296,6 +303,9 @@ static void cppInitCommon(langType clientLang,
t = getNamedLanguage ("CPreProcessor", 0);
initializeParser (t);
}
pushLanguage(Cpp.lang);
setupLanguageSubparsersInUse (Cpp.lang);
popLanguage();

Cpp.clientLang = clientLang;
Cpp.ungetBuffer = NULL;
Expand Down Expand Up @@ -439,6 +449,9 @@ extern void cppTerminate (void)
hashTableDelete (Cpp.fileMacroTable);
Cpp.fileMacroTable = NULL;
}
pushLanguage(Cpp.lang);
teardownLanguageSubparsersInUse (Cpp.lang);
popLanguage();
}

extern void cppBeginStatement (void)
Expand Down Expand Up @@ -1243,30 +1256,135 @@ static Comment isComment (void)
return comment;
}

static cPreProcessorSubparser *notifyLineToSubparsers (cPreProcessorSubparser *sub,
char firstchar,
vString *line,
bool *sentThe1stLine)
{
if (sub == NULL && *sentThe1stLine == true)
return NULL;

if (!*sentThe1stLine)
{
Assert (sub == NULL);

subparser *s;

*sentThe1stLine = true;

pushLanguage (Cpp.lang);
foreachSubparser(s, false)
{
bool b = false;
cPreProcessorSubparser *cpp = (cPreProcessorSubparser *)s;
enterSubparser(s);
if (cpp->firstLineNotify)
b = cpp->firstLineNotify (cpp, firstchar, vStringValue(line));
leaveSubparser();

if (b)
{
sub = cpp;
break;
}
}
popLanguage ();
return sub;
}

enterSubparser(&sub->subparser);
if (sub->restLineNotify)
sub->restLineNotify (sub, vStringValue(line));
leaveSubparser();
return sub;
}

static void notifyEndOfComment (cPreProcessorSubparser *cpp)
{
enterSubparser(&cpp->subparser);
if (cpp->endOfCommentNotify)
cpp->endOfCommentNotify(cpp);
leaveSubparser();
}

static bool isDocCommentStarter(int c)
{
return c == '*';
}

static bool isWhitespaceOnly (vString *line)
{
const char *c = vStringValue(line);

while (*c)
{
if (!isspace((unsigned char) *c)
&& !isDocCommentStarter(*c))
return false;
c++;
}
return true;
}

/* Skips over a C style comment. According to ANSI specification a comment
* is treated as white space, so we perform this substitution.
*
* As side effects, running subparsers interested in comments.
*/
static int cppSkipOverCComment (void)
{
int c = cppGetcFromUngetBufferOrFile ();
int c0 = 0;
vString *line = NULL;
bool sentThe1stLine = false;
cPreProcessorSubparser *sub = NULL;


if (isDocCommentStarter (c))
{
c0 = c;
c = cppGetcFromUngetBufferOrFile ();
if (c0 == '*' && c == '/')
return SPACE;
cppUngetc (c);
c = c0;
line = vStringNew ();
}

while (c != EOF)
{
if (c != '*')
c = cppGetcFromUngetBufferOrFile ();
else
if (c == '*')
{
const int next = cppGetcFromUngetBufferOrFile ();

if (next != '/')
c = next;
else
if (next == '/')
{
c = SPACE; /* replace comment with space */
break;
}
cppUngetc (next);
}

if (line)
{
vStringPut (line, c);
if (c == '\n')
{
if (sub || !isWhitespaceOnly (line))
sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine);
vStringClear (line);
}
}
c = cppGetcFromUngetBufferOrFile ();
}

if (line && !vStringIsEmpty(line) && (sub || !isWhitespaceOnly (line)))
sub = notifyLineToSubparsers (sub, c0, line, &sentThe1stLine);

if (sub)
notifyEndOfComment (sub);

vStringDelete (line); /* NULL is acceptable */
return c;
}

Expand Down
13 changes: 13 additions & 0 deletions parsers/cpreprocessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#include "types.h"
#include "vstring.h"

#include "subparser.h"

/*
* MACROS
*/
Expand Down Expand Up @@ -144,4 +146,15 @@ extern void cppBuildMacroReplacementWithPtrArrayAndUngetResult(
cppMacroInfo * macro,
const ptrArray * args);

/* Running a parser inside comments. */
typedef struct sCPreProcessorSubparser cPreProcessorSubparser;

struct sCPreProcessorSubparser {
subparser subparser;

bool (* firstLineNotify) (cPreProcessorSubparser *s, char firstchar, const char *line);
void (* restLineNotify) (cPreProcessorSubparser *s, const char *line);
void (* endOfCommentNotify) (cPreProcessorSubparser *s);
};

#endif /* CTAGS_MAIN_GET_H */

0 comments on commit 0a045aa

Please sign in to comment.