Skip to content

Commit

Permalink
Merge pull request #3613 from masatake/optscript-params
Browse files Browse the repository at this point in the history
main: introduce --_paramdef-<LANG>=<NAME>,<DESCRIPTION> option
  • Loading branch information
masatake committed Dec 29, 2022
2 parents 50e7a74 + e8847f7 commit 02c5ae5
Show file tree
Hide file tree
Showing 27 changed files with 467 additions and 126 deletions.
4 changes: 4 additions & 0 deletions Tmain/list-params.d/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@ echo
echo '# CPP MACHINABLE NOHEADER'
${C} --with-list-header=no --machinable --list-params=CPreProcessor
echo

echo '# CPP MACHINABLE NOHEADER + PARAM DEFINE WITH CMDLINE'
${C} --_paramdef-CPreProcessor='pragma,handle program' --with-list-header=no --machinable --list-params=CPreProcessor
echo
7 changes: 7 additions & 0 deletions Tmain/list-params.d/stdout-expected.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,10 @@ define define replacement for an identifier (name(params,...)=definition)
if0 examine code within "#if 0" branch (true or [false])
ignore a token to be specially handled

# CPP MACHINABLE NOHEADER + PARAM DEFINE WITH CMDLINE
_expand expand macros if their definitions are in the current C/C++/CUDA input file (true or [false])
define define replacement for an identifier (name(params,...)=definition)
if0 examine code within "#if 0" branch (true or [false])
ignore a token to be specially handled
pragma handle program

11 changes: 11 additions & 0 deletions Units/paramdef.r/no-set.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--langdef=Foo
--map-Foo=.foo
--kinddef-Foo=v,xval,externally defined values
--_paramdef-Foo=VAR,desc
--regex-Foo=/(x)//{{
/VAR _param {
/xval _tag _commit pop
} {
\1 /xval _tag _commit pop
} ifelse
}}
1 change: 1 addition & 0 deletions Units/paramdef.r/no-set.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x input.foo /^x$/;" v
1 change: 1 addition & 0 deletions Units/paramdef.r/no-set.d/input.foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x
10 changes: 10 additions & 0 deletions Units/paramdef.r/simple.d/args.ctags
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
--langdef=Foo
--map-Foo=.foo
--kinddef-Foo=v,xval,externally defined values
--_paramdef-Foo=VAR,desc
--regex-Foo=/(x)//{{
/VAR _param {
/xval _tag _commit pop
} if
}}
--param-Foo.VAR=y
1 change: 1 addition & 0 deletions Units/paramdef.r/simple.d/expected.tags
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
y input.foo /^x$/;" v
1 change: 1 addition & 0 deletions Units/paramdef.r/simple.d/input.foo
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x
50 changes: 48 additions & 2 deletions docs/optscript.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ Related options
--list-fields
--_paramdef-<LANG>=<NAME>,<DESCRIPTION>
You can run optscript code fragments when pattern specified with
options matches successfully. The options are ``--regex-<LANG>``,
``--mline-regex-<LANG>``, and ``--_mtable-regex-<LANG>`` as you
Expand Down Expand Up @@ -269,12 +271,18 @@ represents the field has an operator for reading
(``:fieldname``). ``w`` represents the field has an operator for
writing (``fieldname:``).

``--_paramdef-<LANG>=<NAME>,<DESCRIPTION>`` defines a language specific
parameter named ``<NAME>``. ``--param-<LANG>.<NAME>=<VALUE>`` assigns
a value ``<VALUE>`` to the parameter. You can access the value from
Optscript code with ``_param`` operator. Don't use ``{`` character
in the description. The character is reserved for future extension.

Operators
............................

**.** -> ``-`` **.** ``corkIndex:int``

Push the cork index for the tag
Push the cork index for the tag.

**\\n** -> ``-`` **\\n** ``matchedString:string``

Expand Down Expand Up @@ -324,7 +332,45 @@ Data types
Recipes
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

TBW
Parameters
...........................................
With ``--_paramdef-<LANG>=<param>,<description>`` option, you can
define a parser-specific parameter to your optlib parser.

In the following example, we define a parser, ``Foo`` with a
parser-specific parameter ``VAR``. If the parser sees "x" in the
current input stream, a code fragment attached to the pattern "/(x)/"
runs. The code fragment does (1) check whether a value for ``VAR`` is
given, (2) emit a tag with the value given to parameter ``VAR`` as
name and with ``xval`` kind, and (3) remove the cork index from the
operand stack.

foo.ctags:
.. code-block::
--langdef=Foo
--map-Foo=.foo
--kinddef-Foo=v,xval,externally defined values
--_paramdef-Foo=VAR,desc
--regex-Foo=/(x)//{{
/VAR _param { % if VAR is defined ....
/xval _tag _commit pop
} if
% if VAR is not defined, we do nothing.
}}
input.foo:
.. code-block::
x
When running the parser, we can give a value ("hereiam" in the following example)
for the parameter ``VAR`` from the command line:

