Skip to content

Commit

Permalink
Merge pull request #2025 from masatake/anonymous-tag-in-optlib
Browse files Browse the repository at this point in the history
lregex: introduce {anonymous} flag for making an anonymous tag
  • Loading branch information
masatake committed Apr 16, 2019
2 parents d738e3d + a118be6 commit 46490ea
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 3 deletions.
1 change: 1 addition & 0 deletions Tmain/list-mline-regex-flags.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ i icase applied in a case-insensitive manner
- mgroup=N a group in pattern determining the line number of tag
- warning="MESSAGE" print the given MESSAGE at WARNING level
- _advanceTo=N[start|end] a group in pattern from where the next scan starts [0end]
- _anonymous=PREFIX make an anonymous tag with PREFIX
- _extra=EXTRA record the tag only when the extra is enabled
- _field=FIELD:VALUE record the matched string(VALUE) to parser own FIELD of the tag
- _role=ROLE set the given ROLE to the roles field
1 change: 1 addition & 0 deletions Tmain/list-mtable-regex-flags.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ i icase applied in a case-insensitive manner
- treset=TABLE clear the state stack and jump to given regex table
- warning="MESSAGE" print the given MESSAGE at WARNING level
- _advanceTo=N[start|end] a group in pattern from where the next scan starts [0end]
- _anonymous=PREFIX make an anonymous tag with PREFIX
- _extra=EXTRA record the tag only when the extra is enabled
- _field=FIELD:VALUE record the matched string(VALUE) to parser own FIELD of the tag
- _role=ROLE set the given ROLE to the roles field
1 change: 1 addition & 0 deletions Tmain/list-regex-flags.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ x exclusive skip testing the other patterns if a line is matched
- placeholder don't put this tag to tags file.
- scope=ACTION use scope stack: ACTION = ref|push|pop|clear|set
- warning="MESSAGE" print the given MESSAGE at WARNING level
- _anonymous=PREFIX make an anonymous tag with PREFIX
- _extra=EXTRA record the tag only when the extra is enabled
- _field=FIELD:VALUE record the matched string(VALUE) to parser own FIELD of the tag
- _role=ROLE set the given ROLE to the roles field
10 changes: 10 additions & 0 deletions Units/regex-flag-anonymous.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--sort=no

--langdef=foo
--map-foo=.foo
--kinddef-foo=m,module,modules
--kinddef-foo=x,exception,exceptions

--regex-foo=/^defmodule *([a-zA-Z0-9]+) *do/\1/m/{scope=push}
--regex-foo=/^end//{scope=pop}{placeholder}
--regex-foo=/ +defexception( +.*)$//x/{_anonymous=exception}{scope=ref}
4 changes: 4 additions & 0 deletions Units/regex-flag-anonymous.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
MyAppError1 input.foo /^defmodule MyAppError1 do$/;" m
exceptionf9e1959f0101 input.foo /^ defexception [:message]$/;" x module:MyAppError1
MyAppError2 input.foo /^defmodule MyAppError2 do$/;" m
exceptionf9e1959f0201 input.foo /^ defexception [:message]$/;" x module:MyAppError2
12 changes: 12 additions & 0 deletions Units/regex-flag-anonymous.d/input.foo
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#
# Taken from commit log subitted by @dreamtigers in #2024.
#
defmodule MyAppError1 do
defexception [:message]
# code
end

defmodule MyAppError2 do
defexception [:message]
# code
end
36 changes: 35 additions & 1 deletion docs/optlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,40 @@ Experimental flags
This flag allows a regex match to generate a reference tag entry and
specify the role of the reference, as explained in :ref:`roles`.

.. NOT REVIEWED YET
``_anonymous=PREFIX``

This flag allows a regex match to generate an anonymous tag entry.
ctags gives a name starting with ``PREFIX`` and emits it.
This flag is useful to record the position for a language object
having no name. A lambda function in a functional programming
language is a typical example of a language object having no name.

Consider following input (input.foo):

.. code-block:: lisp
(let ((f (lambda (x) (+ 1 x))))
...
)
Consider following optlib file (foo.ctags):