.. code-block:: console
$ ./ctags --options=args.ctags --param-Foo.VAR=hereiam -o - input.foo
hereiam input.foo /^x$/;" v
Difference between Optscript and PostScript
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down
46 changes: 46 additions & 0 deletions main/lregex.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ struct lregexControlBlock {
struct guestRequest *guest_req;

EsObject *local_dict;
hashTable*param_dict;

ptrArray *hook[SCRIPT_HOOK_MAX];
ptrArray *hook_code[SCRIPT_HOOK_MAX];
Expand Down Expand Up @@ -341,6 +342,8 @@ extern struct lregexControlBlock* allocLregexControlBlock (parserDefinition *par
lcb->tstack = ptrArrayNew(NULL);
lcb->guest_req = guestRequestNew ();
lcb->local_dict = es_nil;
lcb->param_dict = hashTableNew (3, hashCstrhash, hashCstreq,
eFree, eFree);

for (int i = 0; i< SCRIPT_HOOK_MAX; i++)
{
Expand Down Expand Up @@ -373,6 +376,9 @@ extern void freeLregexControlBlock (struct lregexControlBlock* lcb)
es_object_unref (lcb->local_dict);
lcb->local_dict = es_nil;

hashTableDelete (lcb->param_dict);
lcb->param_dict = NULL;

for (int i = 0; i < SCRIPT_HOOK_MAX; i++)
{
ptrArrayDelete (lcb->hook[i]);
Expand Down Expand Up @@ -3157,6 +3163,13 @@ extern void addOptscriptToHook (struct lregexControlBlock *lcb, enum scriptHook
ptrArrayAdd (lcb->hook[hook], eStrdup (code));
}

extern void propagateParamToOptscript (struct lregexControlBlock *lcb, const char *param, const char *value)
{
Assert (param);
Assert (value);
hashTablePutItem (lcb->param_dict, eStrdup (param), eStrdup (value));
}

/* Return true if available. */
extern bool checkRegex (void)
{
Expand Down Expand Up @@ -4000,6 +4013,32 @@ static EsObject *lrop_makepromise (OptVM *vm, EsObject *name)
return es_false;
}

static EsObject *lrop_param (OptVM *vm, EsObject *name)
{
struct lregexControlBlock *lcb = opt_vm_get_app_data (vm);
EsObject *key = opt_vm_ostack_top (vm);
if (es_object_get_type (key) != OPT_TYPE_NAME)
return OPT_ERR_TYPECHECK;
EsObject *key_sym = es_pointer_get (key);
const char *keyc = es_symbol_get (key_sym);
const char *valuec = hashTableGetItem (lcb->param_dict, keyc);

if (valuec)
{
opt_vm_ostack_pop (vm);
EsObject *value = opt_string_new_from_cstr (valuec);
opt_vm_ostack_push (vm, value);
es_object_unref (value);
opt_vm_ostack_push (vm, es_true);
}
else
{
opt_vm_ostack_pop (vm);
opt_vm_ostack_push (vm, es_false);
}
return false;
}

static struct optscriptOperatorRegistration lropOperators [] = {
{
.name = "_matchstr",
Expand Down Expand Up @@ -4165,6 +4204,13 @@ static struct optscriptOperatorRegistration lropOperators [] = {
.help_str = "lang:string start:matchloc end:matchloc _MAKEPROMISE promise:int true%"
"lang:string start:matchloc end:matchloc _MAKEPROMISE false",
},
{
.name = "_param",
.fn = lrop_param,
.arity = 1,
.help_str = "param:name _PARAM value:string true%"
"param:name _PARAM false",
},
};

extern void initRegexOptscript (void)
Expand Down
1 change: 1 addition & 0 deletions main/lregex_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ extern void initRegexOptscript (void);
extern void listRegexOpscriptOperators (FILE *fp);

extern void addOptscriptToHook (struct lregexControlBlock *lcb, enum scriptHook hook, const char *code);
extern void propagateParamToOptscript (struct lregexControlBlock *lcb, const char *param, const char *value);

extern void printMultitableStatistics (struct lregexControlBlock *lcb);

Expand Down
4 changes: 4 additions & 0 deletions main/mini-geany.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,10 @@ static unsigned int ctagsGetLangCount(void)
void addIgnoreSymbol(const char *value)
{
langType lang = getNamedLanguage ("CPreProcessor", 0);
/*
* In the future, we will rename applyParameter to
* applyLanguageParam.
*/
applyParameter (lang, "ignore", value);
}

Expand Down
51 changes: 15 additions & 36 deletions main/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ static optionDescription LongOptionDescription [] = {
{1,1," Copy patterns of a regex table to another regex table."},
{1,1," --_mtable-regex-<LANG>=<table>/<line_pattern>/<name_pattern>/[<flags>]"},
{1,1," Define multitable regular expression for locating tags in specific language."},
{1,1," --_paramdef-<LANG>=<name>,<description>"},
{1,1," Define new param for <LANG>."},
{1,1," --_prelude-<LANG>={{ optscript-code }}"},
{1,1," Specify code run before parsing with <LANG> parser."},
{1,1," --_pretend-<NEWLANG>=<OLDLANG>"},
Expand Down Expand Up @@ -1709,7 +1711,7 @@ static void processIf0Option (const char *const option,
langType lang = getNamedLanguage ("CPreProcessor", 0);
const char *arg = if0? "true": "false";

applyParameter (lang, "if0", arg);
applyLanguageParam (lang, "if0", arg);
}

static void processLanguageForceOption (
Expand Down Expand Up @@ -2018,31 +2020,6 @@ extern bool processMapOption (
return true;
}

extern bool processParamOption (
const char *const option, const char *const value)
{
langType language;
const char* name;
const char* sep;

language = getLanguageComponentInOption (option, "param-");
if (language == LANG_IGNORE)
return false;

sep = option + strlen ("param-") + strlen (getLanguageName (language));
/* `:' is only for keeping self compatibility */
if (! (*sep == '.' || *sep == ':' ))
error (FATAL, "no separator(.) is given for %s=%s", option, value);
name = sep + 1;

if (value == NULL || value [0] == '\0')
error (FATAL, "no value is given for %s", option);

applyParameter (language, name, value);

return true;
}

static void processLicenseOption (
const char *const option CTAGS_ATTR_UNUSED,
const char *const parameter CTAGS_ATTR_UNUSED)
Expand Down Expand Up @@ -2129,18 +2106,18 @@ static void processListParametersOption (const char *const option,
const char *const parameter)
{
if (parameter [0] == '\0' || strcasecmp (parameter, RSV_LANG_ALL) == 0)
printLanguageParameters (LANG_AUTO,
localOption.withListHeader, localOption.machinable,
stdout);
printLanguageParams (LANG_AUTO,
localOption.withListHeader, localOption.machinable,
stdout);
else
{
langType language = getNamedLanguage (parameter, 0);
if (language == LANG_IGNORE)
error (FATAL, "Unknown language \"%s\" in \"%s\" option", parameter, option);
else
printLanguageParameters (language,
localOption.withListHeader, localOption.machinable,
stdout);
printLanguageParams (language,
localOption.withListHeader, localOption.machinable,
stdout);
}
exit (0);
}
Expand Down Expand Up @@ -2595,7 +2572,7 @@ static void readIgnoreList (const char *const list)

while (token != NULL)
{
applyParameter (lang, "ignore", token);
applyLanguageParam (lang, "ignore", token);
token = strtok (NULL, IGNORE_SEPARATORS);
}
eFree (newList);
Expand All @@ -2615,7 +2592,7 @@ static void addIgnoreListFromFile (const char *const fileName)
for(i=0;i<c;i++)
{
vString * s = stringListItem(tokens,i);
applyParameter (lang, "ignore", vStringValue(s));
applyLanguageParam (lang, "ignore", vStringValue(s));
}

stringListDelete(tokens);
Expand All @@ -2626,7 +2603,7 @@ static void processIgnoreOption (const char *const list, int IgnoreOrDefine)
langType lang = getNamedLanguage ("CPreProcessor", 0);

if (IgnoreOrDefine == 'D')
applyParameter (lang, "define", list);
applyLanguageParam (lang, "define", list);
else if (strchr ("@./\\", list [0]) != NULL)
{
const char* fileName = (*list == '@') ? list + 1 : list;
Expand All @@ -2637,7 +2614,7 @@ static void processIgnoreOption (const char *const list, int IgnoreOrDefine)
addIgnoreListFromFile (list);
#endif
else if (strcmp (list, "-") == 0)
applyParameter (lang, "ignore", NULL);
applyLanguageParam (lang, "ignore", NULL);
else
readIgnoreList (list);
}
Expand Down Expand Up @@ -3352,6 +3329,8 @@ static void processLongOption (
;
else if (processMapOption (option, parameter))
;
else if (processParamdefOption (option, parameter))
;
else if (processParamOption (option, parameter))
;
else if (processTabledefOption (option, parameter))
Expand Down
1 change: 1 addition & 0 deletions main/options_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ extern langType getLanguageComponentInOptionFull (const char *const option,

extern void processLanguageDefineOption (const char *const option, const char *const parameter);
extern bool processMapOption (const char *const option, const char *const parameter);
extern bool processParamdefOption (const char *const option, const char *const value);
extern bool processParamOption (const char *const option, const char *const value);
extern bool processKinddefOption (const char *const option, const char *const parameter);
extern bool processKindsOption (const char *const option, const char *const parameter);
Expand Down
Loading

0 comments on commit 02c5ae5

Please sign in to comment.