.. code-block:: perl
--langdef=Foo
--map-Foo=+.foo
--kinddef-Foo=l,lambda,lambda functions
--regex-Foo=/.*\(lambda .*//l/{_anonymous=L}
You can get following tags file:

.. code-block:: console
$ u-ctags --options=foo.ctags -o - /tmp/input.foo
Le4679d360100 /tmp/input.foo /^(let ((f (lambda (x) (+ 1 x))))$/;" l
Ghost kind in regex parser
......................................................................
Expand Down Expand Up @@ -538,7 +572,7 @@ tags automatically.

`.` is the (ctags global) default separator combining names into a
fully qualified tag. You can customize separators with
``--_scopesep-<LANG>=...` option.
``--_scopesep-<LANG>=...`` option.

input.foo::

Expand Down
46 changes: 44 additions & 2 deletions main/lregex.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,8 @@ typedef struct {

char *pattern_string;

char *anonymous_tag_prefix;

struct {
errorSelection selection;
char *message_string;
Expand Down Expand Up @@ -226,6 +228,9 @@ static void deletePattern (regexPattern *p)
if (p->message.message_string)
eFree (p->message.message_string);

if (p->anonymous_tag_prefix)
eFree (p->anonymous_tag_prefix);

eFree (p);
}

Expand Down Expand Up @@ -797,6 +802,31 @@ static void common_flag_role_long (const char* const s, const char* const v, voi
ptrn->u.tag.roleBits |= makeRoleBit(role->id);
}

static void common_flag_anonymous_long (const char* const s, const char* const v, void* data)
{
struct commonFlagData * cdata = data;
regexPattern *ptrn = cdata->ptrn;

Assert (ptrn);

if (ptrn->anonymous_tag_prefix)
{
error (WARNING, "an anonymous tag prefix for this pattern (%s) is already given: %s",
ptrn->pattern_string? ptrn->pattern_string: "",
ptrn->anonymous_tag_prefix);
return;
}

if (!v)
{
error (WARNING, "no PREFIX for anonymous regex flag is given (pattern == %s)",
ptrn->pattern_string? ptrn->pattern_string: "");
return;
}

ptrn->anonymous_tag_prefix = eStrdup (v);
}

static flagDefinition commonSpecFlagDef[] = {
{ '\0', "fatal", NULL, common_flag_msg_long ,
"\"MESSAGE\"", "print the given MESSAGE and exit"},
Expand All @@ -809,6 +839,8 @@ static flagDefinition commonSpecFlagDef[] = {
"FIELD:VALUE", "record the matched string(VALUE) to parser own FIELD of the tag"},
{ '\0', EXPERIMENTAL "role", NULL, common_flag_role_long,
"ROLE", "set the given ROLE to the roles field"},
{ '\0', EXPERIMENTAL "anonymous", NULL, common_flag_anonymous_long,
"PREFIX", "make an anonymous tag with PREFIX"},
};


Expand Down Expand Up @@ -1160,8 +1192,13 @@ static void matchTagPattern (struct lregexControlBlock *lcb,
const regmatch_t* const pmatch,
off_t offset)
{
vString *const name = substitute (line,
patbuf->u.tag.name_pattern, BACK_REFERENCE_COUNT, pmatch);
vString *const name =
(patbuf->u.tag.name_pattern[0] != '\0') ? substitute (line,
patbuf->u.tag.name_pattern,
BACK_REFERENCE_COUNT, pmatch):
(patbuf->anonymous_tag_prefix) ? anonGenerateNew (patbuf->anonymous_tag_prefix,
patbuf->u.tag.kindIndex):
vStringNewInit ("");
bool placeholder = !!((patbuf->scopeActions & SCOPE_PLACEHOLDER) == SCOPE_PLACEHOLDER);
unsigned long scope = CORK_NIL;
int n;
Expand Down Expand Up @@ -1260,6 +1297,10 @@ static void matchTagPattern (struct lregexControlBlock *lcb,
assignRole (&e, roleIndex);
}
}

if (patbuf->anonymous_tag_prefix)
markTagExtraBit (&e, XTAG_ANONYMOUS);

n = makeTagEntry (&e);

trashBoxMakeEmpty(field_trashbox);
Expand Down Expand Up @@ -1592,6 +1633,7 @@ static regexPattern *addTagRegexInternal (struct lregexControlBlock *lcb,
if (*name == '\0')
{
if (rptr->exclusive || rptr->scopeActions & SCOPE_PLACEHOLDER
|| rptr->anonymous_tag_prefix
|| regptype == REG_PARSER_MULTI_TABLE)
rptr->accept_empty_name = true;
else
Expand Down

0 comments on commit 46490ea

Please sign in to comment.