From bdd51286dba5a9a0f8bc1f7fda654a6df83b40e7 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 15 Oct 2025 20:26:20 +0900 Subject: [PATCH 1/6] circleci,comment: fix a typo Signed-off-by: Masatake YAMATO --- circle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/circle.yml b/circle.yml index a308171273..78911df7f1 100644 --- a/circle.yml +++ b/circle.yml @@ -26,7 +26,7 @@ jobs: # These are for input-validation. dnf -y install g++ jq puppet nodejs gcc-gfortran gcc-gnat typescript # nodejs requires libsqlite.so.0 with sqlite-session feature - # It was tured off in 3.46.1-1. + # It was turned off in 3.46.1-1. dnf -y update sqlite-libs - run: name: Build From 82e75fc9dfd497961e3e3627207c965882f9d3e0 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sun, 18 May 2025 10:06:15 +0900 Subject: [PATCH 2/6] tokeninfo: add a function for skipping to one of multiple types Signed-off-by: Masatake YAMATO --- main/tokeninfo.c | 28 ++++++++++++++++++++++++++++ main/tokeninfo.h | 5 +++++ 2 files changed, 33 insertions(+) diff --git a/main/tokeninfo.c b/main/tokeninfo.c index e3a20c676d..4166c50786 100644 --- a/main/tokeninfo.c +++ b/main/tokeninfo.c @@ -190,6 +190,34 @@ static int tokenGetRightSideOfPair (tokenInfo *token) return token->klass->typeForUndefined; } +static bool tokenTypeIsIn (tokenInfo *token, tokenType ts[], size_t count) +{ + tokenType t = token->type; + + for (size_t i = 0; i < count; i++) + { + if (t == ts[i]) + return true; + } + return false; +} + +bool tokenSkipToOneOfTypesImpl (tokenInfo *token, bool skipPair, tokenType ts[], size_t count) +{ + while (! tokenIsEOF (token)) + { + if (tokenTypeIsIn (token, ts, count)) + return true; + if (skipPair && + tokenGetRightSideOfPair (token) != token->klass->typeForUndefined) + tokenSkipOverPair (token); + else + tokenReadFull (token, NULL); + } + + return false; +} + bool tokenSkipOverPair (tokenInfo *token) { return tokenSkipOverPairFull(token, NULL); diff --git a/main/tokeninfo.h b/main/tokeninfo.h index b860dac828..3bf37f20c6 100644 --- a/main/tokeninfo.h +++ b/main/tokeninfo.h @@ -99,6 +99,11 @@ void tokenCopy (tokenInfo *dest, tokenInfo *src); return false if it reaches EOF. */ bool tokenSkipToType (tokenInfo *token, tokenType t); bool tokenSkipToTypeFull (tokenInfo *token, tokenType t, void *data); + +#define tokenSkipToOneOfTypes(TOKEN, SKIPPAIR, ...) \ + tokenSkipToOneOfTypesImpl(TOKEN, SKIPPAIR, ((tokenType []){__VA_ARGS__}), sizeof((tokenType []){__VA_ARGS__})/sizeof(tokenType)) +bool tokenSkipToOneOfTypesImpl (tokenInfo *token, bool skipPair, tokenType ts[], size_t count); + bool tokenSkipOverPair (tokenInfo *token); bool tokenSkipOverPairFull (tokenInfo *token, void *data); From 830b8e9e51860350028ebef7b1db110e5bc2f143 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sun, 18 May 2025 10:07:01 +0900 Subject: [PATCH 3/6] tokeninfo: add functions making tag from token directly Signed-off-by: Masatake YAMATO --- main/tokeninfo.c | 29 +++++++++++++++++++++++++++++ main/tokeninfo.h | 5 +++++ 2 files changed, 34 insertions(+) diff --git a/main/tokeninfo.c b/main/tokeninfo.c index 4166c50786..380811d80a 100644 --- a/main/tokeninfo.c +++ b/main/tokeninfo.c @@ -244,3 +244,32 @@ bool tokenSkipOverPairFull (tokenInfo *token, void *data) return (depth == 0)? true: false; } + +void tokenInitTagEntry (tokenInfo *token, tagEntryInfo *e, int kind) +{ + initTagEntry (e, tokenString (token), kind); + e->lineNumber = token->lineNumber; + e->filePosition = token->filePosition; +} + +void tokenInitRefTagEntry (tokenInfo *token, tagEntryInfo *e, int kind, int role) +{ + initRefTagEntry (e, tokenString (token), kind, role); + e->lineNumber = token->lineNumber; + e->filePosition = token->filePosition; +} + +int tokenMakeSimpleTag (tokenInfo *token, int kind) +{ + tagEntryInfo e; + + tokenInitTagEntry (token, &e, kind); + return makeTagEntry (&e); +} + +int tokenMakeSimpleRefTag (tokenInfo *token, int kind, int role) +{ + tagEntryInfo e; + tokenInitRefTagEntry (token, &e, kind, role); + return makeTagEntry (&e); +} diff --git a/main/tokeninfo.h b/main/tokeninfo.h index 3bf37f20c6..9c840d4e10 100644 --- a/main/tokeninfo.h +++ b/main/tokeninfo.h @@ -107,4 +107,9 @@ bool tokenSkipToOneOfTypesImpl (tokenInfo *token, bool skipPair, tokenType ts[], bool tokenSkipOverPair (tokenInfo *token); bool tokenSkipOverPairFull (tokenInfo *token, void *data); +void tokenInitTagEntry (tokenInfo *token, tagEntryInfo *e, int kind); +void tokenInitRefTagEntry (tokenInfo *token, tagEntryInfo *e, int kind, int role); +int tokenMakeSimpleTag (tokenInfo *token, int kind); +int tokenMakeSimpleRefTag (tokenInfo *token, int kind, int role); + #endif From bd7e2caced7d37e546b028c4497877c82cb41b27 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 15 May 2025 05:10:34 +0900 Subject: [PATCH 4/6] main: add a way to limit the number of lines in tasting Signed-off-by: Masatake YAMATO --- main/selectors.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/main/selectors.c b/main/selectors.c index 333e94c12b..6960cd46ba 100644 --- a/main/selectors.c +++ b/main/selectors.c @@ -21,6 +21,7 @@ #include "mio.h" static const char *TR_UNKNOWN = NULL; +static const char *TR_BREAK = "/BREAK/"; static const char *TR_PERL5 = "Perl"; static const char *TR_PERL6 = "Perl6"; @@ -53,6 +54,8 @@ static const char *selectByLines (MIO *input, char line[0x800]; while (mio_gets(input, line, sizeof(line))) { const char *lang = lineTaster (line, userData); + if (lang == TR_BREAK) + return defaultLang; if (lang) return lang; } From 5ac8417e8ef8dcc37011753c0cf3a04ad8ec6d57 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Wed, 14 May 2025 09:06:32 +0900 Subject: [PATCH 5/6] Prolog: new parser Close #2628. Signed-off-by: Masatake YAMATO --- Tmain/extras-long.d/stdout-expected.txt | 5 + Tmain/list-extras.d/stdout-expected.txt | 2 + .../stdout-expected.txt | 1 + Tmain/list-fields.d/stdout-expected.txt | 1 + Tmain/list-params.d/stdout-expected.txt | 27 +- Tmain/list-roles.d/stdout-expected.txt | 2 + Units/parser-prolog.r/code.d/args.ctags | 4 + Units/parser-prolog.r/code.d/expected.tags | 12 + Units/parser-prolog.r/code.d/input.pl | 108 +++ Units/parser-prolog.r/dcg.d/args.ctags | 3 + Units/parser-prolog.r/dcg.d/expected.tags | 18 + Units/parser-prolog.r/dcg.d/input.pl | 93 +++ Units/parser-prolog.r/module.d/args.ctags | 4 + Units/parser-prolog.r/module.d/expected.tags | 33 + Units/parser-prolog.r/module.d/input.pl | 127 +++ .../simple-flat-comment.d/args.ctags | 4 + .../simple-flat-comment.d/expected.tags | 28 + .../simple-flat-comment.d/input.pl | 28 + Units/parser-prolog.r/simple.d/args.ctags | 4 + Units/parser-prolog.r/simple.d/expected.tags | 28 + Units/parser-prolog.r/simple.d/input.pl | 28 + docs/news/HEAD.rst | 1 + main/parsers_p.h | 1 + main/selectors.c | 60 ++ main/selectors.h | 3 + parsers/perl.c | 6 +- parsers/prolog.c | 730 ++++++++++++++++++ source.mak | 1 + win32/ctags_vs2013.vcxproj | 1 + win32/ctags_vs2013.vcxproj.filters | 3 + 30 files changed, 1352 insertions(+), 14 deletions(-) create mode 100644 Units/parser-prolog.r/code.d/args.ctags create mode 100644 Units/parser-prolog.r/code.d/expected.tags create mode 100644 Units/parser-prolog.r/code.d/input.pl create mode 100644 Units/parser-prolog.r/dcg.d/args.ctags create mode 100644 Units/parser-prolog.r/dcg.d/expected.tags create mode 100644 Units/parser-prolog.r/dcg.d/input.pl create mode 100644 Units/parser-prolog.r/module.d/args.ctags create mode 100644 Units/parser-prolog.r/module.d/expected.tags create mode 100644 Units/parser-prolog.r/module.d/input.pl create mode 100644 Units/parser-prolog.r/simple-flat-comment.d/args.ctags create mode 100644 Units/parser-prolog.r/simple-flat-comment.d/expected.tags create mode 100644 Units/parser-prolog.r/simple-flat-comment.d/input.pl create mode 100644 Units/parser-prolog.r/simple.d/args.ctags create mode 100644 Units/parser-prolog.r/simple.d/expected.tags create mode 100644 Units/parser-prolog.r/simple.d/input.pl create mode 100644 parsers/prolog.c diff --git a/Tmain/extras-long.d/stdout-expected.txt b/Tmain/extras-long.d/stdout-expected.txt index 383ce79d9e..e3abd50559 100644 --- a/Tmain/extras-long.d/stdout-expected.txt +++ b/Tmain/extras-long.d/stdout-expected.txt @@ -15,6 +15,7 @@ z nulltag no NONE no 1 Include tags with empt - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars # enabling 1 @@ -34,6 +35,7 @@ z nulltag no NONE no 1 Include tags with empt - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars # disabling 1 @@ -53,6 +55,7 @@ z nulltag no NONE no 1 Include tags with empt - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars # combination @@ -72,6 +75,7 @@ z nulltag no NONE no 1 Include tags with empt - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars # combination with letters @@ -91,5 +95,6 @@ z nulltag no NONE no 1 Include tags with empt - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars diff --git a/Tmain/list-extras.d/stdout-expected.txt b/Tmain/list-extras.d/stdout-expected.txt index 83f9800c46..ad708c0365 100644 --- a/Tmain/list-extras.d/stdout-expected.txt +++ b/Tmain/list-extras.d/stdout-expected.txt @@ -15,6 +15,7 @@ z nulltag yes NONE no 1 Include tags with empt - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars #LETTER NAME ENABLED LANGUAGE FIXED VER DESCRIPTION @@ -34,6 +35,7 @@ z nulltag yes NONE no 1 Include tags with empty strings as their names - configPrefixed yes Kconfig no 0 prepend CONFIG_ to config names - CppDef no Make no 1 Include FOO in -DFOO as as a name of CPreProcessor macro - guessedFromFileName yes PkgConfig no 0 the guessed package name of the .pc file +- arityAppended yes Prolog no 0 Include predicates with their arities - funcmap yes QemuHX no 0 Include mapping SQMP to C function name - whitespaceSwapped yes Robot no 0 Include tags swapping whitespace and underscore chars #LETTER NAME ENABLED LANGUAGE FIXED VER DESCRIPTION diff --git a/Tmain/list-fields-with-prefix.d/stdout-expected.txt b/Tmain/list-fields-with-prefix.d/stdout-expected.txt index 1f37f993a7..8de8d30483 100644 --- a/Tmain/list-fields-with-prefix.d/stdout-expected.txt +++ b/Tmain/list-fields-with-prefix.d/stdout-expected.txt @@ -42,6 +42,7 @@ x UCTAGSxpath no NONE s-- no -- 0 xpath - UCTAGSprotocols yes ObjectiveC s-- no -- 0 protocols that the class (or category) confirms to - UCTAGShome yes Passwd s-- no rw 0 home directory - UCTAGSshell yes Passwd s-- no rw 0 login shell +- UCTAGSarity yes Prolog -i- no -- 0 the number of parameters - UCTAGSdecorators no Python s-- no -- 0 decorators on functions and classes - UCTAGSnameref yes Python s-- no -- 0 the original name for the tag - UCTAGSassignmentop no R s-- no -- 0 operator for assignment diff --git a/Tmain/list-fields.d/stdout-expected.txt b/Tmain/list-fields.d/stdout-expected.txt index df89b5bda4..0f0618a257 100644 --- a/Tmain/list-fields.d/stdout-expected.txt +++ b/Tmain/list-fields.d/stdout-expected.txt @@ -60,6 +60,7 @@ z kind no NONE s-- no r- 0 [tags output] prepend "kind:" to k/ (or K/) field out - protocols yes ObjectiveC s-- no -- 0 protocols that the class (or category) confirms to - home yes Passwd s-- no rw 0 home directory - shell yes Passwd s-- no rw 0 login shell +- arity yes Prolog -i- no -- 0 the number of parameters - decorators no Python s-- no -- 0 decorators on functions and classes - nameref yes Python s-- no -- 0 the original name for the tag - assignmentop no R s-- no -- 0 operator for assignment diff --git a/Tmain/list-params.d/stdout-expected.txt b/Tmain/list-params.d/stdout-expected.txt index c2d7806b96..bb6ee857fc 100644 --- a/Tmain/list-params.d/stdout-expected.txt +++ b/Tmain/list-params.d/stdout-expected.txt @@ -1,16 +1,17 @@ # ALL -#LANGUAGE NAME DESCRIPTION -Asm commentCharsAtBOL line comment chraracters at the beginning of line ([;*@]) -Asm commentCharsInMOL line comment chraracters in the beginning of line ([]) -Asm extraLinesepChars extra characters used as a line separator ([]) -Asm useCPreProcessor run CPreProcessor parser for extracting macro definitions ([true] or false) -CPreProcessor _expand expand macros if their definitions are in the current C/C++/CUDA input file (true or [false]) -CPreProcessor define define replacement for an identifier (name(params,...)=definition) -CPreProcessor if0 examine code within "#if 0" branch (true or [false]) -CPreProcessor ignore a token to be specially handled -Fypp guest parser run after Fypp parser parses the original input ("NONE" or a parser name [Fortran]) -ITcl forceUse enable the parser even when `itcl' namespace is not specified in the input (true or [false]) -TclOO forceUse enable the parser even when `oo' namespace is not specified in the input (true or [false]) +#LANGUAGE NAME DESCRIPTION +Asm commentCharsAtBOL line comment chraracters at the beginning of line ([;*@]) +Asm commentCharsInMOL line comment chraracters in the beginning of line ([]) +Asm extraLinesepChars extra characters used as a line separator ([]) +Asm useCPreProcessor run CPreProcessor parser for extracting macro definitions ([true] or false) +CPreProcessor _expand expand macros if their definitions are in the current C/C++/CUDA input file (true or [false]) +CPreProcessor define define replacement for an identifier (name(params,...)=definition) +CPreProcessor if0 examine code within "#if 0" branch (true or [false]) +CPreProcessor ignore a token to be specially handled +Fypp guest parser run after Fypp parser parses the original input ("NONE" or a parser name [Fortran]) +ITcl forceUse enable the parser even when `itcl' namespace is not specified in the input (true or [false]) +Prolog allowNestedComments allow nested comments like "/* /* */ */" ([true] or false) +TclOO forceUse enable the parser even when `oo' namespace is not specified in the input (true or [false]) # ALL MACHINABLE #LANGUAGE NAME DESCRIPTION @@ -24,6 +25,7 @@ CPreProcessor if0 examine code within "#if 0" branch (true or [false]) CPreProcessor ignore a token to be specially handled Fypp guest parser run after Fypp parser parses the original input ("NONE" or a parser name [Fortran]) ITcl forceUse enable the parser even when `itcl' namespace is not specified in the input (true or [false]) +Prolog allowNestedComments allow nested comments like "/* /* */ */" ([true] or false) TclOO forceUse enable the parser even when `oo' namespace is not specified in the input (true or [false]) # ALL MACHINABLE NOHEADER @@ -37,6 +39,7 @@ CPreProcessor if0 examine code within "#if 0" branch (true or [false]) CPreProcessor ignore a token to be specially handled Fypp guest parser run after Fypp parser parses the original input ("NONE" or a parser name [Fortran]) ITcl forceUse enable the parser even when `itcl' namespace is not specified in the input (true or [false]) +Prolog allowNestedComments allow nested comments like "/* /* */ */" ([true] or false) TclOO forceUse enable the parser even when `oo' namespace is not specified in the input (true or [false]) # CPP diff --git a/Tmain/list-roles.d/stdout-expected.txt b/Tmain/list-roles.d/stdout-expected.txt index aa0bdfac9c..870c799216 100644 --- a/Tmain/list-roles.d/stdout-expected.txt +++ b/Tmain/list-roles.d/stdout-expected.txt @@ -98,6 +98,7 @@ Perl h/heredoc endmarker on 0 end mar PkgConfig p/pkg conflicted on 0 conflicted PkgConfig p/pkg provided on 0 provided PkgConfig p/pkg required on 0 required +Prolog m/module chainElt off 0 (EXPERIMENTAL)used as an element in a module-qualified atom like module:predicate Protobuf D/protodef imported on 0 imported Protobuf m/message extension on 0 extending the message Python Y/unknown imported on 0 imported from the other module @@ -248,6 +249,7 @@ Perl h/heredoc endmarker on 0 end mar PkgConfig p/pkg conflicted on 0 conflicted PkgConfig p/pkg provided on 0 provided PkgConfig p/pkg required on 0 required +Prolog m/module chainElt off 0 (EXPERIMENTAL)used as an element in a module-qualified atom like module:predicate Protobuf D/protodef imported on 0 imported Protobuf m/message extension on 0 extending the message Python Y/unknown imported on 0 imported from the other module diff --git a/Units/parser-prolog.r/code.d/args.ctags b/Units/parser-prolog.r/code.d/args.ctags new file mode 100644 index 0000000000..d93aeea872 --- /dev/null +++ b/Units/parser-prolog.r/code.d/args.ctags @@ -0,0 +1,4 @@ +-G +--sort=no +--extras=+q +--fields=+neEK diff --git a/Units/parser-prolog.r/code.d/expected.tags b/Units/parser-prolog.r/code.d/expected.tags new file mode 100644 index 0000000000..f915636c8d --- /dev/null +++ b/Units/parser-prolog.r/code.d/expected.tags @@ -0,0 +1,12 @@ +unicode_file_name input.pl /^unicode_file_name(Name) :-$/;" predicate line:44 end:47 arity:1 +unicode_file_name/1 input.pl /^unicode_file_name(Name) :-$/;" predicate line:44 extras:arityAppended end:47 arity:1 +unicode_file input.pl /^unicode_file(mkdir-1) :- % create Cyrillic directory$/;" predicate line:49 end:58 arity:1 +unicode_file/1 input.pl /^unicode_file(mkdir-1) :- % create Cyrillic directory$/;" predicate line:49 extras:arityAppended end:58 arity:1 +unicode_file input.pl /^unicode_file(file-1) :- % create Cyrillic file$/;" predicate line:59 end:71 arity:1 +unicode_file/1 input.pl /^unicode_file(file-1) :- % create Cyrillic file$/;" predicate line:59 extras:arityAppended end:71 arity:1 +unicode_file input.pl /^unicode_file(absfile-1) :-$/;" predicate line:72 end:78 arity:1 +unicode_file/1 input.pl /^unicode_file(absfile-1) :-$/;" predicate line:72 extras:arityAppended end:78 arity:1 +unicode_file input.pl /^unicode_file(ext-1) :-$/;" predicate line:79 end:83 arity:1 +unicode_file/1 input.pl /^unicode_file(ext-1) :-$/;" predicate line:79 extras:arityAppended end:83 arity:1 +seek input.pl /^seek(write-1) :-$/;" predicate line:90 end:108 arity:1 +seek/1 input.pl /^seek(write-1) :-$/;" predicate line:90 extras:arityAppended end:108 arity:1 diff --git a/Units/parser-prolog.r/code.d/input.pl b/Units/parser-prolog.r/code.d/input.pl new file mode 100644 index 0000000000..e165388d98 --- /dev/null +++ b/Units/parser-prolog.r/code.d/input.pl @@ -0,0 +1,108 @@ +% Taken from pl-9.2.9-build/swipl-9.2.9/src/test.pl +% 0'. can be a trouble. + +/* Part of SWI-Prolog + + Author: Jan Wielemaker and Anjo Anjewierden + E-mail: J.Wielemaker@cs.vu.nl + WWW: http://www.swi-prolog.org + Copyright (c) 1996-2023, University of Amsterdam + VU University Amsterdam + CWI, Amsterdam + SWI-Prolog Solutions b.v. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + /******************************* + * UNICODE FILENAMES * + *******************************/ + +unicode_file_name(Name) :- + current_prolog_flag(pid, Pid), + atom_codes(Name0, [1074, 1086, 1079, 1076, 1091, 1093, 1072]), + atomic_list_concat([Name0, -, Pid], Name). + +unicode_file(mkdir-1) :- % create Cyrillic directory + unicode_file_name(Dir), + catch(delete_directory(Dir), _, true), + make_directory(Dir), + exists_directory(Dir), + working_directory(Old, Dir), + working_directory(O2, '..'), + same_file(Old, '.'), + same_file(O2, Dir), + delete_directory(Dir). +unicode_file(file-1) :- % create Cyrillic file + unicode_file_name(File), + Term = hello(world), + catch(delete_file(File), _, true), + open(File, write, Out), + format(Out, '~q.~n', [Term]), + close(Out), + exists_file(File), + open(File, read, In), + read(In, Read), + close(In), + Read =@= Term, + delete_file(File). +unicode_file(absfile-1) :- + unicode_file_name(File), + absolute_file_name(File, Path), + file_directory_name(Path, Dir), + same_file(Dir, '.'), + file_base_name(Path, Base), + Base == File. +unicode_file(ext-1) :- + atom_codes(File, [1074, 1086, 1079, 1076, 0'., 1091, 1093, 1072]), + file_name_extension(Base, Ext, File), + atom_codes(Base, [1074, 1086, 1079, 1076]), + atom_codes(Ext, [1091, 1093, 1072]). + + + /******************************* + * SEEK * + *******************************/ + +seek(write-1) :- + tmp_file(seek, File), + open(File, write, S, [type(binary)]), + Max = 999, + forall(between(0, Max, _), + format(S, '1234567890~n', [])), + forall(between(0, Max, N), + ( Pos is N * 11 + 6, + seek(S, Pos, bof, _), + format(S, 'x', []) + )), + close(S), + + open(File, read, In, [type(binary)]), + atom_codes('123456x890\n', Bytes), + forall(between(0, Max, N), + must_read(Bytes, In)), + close(In), + delete_file(File). diff --git a/Units/parser-prolog.r/dcg.d/args.ctags b/Units/parser-prolog.r/dcg.d/args.ctags new file mode 100644 index 0000000000..a47c3a8063 --- /dev/null +++ b/Units/parser-prolog.r/dcg.d/args.ctags @@ -0,0 +1,3 @@ +-G +--sort=no +--fields=+neEK diff --git a/Units/parser-prolog.r/dcg.d/expected.tags b/Units/parser-prolog.r/dcg.d/expected.tags new file mode 100644 index 0000000000..2445f1f7e0 --- /dev/null +++ b/Units/parser-prolog.r/dcg.d/expected.tags @@ -0,0 +1,18 @@ +server input.pl /^server :-$/;" predicate line:27 end:28 arity:0 +server/0 input.pl /^server :-$/;" predicate line:27 extras:arityAppended end:28 arity:0 +server input.pl /^server(Port, Options) :-$/;" predicate line:30 end:35 arity:2 +server/2 input.pl /^server(Port, Options) :-$/;" predicate line:30 extras:arityAppended end:35 arity:2 +reply input.pl /^reply(Request) :-$/;" predicate line:37 end:39 arity:1 +reply/1 input.pl /^reply(Request) :-$/;" predicate line:37 extras:arityAppended end:39 arity:1 +reply input.pl /^reply(\/, _Request) :-$/;" predicate line:41 end:45 arity:2 +reply/2 input.pl /^reply(\/, _Request) :-$/;" predicate line:41 extras:arityAppended end:45 arity:2 +reply input.pl /^reply('\/calc', Request) :-$/;" predicate line:47 end:56 arity:2 +reply/2 input.pl /^reply('\/calc', Request) :-$/;" predicate line:47 extras:arityAppended end:56 arity:2 +page input.pl /^page(Formula) :-$/;" predicate line:59 end:74 arity:1 +page/1 input.pl /^page(Formula) :-$/;" predicate line:59 extras:arityAppended end:74 arity:1 +formula input.pl /^formula(Formula) -->$/;" grammar line:76 end:80 arity:1 +formula/1 input.pl /^formula(Formula) -->$/;" grammar line:76 extras:arityAppended end:80 arity:1 +ops input.pl /^ops -->$/;" grammar line:82 end:88 arity:0 +ops/0 input.pl /^ops -->$/;" grammar line:82 extras:arityAppended end:88 arity:0 +reply_page input.pl /^reply_page(Title, Content) :-$/;" predicate line:90 end:93 arity:2 +reply_page/2 input.pl /^reply_page(Title, Content) :-$/;" predicate line:90 extras:arityAppended end:93 arity:2 diff --git a/Units/parser-prolog.r/dcg.d/input.pl b/Units/parser-prolog.r/dcg.d/input.pl new file mode 100644 index 0000000000..0492e12948 --- /dev/null +++ b/Units/parser-prolog.r/dcg.d/input.pl @@ -0,0 +1,93 @@ +% Taken from swipl-9.2.9 +/* $Id$ + + Part of SWI-Prolog + + Author: Jan Wielemaker + E-mail: wielemak@science.uva.nl + WWW: http://www.swi-prolog.org + Copyright (C): Public domain +*/ + +:- use_module(library('http/thread_httpd')). +:- use_module(library('http/html_write')). +:- use_module(library('http/http_session')). +:- use_module(library('http/http_error')). + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +This demo shows session state management in a very simple calculator +package. It also demonstrates the use of the html_write library. To use +it, start Prolog, load this file and run + + ?- server. + +Now direct your browser to http://localhost:3000/ +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +server :- + server(3000, []). + +server(Port, Options) :- + http_server(reply, + [ port(Port), + timeout(20) + | Options + ]). + +reply(Request) :- + memberchk(path(Path), Request), + reply(Path, Request). + +reply(/, _Request) :- + http_session_retractall(formula(_)), + Formula = 0, + http_session_assert(formula(Formula)), + page(Formula). + +reply('/calc', Request) :- + memberchk(search(Search), Request), + memberchk(operation=Op, Search), + memberchk(value=AtomVal, Search), + atom_number(AtomVal, Val), + http_session_retract(formula(Formula0)), + debug(calc, 'Formula0 = ~w', [Formula0]), + Formula =.. [Op, Formula0, Val], + http_session_assert(formula(Formula)), + page(Formula). + + +page(Formula) :- + reply_page('HTTP Session DEMO', + [ h2('Simple session demo'), + form([ action('/calc'), + method('GET') + ], + table([align(center), border(1)], + [ tr(td(\formula(Formula))), + tr(td([ \ops, + input([ name(value) ]), + input([ type(submit), + value('Calc!') + ]) + ])) + ])) + ]). + +formula(Formula) --> + { sformat(S, '~w', [Formula]), + Value is Formula + }, + html([ S, ' = ', Value ]). + +ops --> + html(select(name(operation), + [ option([selected], +), + option([], -), + option([], /), + option([], *) + ])). + +reply_page(Title, Content) :- + phrase(page(title(Title), Content), HTML), + format('Content-type: text/html~n~n'), + print_html(HTML). diff --git a/Units/parser-prolog.r/module.d/args.ctags b/Units/parser-prolog.r/module.d/args.ctags new file mode 100644 index 0000000000..d93aeea872 --- /dev/null +++ b/Units/parser-prolog.r/module.d/args.ctags @@ -0,0 +1,4 @@ +-G +--sort=no +--extras=+q +--fields=+neEK diff --git a/Units/parser-prolog.r/module.d/expected.tags b/Units/parser-prolog.r/module.d/expected.tags new file mode 100644 index 0000000000..4260cfc0fe --- /dev/null +++ b/Units/parser-prolog.r/module.d/expected.tags @@ -0,0 +1,33 @@ +clpq input.pl /^:- module(clpq,$/;" module line:42 +portray_message input.pl /^user:portray_message(warning,import(_,_,clpq,private)).$/;" predicate line:67 module:user end:67 arity:2 +user:portray_message input.pl /^user:portray_message(warning,import(_,_,clpq,private)).$/;" predicate line:67 module:user extras:qualified end:67 arity:2 +portray_message/2 input.pl /^user:portray_message(warning,import(_,_,clpq,private)).$/;" predicate line:67 module:user extras:arityAppended end:67 arity:2 +user:portray_message/2 input.pl /^user:portray_message(warning,import(_,_,clpq,private)).$/;" predicate line:67 module:user extras:qualified,arityAppended end:67 arity:2 +message input.pl /^prolog:message(query(YesNo,Bindings)) --> !,$/;" grammar line:93 module:prolog end:96 arity:1 +prolog:message input.pl /^prolog:message(query(YesNo,Bindings)) --> !,$/;" grammar line:93 module:prolog extras:qualified end:96 arity:1 +message/1 input.pl /^prolog:message(query(YesNo,Bindings)) --> !,$/;" grammar line:93 module:prolog extras:arityAppended end:96 arity:1 +prolog:message/1 input.pl /^prolog:message(query(YesNo,Bindings)) --> !,$/;" grammar line:93 module:prolog extras:qualified,arityAppended end:96 arity:1 +dump_toplevel_bindings input.pl /^dump_toplevel_bindings(Bindings,Constraints) :-$/;" predicate line:98 module:clpq end:100 arity:2 +clpq:dump_toplevel_bindings input.pl /^dump_toplevel_bindings(Bindings,Constraints) :-$/;" predicate line:98 module:clpq extras:qualified end:100 arity:2 +dump_toplevel_bindings/2 input.pl /^dump_toplevel_bindings(Bindings,Constraints) :-$/;" predicate line:98 module:clpq extras:arityAppended end:100 arity:2 +clpq:dump_toplevel_bindings/2 input.pl /^dump_toplevel_bindings(Bindings,Constraints) :-$/;" predicate line:98 module:clpq extras:qualified,arityAppended end:100 arity:2 +dump_vars_names input.pl /^dump_vars_names([],_,[],[]).$/;" predicate line:102 module:clpq end:102 arity:4 +clpq:dump_vars_names input.pl /^dump_vars_names([],_,[],[]).$/;" predicate line:102 module:clpq extras:qualified end:102 arity:4 +dump_vars_names/4 input.pl /^dump_vars_names([],_,[],[]).$/;" predicate line:102 module:clpq extras:arityAppended end:102 arity:4 +clpq:dump_vars_names/4 input.pl /^dump_vars_names([],_,[],[]).$/;" predicate line:102 module:clpq extras:qualified,arityAppended end:102 arity:4 +dump_vars_names input.pl /^dump_vars_names([Name=Term|Rest],Seen,Vars,Names) :-$/;" predicate line:103 module:clpq end:116 arity:4 +clpq:dump_vars_names input.pl /^dump_vars_names([Name=Term|Rest],Seen,Vars,Names) :-$/;" predicate line:103 module:clpq extras:qualified end:116 arity:4 +dump_vars_names/4 input.pl /^dump_vars_names([Name=Term|Rest],Seen,Vars,Names) :-$/;" predicate line:103 module:clpq extras:arityAppended end:116 arity:4 +clpq:dump_vars_names/4 input.pl /^dump_vars_names([Name=Term|Rest],Seen,Vars,Names) :-$/;" predicate line:103 module:clpq extras:qualified,arityAppended end:116 arity:4 +dump_format input.pl /^dump_format([]) --> [].$/;" grammar line:118 module:clpq end:118 arity:1 +clpq:dump_format input.pl /^dump_format([]) --> [].$/;" grammar line:118 module:clpq extras:qualified end:118 arity:1 +dump_format/1 input.pl /^dump_format([]) --> [].$/;" grammar line:118 module:clpq extras:arityAppended end:118 arity:1 +clpq:dump_format/1 input.pl /^dump_format([]) --> [].$/;" grammar line:118 module:clpq extras:qualified,arityAppended end:118 arity:1 +dump_format input.pl /^dump_format([X|Xs]) -->$/;" grammar line:119 module:clpq end:121 arity:1 +clpq:dump_format input.pl /^dump_format([X|Xs]) -->$/;" grammar line:119 module:clpq extras:qualified end:121 arity:1 +dump_format/1 input.pl /^dump_format([X|Xs]) -->$/;" grammar line:119 module:clpq extras:arityAppended end:121 arity:1 +clpq:dump_format/1 input.pl /^dump_format([X|Xs]) -->$/;" grammar line:119 module:clpq extras:qualified,arityAppended end:121 arity:1 +memberchk_eq input.pl /^memberchk_eq(X,[Y|Ys]) :-$/;" predicate line:123 module:clpq end:127 arity:2 +clpq:memberchk_eq input.pl /^memberchk_eq(X,[Y|Ys]) :-$/;" predicate line:123 module:clpq extras:qualified end:127 arity:2 +memberchk_eq/2 input.pl /^memberchk_eq(X,[Y|Ys]) :-$/;" predicate line:123 module:clpq extras:arityAppended end:127 arity:2 +clpq:memberchk_eq/2 input.pl /^memberchk_eq(X,[Y|Ys]) :-$/;" predicate line:123 module:clpq extras:qualified,arityAppended end:127 arity:2 diff --git a/Units/parser-prolog.r/module.d/input.pl b/Units/parser-prolog.r/module.d/input.pl new file mode 100644 index 0000000000..e053c1f230 --- /dev/null +++ b/Units/parser-prolog.r/module.d/input.pl @@ -0,0 +1,127 @@ +% Taken from swipl-9.2.9 + +/* + + Part of CLP(Q) (Constraint Logic Programming over Rationals) + + Author: Leslie De Koninck + E-mail: Leslie.DeKoninck@cs.kuleuven.be + WWW: http://www.swi-prolog.org + http://www.ai.univie.ac.at/cgi-bin/tr-online?number+95-09 + Copyright (C): 2006, K.U. Leuven and + 1992-1995, Austrian Research Institute for + Artificial Intelligence (OFAI), + Vienna, Austria + + This software is based on CLP(Q,R) by Christian Holzbaur for SICStus + Prolog and distributed under the license details below with permission from + all mentioned authors. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + As a special exception, if you link this library with other files, + compiled with a Free Software compiler, to produce an executable, this + library does not by itself cause the resulting executable to be covered + by the GNU General Public License. This exception does not however + invalidate any other reasons why the executable file might be covered by + the GNU General Public License. +*/ + +:- module(clpq, + [ {}/1, + maximize/1, + minimize/1, + inf/2, inf/4, sup/2, sup/4, + bb_inf/3, + bb_inf/4, + ordering/1, + entailed/1, + clp_type/2, + dump/3%, projecting_assert/1 + ]). +:- license(gpl_swipl, 'CLP(Q)'). +:- use_module(library(dialect)). +:- expects_dialect(swi). + +% +% Don't report export of private predicates from clpq +% +:- multifile + user:portray_message/2. + +:- dynamic + user:portray_message/2. +% +user:portray_message(warning,import(_,_,clpq,private)). + +:- use_module([ clpq/bb_q, + clpq/bv_q, + clpq/fourmotz_q, + clpq/ineq_q, + clpq/itf_q, + clpq/nf_q, + clpq/store_q, + clpqr/class, + clpqr/dump, + clpqr/geler, + clpqr/itf, + clpqr/ordering, + clpqr/project, + clpqr/redund, + library(ugraphs) + ]). + + /******************************* + * TOPLEVEL PRINTING * + *******************************/ + +:- multifile + prolog:message/3. + +prolog:message(query(YesNo,Bindings)) --> !, + {dump_toplevel_bindings(Bindings,Constraints)}, + dump_format(Constraints), + '$messages':prolog_message(query(YesNo,Bindings)). + +dump_toplevel_bindings(Bindings,Constraints) :- + dump_vars_names(Bindings,[],Vars,Names), + dump(Vars,Names,Constraints). + +dump_vars_names([],_,[],[]). +dump_vars_names([Name=Term|Rest],Seen,Vars,Names) :- + ( var(Term), + ( get_attr(Term,clpqr_itf,_) + ; get_attr(Term,clpqr_geler,_) + ), + \+ memberchk_eq(Term,Seen) + -> Vars = [Term|RVars], + Names = [Name|RNames], + NSeen = [Term|Seen] + ; Vars = RVars, + Names = RNames, + Seen = NSeen + ), + dump_vars_names(Rest,NSeen,RVars,RNames). + +dump_format([]) --> []. +dump_format([X|Xs]) --> + ['{~w}'-[X], nl], + dump_format(Xs). + +memberchk_eq(X,[Y|Ys]) :- + ( X == Y + -> true + ; memberchk_eq(X,Ys) + ). diff --git a/Units/parser-prolog.r/simple-flat-comment.d/args.ctags b/Units/parser-prolog.r/simple-flat-comment.d/args.ctags new file mode 100644 index 0000000000..b36a1605b9 --- /dev/null +++ b/Units/parser-prolog.r/simple-flat-comment.d/args.ctags @@ -0,0 +1,4 @@ +-G +--sort=no +--fields=+nEK +--param-Prolog.allowNestedComments=0 diff --git a/Units/parser-prolog.r/simple-flat-comment.d/expected.tags b/Units/parser-prolog.r/simple-flat-comment.d/expected.tags new file mode 100644 index 0000000000..c7ea8bbff1 --- /dev/null +++ b/Units/parser-prolog.r/simple-flat-comment.d/expected.tags @@ -0,0 +1,28 @@ +mother_child input.pl /^mother_child(trude, sally).$/;" predicate line:2 arity:2 +mother_child/2 input.pl /^mother_child(trude, sally).$/;" predicate line:2 extras:arityAppended arity:2 +father_child input.pl /^father_child(tom, sally).$/;" predicate line:4 arity:2 +father_child/2 input.pl /^father_child(tom, sally).$/;" predicate line:4 extras:arityAppended arity:2 +father_child input.pl /^father_child(tom, erica).$/;" predicate line:5 arity:2 +father_child/2 input.pl /^father_child(tom, erica).$/;" predicate line:5 extras:arityAppended arity:2 +father_child input.pl /^father_child(mike, tom).$/;" predicate line:6 arity:2 +father_child/2 input.pl /^father_child(mike, tom).$/;" predicate line:6 extras:arityAppended arity:2 +sibling input.pl /^sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).$/;" predicate line:8 arity:2 +sibling/2 input.pl /^sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).$/;" predicate line:8 extras:arityAppended arity:2 +parent_child input.pl /^parent_child(X, Y) :- father_child(X, Y).$/;" predicate line:10 arity:2 +parent_child/2 input.pl /^parent_child(X, Y) :- father_child(X, Y).$/;" predicate line:10 extras:arityAppended arity:2 +parent_child input.pl /^parent_child(X, Y) :- mother_child(X, Y).$/;" predicate line:11 arity:2 +parent_child/2 input.pl /^parent_child(X, Y) :- mother_child(X, Y).$/;" predicate line:11 extras:arityAppended arity:2 +not_dummy input.pl /^not_dummy.$/;" predicate line:16 arity:0 +not_dummy/0 input.pl /^not_dummy.$/;" predicate line:16 extras:arityAppended arity:0 +'quoted predicate' input.pl /^'quoted predicate'($/;" predicate line:18 arity:1 +'quoted predicate'/1 input.pl /^'quoted predicate'($/;" predicate line:18 extras:arityAppended arity:1 +rel input.pl /^rel(X,Y,Z) :- Z =:= X + Y + 0.25.$/;" predicate line:23 arity:3 +rel/3 input.pl /^rel(X,Y,Z) :- Z =:= X + Y + 0.25.$/;" predicate line:23 extras:arityAppended arity:3 +rel input.pl /^rel(X,Y) :- Y =:= X + 0.25.$/;" predicate line:24 arity:2 +rel/2 input.pl /^rel(X,Y) :- Y =:= X + 0.25.$/;" predicate line:24 extras:arityAppended arity:2 +rel input.pl /^rel(X) :- X =:= 100_000.$/;" predicate line:25 arity:1 +rel/1 input.pl /^rel(X) :- X =:= 100_000.$/;" predicate line:25 extras:arityAppended arity:1 +rel0 input.pl /^rel0(X) :- X =:= 100_000 0.$/;" predicate line:27 arity:1 +rel0/1 input.pl /^rel0(X) :- X =:= 100_000 0.$/;" predicate line:27 extras:arityAppended arity:1 +rel0 input.pl /^rel0(X, 100_000_11, Y) :- X =:= Y.$/;" predicate line:28 arity:3 +rel0/3 input.pl /^rel0(X, 100_000_11, Y) :- X =:= Y.$/;" predicate line:28 extras:arityAppended arity:3 diff --git a/Units/parser-prolog.r/simple-flat-comment.d/input.pl b/Units/parser-prolog.r/simple-flat-comment.d/input.pl new file mode 100644 index 0000000000..160a111965 --- /dev/null +++ b/Units/parser-prolog.r/simple-flat-comment.d/input.pl @@ -0,0 +1,28 @@ +%% Taken from https://en.wikipedia.org/wiki/Prolog +mother_child(trude, sally). + +father_child(tom, sally). +father_child(tom, erica). +father_child(mike, tom). + +sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y). + +parent_child(X, Y) :- father_child(X, Y). +parent_child(X, Y) :- mother_child(X, Y). + +% dummy0() +/* dummy1() */ +/* /* dummy2() */ +not_dummy. + +'quoted predicate'( +X +) :- + father_child(tom, X). + +rel(X,Y,Z) :- Z =:= X + Y + 0.25. +rel(X,Y) :- Y =:= X + 0.25. +rel(X) :- X =:= 100_000. + +rel0(X) :- X =:= 100_000 0. +rel0(X, 100_000_11, Y) :- X =:= Y. diff --git a/Units/parser-prolog.r/simple.d/args.ctags b/Units/parser-prolog.r/simple.d/args.ctags new file mode 100644 index 0000000000..71bea42029 --- /dev/null +++ b/Units/parser-prolog.r/simple.d/args.ctags @@ -0,0 +1,4 @@ +-G +--sort=no +--fields=+nEK +--param-Prolog.allowNestedComments=1 diff --git a/Units/parser-prolog.r/simple.d/expected.tags b/Units/parser-prolog.r/simple.d/expected.tags new file mode 100644 index 0000000000..c7ea8bbff1 --- /dev/null +++ b/Units/parser-prolog.r/simple.d/expected.tags @@ -0,0 +1,28 @@ +mother_child input.pl /^mother_child(trude, sally).$/;" predicate line:2 arity:2 +mother_child/2 input.pl /^mother_child(trude, sally).$/;" predicate line:2 extras:arityAppended arity:2 +father_child input.pl /^father_child(tom, sally).$/;" predicate line:4 arity:2 +father_child/2 input.pl /^father_child(tom, sally).$/;" predicate line:4 extras:arityAppended arity:2 +father_child input.pl /^father_child(tom, erica).$/;" predicate line:5 arity:2 +father_child/2 input.pl /^father_child(tom, erica).$/;" predicate line:5 extras:arityAppended arity:2 +father_child input.pl /^father_child(mike, tom).$/;" predicate line:6 arity:2 +father_child/2 input.pl /^father_child(mike, tom).$/;" predicate line:6 extras:arityAppended arity:2 +sibling input.pl /^sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).$/;" predicate line:8 arity:2 +sibling/2 input.pl /^sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y).$/;" predicate line:8 extras:arityAppended arity:2 +parent_child input.pl /^parent_child(X, Y) :- father_child(X, Y).$/;" predicate line:10 arity:2 +parent_child/2 input.pl /^parent_child(X, Y) :- father_child(X, Y).$/;" predicate line:10 extras:arityAppended arity:2 +parent_child input.pl /^parent_child(X, Y) :- mother_child(X, Y).$/;" predicate line:11 arity:2 +parent_child/2 input.pl /^parent_child(X, Y) :- mother_child(X, Y).$/;" predicate line:11 extras:arityAppended arity:2 +not_dummy input.pl /^not_dummy.$/;" predicate line:16 arity:0 +not_dummy/0 input.pl /^not_dummy.$/;" predicate line:16 extras:arityAppended arity:0 +'quoted predicate' input.pl /^'quoted predicate'($/;" predicate line:18 arity:1 +'quoted predicate'/1 input.pl /^'quoted predicate'($/;" predicate line:18 extras:arityAppended arity:1 +rel input.pl /^rel(X,Y,Z) :- Z =:= X + Y + 0.25.$/;" predicate line:23 arity:3 +rel/3 input.pl /^rel(X,Y,Z) :- Z =:= X + Y + 0.25.$/;" predicate line:23 extras:arityAppended arity:3 +rel input.pl /^rel(X,Y) :- Y =:= X + 0.25.$/;" predicate line:24 arity:2 +rel/2 input.pl /^rel(X,Y) :- Y =:= X + 0.25.$/;" predicate line:24 extras:arityAppended arity:2 +rel input.pl /^rel(X) :- X =:= 100_000.$/;" predicate line:25 arity:1 +rel/1 input.pl /^rel(X) :- X =:= 100_000.$/;" predicate line:25 extras:arityAppended arity:1 +rel0 input.pl /^rel0(X) :- X =:= 100_000 0.$/;" predicate line:27 arity:1 +rel0/1 input.pl /^rel0(X) :- X =:= 100_000 0.$/;" predicate line:27 extras:arityAppended arity:1 +rel0 input.pl /^rel0(X, 100_000_11, Y) :- X =:= Y.$/;" predicate line:28 arity:3 +rel0/3 input.pl /^rel0(X, 100_000_11, Y) :- X =:= Y.$/;" predicate line:28 extras:arityAppended arity:3 diff --git a/Units/parser-prolog.r/simple.d/input.pl b/Units/parser-prolog.r/simple.d/input.pl new file mode 100644 index 0000000000..63d8053d1d --- /dev/null +++ b/Units/parser-prolog.r/simple.d/input.pl @@ -0,0 +1,28 @@ +%% Taken from https://en.wikipedia.org/wiki/Prolog +mother_child(trude, sally). + +father_child(tom, sally). +father_child(tom, erica). +father_child(mike, tom). + +sibling(X, Y) :- parent_child(Z, X), parent_child(Z, Y). + +parent_child(X, Y) :- father_child(X, Y). +parent_child(X, Y) :- mother_child(X, Y). + +% dummy0() +/* dummy1() */ +/* /* dummy2() */ */ +not_dummy. + +'quoted predicate'( +X +) :- + father_child(tom, X). + +rel(X,Y,Z) :- Z =:= X + Y + 0.25. +rel(X,Y) :- Y =:= X + 0.25. +rel(X) :- X =:= 100_000. + +rel0(X) :- X =:= 100_000 0. +rel0(X, 100_000_11, Y) :- X =:= Y. diff --git a/docs/news/HEAD.rst b/docs/news/HEAD.rst index 0faa201c21..859755b5a3 100644 --- a/docs/news/HEAD.rst +++ b/docs/news/HEAD.rst @@ -44,6 +44,7 @@ The following parsers have been added: * SINEX: to handle SINEX (Solution INdependent EXchange) files * Netfilter: to handle the output of "nft list ..." command +* Prolog Changes about parser specific kinds, roles, fields, and extras ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/main/parsers_p.h b/main/parsers_p.h index c4cc4429de..2c16addd53 100644 --- a/main/parsers_p.h +++ b/main/parsers_p.h @@ -149,6 +149,7 @@ PkgConfigParser, \ PodParser, \ PowerShellParser, \ + PrologParser, \ ProtobufParser, \ PuppetManifestParser, \ PythonParser, \ diff --git a/main/selectors.c b/main/selectors.c index 6960cd46ba..fe7f31040f 100644 --- a/main/selectors.c +++ b/main/selectors.c @@ -43,6 +43,8 @@ static const char *TR_FORTRAN = "Fortran"; static const char *TR_V = "V"; static const char *TR_VERILOG = "Verilog"; +static const char *TR_PROLOG = "Prolog"; + #define startsWith(line,prefix) \ (strncmp(line, prefix, strlen(prefix)) == 0? true: false) @@ -422,6 +424,64 @@ selectVOrVerilogByKeywords (MIO *input, return TR_UNKNOWN; } +struct PerlOrPrologScore { + int perl; + int prolog; + unsigned int linum; +}; + +static const char * +tastePerlOrPrologLines (const char *line, void *data) +{ + struct PerlOrPrologScore *score = (struct PerlOrPrologScore *)data; + + score->linum++; + + if (score->linum > 16) + return TR_BREAK; + + if (line[0] == '#' && line[1] != '!') + { + /* This is not a shebang: the comment line of perl */ + score->perl++; + } + else if (line[0] == '%') + { + score->prolog++; + } + else if (startsWith (line, "use ")) + { + score->perl++; + } + else if (startsWith (line, ":-")) + score->prolog += 2; + else if (strstr (line, ":-")) + score->prolog++; + else if (strstr (line, "/*")) + score->prolog++; + + return TR_UNKNOWN; +} + +const char * +selectPerlOrPrologByDistinctiveToken (struct _MIO *input, langType *candidates, unsigned int nCandidates) +{ + struct PerlOrPrologScore score = { + .perl = 0, + .prolog = 0, + .linum = 0, + }; + selectByLines (input, tastePerlOrPrologLines, TR_UNKNOWN, &score); + + int d = score.perl - score.prolog; + if (d > 0) + return TR_PERL5; + else if (d < 0) + return TR_PROLOG; + else + return TR_UNKNOWN; +} + #ifdef HAVE_LIBXML #include #include diff --git a/main/selectors.h b/main/selectors.h index fe48c64773..7571b7d51a 100644 --- a/main/selectors.h +++ b/main/selectors.h @@ -39,4 +39,7 @@ selectByXpathFileSpec (struct _MIO *input, langType *candidates, unsigned int nC const char * selectFortranOrForthByForthMarker (struct _MIO *input, langType *candidates, unsigned int nCandidates); +const char * +selectPerlOrPrologByDistinctiveToken (struct _MIO *input, langType *candidates, unsigned int nCandidates); + #endif diff --git a/parsers/perl.c b/parsers/perl.c index 49992599f0..b566464a9a 100644 --- a/parsers/perl.c +++ b/parsers/perl.c @@ -1019,8 +1019,10 @@ extern parserDefinition* PerlParser (void) /* cperl is an Emacs' editing mode for Perl source code */ "cperl", NULL }; - static selectLanguage selectors [] = { selectByPickingPerlVersion, - NULL }; + static selectLanguage selectors [] = { + selectPerlOrPrologByDistinctiveToken, + selectByPickingPerlVersion, + NULL }; parserDefinition* def = parserNew ("Perl"); def->kindTable = PerlKinds; def->kindCount = ARRAY_SIZE (PerlKinds); diff --git a/parsers/prolog.c b/parsers/prolog.c new file mode 100644 index 0000000000..2257441ab4 --- /dev/null +++ b/parsers/prolog.c @@ -0,0 +1,730 @@ +/* +* Copyright (c) 2025, Masatake YAMATO +* +* This source code is released for free distribution under the terms of the +* GNU General Public License version 2 or (at your option) any later version. +* +* This module contains functions for generating tags for prolog source file. +* +* References: +* - https://www.swi-prolog.org/pldoc/man?section=syntax +* - https://sicstus.sics.se/sicstus/docs/3.7.1/html/sicstus_45.html +* - https://www.az-prolog.com/manual/manuals/manual_program.html (in Japanese) +* +*/ + +/* +* INCLUDE FILES +*/ +#include "general.h" /* must always come first */ + +#include "entry.h" +#include "field.h" +#include "keyword.h" +#include "param.h" +#include "parse.h" +#include "read.h" +#include "routines.h" +#include "selectors.h" +#include "tokeninfo.h" +#include "vstring.h" +#include "xtag.h" + +#include + +/* +* DATA DECLARATIONS +*/ + +typedef enum { + K_PREDICATE, + K_GRAMMAR, + K_MODULE, +} prologKind; + +typedef enum { + F_ARITY, +} prologField; + +typedef enum { + X_ARITY, +} prologXtag; + +typedef enum { + R_MODULE_CHAINELT, +} prologModuleRole; + + +typedef enum { + /* 0..255 are the byte's value */ + TOKEN_EOF = 256, + TOKEN_UNDEFINED, + TOKEN_KEYWORD, + + TOKEN_STRATOM, + TOKEN_STRING, + TOKEN_APPLY, + TOKEN_RULEOP, + TOKEN_DCGOP, + + TOKEN_CODE, + TOKEN_ATOM, + TOKEN_VAR, + TOKEN_NUM, + +} prologTokenType; + +typedef enum { + KEYWORD_MODULE, +#if 0 + KEYWORD_USE_MODULE, + KEYWORD_AUTOLOAD, + KEYWORD_LIBRARY, +#endif +} prologKeyword; + +/* +* FUNCTION PROTOTYPES +*/ + +static void readToken (tokenInfo *const token, void *data CTAGS_ATTR_UNUSED); + +/* +* DATA DEFINITIONS +*/ + +static roleDefinition PrologModuleRoles [] = { + /* Currently V parser wants this items. */ + { false, "chainElt", "(EXPERIMENTAL)used as an element in a module-qualified atom like module:predicate" }, +}; + +static kindDefinition PrologKinds [] = { + {true, 'p', "predicate", "predicates", }, + {true, 'g', "grammar", "grammars", }, + {true, 'm', "module", "modules", + .referenceOnly = false, ATTACH_ROLES(PrologModuleRoles), + }, +}; + +static fieldDefinition PrologFields[] = { + { .name = "arity", + .description = "the number of parameters", + .enabled = true, + .dataType = FIELDTYPE_INTEGER, + }, +}; + +static xtagDefinition PrologXtags [] = { + { .enabled = true, + .name = "arityAppended", + .description = "Include predicates with their arities", + }, +}; + +static bool prologAllowNestedComments = true; +static bool prologAllowNestedCommentsHandler (const langType language CTAGS_ATTR_UNUSED, + const char *name, const char *arg) +{ + prologAllowNestedComments = paramParserBool (arg, prologAllowNestedComments, name, "parameter"); + return true; +} + +static paramDefinition PrologParams [] = { + { .name = "allowNestedComments", + .desc = "allow nested comments like \"/* /* */ */\" ([true] or false)", + .handleParam = prologAllowNestedCommentsHandler, + /* https://www.swi-prolog.org/pldoc/man?section=nestedcomments */ + }, +}; + +static struct tokenTypePair prologTypePairs [] = { + { '(', ')' }, + { '[', ']' }, + { '{', '}' }, +}; + +static const keywordTable PrologKeywords[] = { + { "module", KEYWORD_MODULE }, +}; + +static struct tokenInfoClass prologTokenInfoClass = { + .nPreAlloc = 4, + .typeForUndefined = TOKEN_UNDEFINED, + .keywordNone = KEYWORD_NONE, + .typeForKeyword = TOKEN_KEYWORD, + .typeForEOF = TOKEN_EOF, + .extraSpace = 0, + .pairs = prologTypePairs, + .pairCount = ARRAY_SIZE (prologTypePairs), + .read = readToken, +}; + +static langType Lang_prolog; + +/* +* FUNCTION DEFINITIONS +*/ + +static tokenInfo *newPrologToken (void) +{ + return newToken (&prologTokenInfoClass); +} + +static void skipNestedBlockComment (int c) +{ + int depth = 1; + + while (c != EOF) + { + if (c == '/') + { + c = getcFromInputFile (); + if (c == '*') + { + ++depth; + c = getcFromInputFile (); + } + } + else if (c == '*') + { + c = getcFromInputFile (); + if (c == '/') + { + if (--depth == 0) + return; + c = getcFromInputFile (); + } + } + else + c = getcFromInputFile (); + } +} + +static void skipBlockComment (int c) +{ + while (c != EOF) + { + if (c == '*') + { + c = getcFromInputFile (); + if (c == '/') + return; + } + else + c = getcFromInputFile (); + } +} + +static void readString (tokenInfo *const token, int c) +{ + int terminator = c; + + tokenPutc (token, c); + c = getcFromInputFile (); + + while (c != EOF) + { + tokenPutc (token, c); + + if (c == '\\') + { + /* consume the next char */ + c = getcFromInputFile (); + if (c != EOF) + { + tokenPutc (token, c); + c = getcFromInputFile (); + } + continue; + } + + if (c == terminator) + return; + + c = getcFromInputFile (); + } +} + +static void readNumber (tokenInfo *const token, int c) +{ + bool dpoint_seen = false; + + tokenPutc (token, c); + c = getcFromInputFile (); + + while (c != EOF) + { + // SWI prolog accepts: + // + // 1_000_000 + // 1 000 000 + // 1_000_/*more*/000 + // + // We handle _ here. + // + if (isdigit (c) || c == '_') + { + tokenPutc (token, c); + c = getcFromInputFile (); + continue; + } + + if (c == '.') + { + if (dpoint_seen) + { + ungetcToInputFile ('.'); + return; + } + + dpoint_seen = true; + int c0 = getcFromInputFile (); + if (isdigit (c0)) + { + tokenPutc (token, '.'); + tokenPutc (token, c0); + c = getcFromInputFile (); + continue; + } + + ungetcToInputFile (c0); + ungetcToInputFile ('.'); + return; + } + + ungetcToInputFile (c); + return; + } +} + +static void readAtom (tokenInfo *const token, int c) +{ + tokenPutc (token, c); + c = getcFromInputFile (); + + while (c != EOF) + { + if (isalnum (c) || c == '_') + { + tokenPutc (token, c); + c = getcFromInputFile (); + continue; + } + + ungetcToInputFile (c); + return; + } +} + +static void readToken (tokenInfo *const token, void *data CTAGS_ATTR_UNUSED) +{ + int c; + + token->type = TOKEN_UNDEFINED; + token->keyword = KEYWORD_NONE; + vStringClear (token->string); + + getNextChar: + do + c = getcFromInputFile (); + while (c == ' ' || c == '\t' || c == '\f' || c == '\r' || c == '\n'); + + token->lineNumber = getInputLineNumber (); + token->filePosition = getInputFilePosition (); + + switch (c) + { + case EOF: + token->type = TOKEN_EOF; + break; + case '%': + do + c = getcFromInputFile (); + while (c != EOF && c != '\n'); + goto getNextChar; + case '/': + { + int c0 = getcFromInputFile (); + if (c0 == '*') + { + c0 = getcFromInputFile (); + if (prologAllowNestedComments) + skipNestedBlockComment (c0); + else + skipBlockComment (c0); + goto getNextChar; + } + ungetcToInputFile (c0); + tokenPutc (token, c); + token->type = c; + break; + } + case '\'': + { + readString (token, c); + token->type = TOKEN_STRATOM; + break; + } + case '"': + { + readString (token, c); + token->type = TOKEN_STRING; + break; + } + + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + case ',': + case '.': + tokenPutc(token, c); + token->type = c; + break; + case '=': + { + tokenPutc(token, c); + int c0 = getcFromInputFile (); + if (c0 == '.') + { + int c1 = getcFromInputFile (); + if (c1 == '.') + { + tokenCatS (token, ".."); + token->type = TOKEN_APPLY; + break; + } + ungetcToInputFile (c1); + } + ungetcToInputFile (c0); + token->type = c; + break; + } + case ':': + { + tokenPutc(token, c); + int c0 = getcFromInputFile (); + if (c0 == '-') + { + tokenPutc(token, c0); + token->type = TOKEN_RULEOP; + break; + } + ungetcToInputFile (c0); + token->type = c; + break; + } + case '-': + { + tokenPutc(token, c); + + int c0 = getcFromInputFile (); + if (c0 == '-') + { + int c1 = getcFromInputFile (); + if (c1 == '>') + { + tokenCatS (token, "->"); + token->type = TOKEN_DCGOP; + break; + } + ungetcToInputFile (c1); + } + ungetcToInputFile (c0); + token->type = c; + break; + } + default: + if (c == '0') + { + int c0 = getcFromInputFile (); + if (c0 == '\'') + { + tokenPutc(token, c); + c = getcFromInputFile (); + if (c != EOF) + tokenPutc(token, c); + + token->type = TOKEN_CODE; + break; + } + ungetcToInputFile (c0); + readNumber (token, c); + token->type = TOKEN_NUM; + return; + } + if (isdigit(c)) + { + readNumber (token, c); + token->type = TOKEN_NUM; + } + else if (c == '_' || ('A' <= c && c <= 'Z')) + { + readAtom (token, c); + token->type = TOKEN_VAR; + } + else if ('a' <= c && c <= 'z') + { + readAtom (token, c); + token->keyword = lookupKeyword (tokenString (token), Lang_prolog); + token->type = (token->keyword == KEYWORD_NONE) + ? TOKEN_ATOM + : TOKEN_KEYWORD; + } + else if (c == '-') + { + tokenPutc (token, c); + c = getcFromInputFile (); + if (isdigit (c)) + { + readNumber (token, c); + token->type = TOKEN_NUM; + } + else + { + /* I wonder what I should do here? */ + ungetcToInputFile (c); + token->type = TOKEN_ATOM; + } + } + else + { + tokenPutc (token, c); + if (c == '\\') + { + int c0 = getcFromInputFile (); + if (c0 != EOF) + tokenPutc (token, c0); + } + token->type = c; +#if 0 + tokenCatS (token, " REST :: "); + tokenCatS (token, getInputFileName ()); +#endif + } + break; + } +} + +static void makePrologTagEntry (tokenInfo *const atom, prologKind kindex, int arity, + unsigned long endLine, int module) +{ + tagEntryInfo e, ex; + char arity_str[16]; + + tokenInitTagEntry (atom, &e, kindex); + setTagEndLine (&e, endLine); + e.extensionFields.scopeIndex = module; + snprintf (arity_str, sizeof (arity_str), "%d", arity); + attachParserField (&e, PrologFields[F_ARITY].ftype, arity_str); + makeTagEntry (&e); + + tokenPutc (atom, '/'); + tokenCatS (atom, arity_str); + tokenInitTagEntry (atom, &ex, kindex); + setTagEndLine (&ex, endLine); + ex.extensionFields.scopeIndex = module; + attachParserField (&ex, PrologFields[F_ARITY].ftype, arity_str); + markTagExtraBit (&ex, PrologXtags[X_ARITY].xtype); + makeTagEntry (&ex); +} + +static int parseArguments (tokenInfo *const t) +{ + tokenRead (t); + + int arity = 0; + while (!tokenIsEOF (t) && tokenSkipToOneOfTypes (t, true, ',', '(', ')')) + { + if (t->type == '(') + tokenSkipOverPair (t); + else + { + arity++; + if (t->type == ')') + break; + } + tokenRead (t); + } + return arity; +} + +static void deleteBackToken (tokenInfo *t) +{ + if (!tokenIsEOF (t)) + tokenUnread (t); + tokenDelete (t); +} + +static int lookModuleAhead (void) +{ + int r = CORK_NIL; + tokenInfo *openparen = newPrologToken (); + + tokenRead (openparen); + if (openparen->type == '(') + { + tokenInfo *mod = newPrologToken (); + tokenRead (mod); + if (tokenIsType (mod, ATOM)) + r = tokenMakeSimpleTag (mod, K_MODULE); + deleteBackToken (mod); + } + deleteBackToken (openparen); + + return r; +} + +static int lookBodyAhead (void) +{ + int r = CORK_NIL; + + tokenInfo *modpred = newPrologToken (); + + tokenRead (modpred); + if (tokenIsKeyword (modpred, MODULE)) + r = lookModuleAhead (); + deleteBackToken (modpred); + + return r; +} + +static int parseClause (tokenInfo *const t, int module) +{ + tokenInfo *atom = NULL; + int arity = 0; + + if (tokenIsType (t, ATOM) + || tokenIsType (t, STRATOM) + || tokenIsType (t, KEYWORD)) + { + atom = newPrologToken (); + tokenCopy (atom, t); + + tokenRead (t); + if (tokenIsEOF (t)) + { + tokenDelete (atom); + return module; + } + if (t->type == ':') + { + int chainelt = makeSimpleRefTag (atom->string, K_MODULE, R_MODULE_CHAINELT); + tokenDelete (atom); + tokenRead (t); + parseClause (t, chainelt); + return module; + } + else + tokenUnread (t); + } + else if (tokenIsType (t, RULEOP)) + { + int newmod = lookBodyAhead (); + tokenSkipToOneOfTypes (t, true, '.'); + if (newmod != CORK_NIL) + module = newmod; + return module; + } + else + { + tokenSkipToOneOfTypes (t, true, '.'); + return module; + } + + tokenRead (t); + if (atom) + { + int kindex = K_PREDICATE; + + if (t->type == '(') + { + arity = parseArguments (t); + tokenRead (t); + } + + if (tokenIsType (t, RULEOP) + || tokenIsType (t, DCGOP)) + { + if (tokenIsType (t, DCGOP)) + kindex = K_GRAMMAR; + tokenSkipToOneOfTypes (t, true, '.'); + } + + if (t->type == '.') + makePrologTagEntry (atom, kindex, arity, t->lineNumber, + module); + + tokenDelete (atom); + } + + return module; +} + +static void findPrologTags (void) +{ + int module = CORK_NIL; + tokenInfo *t = newPrologToken (); + + while (1) + { + tokenRead (t); + if (tokenIsEOF (t)) + break; + module = parseClause (t, module); + } + + tokenDelete (t); +} + +extern void initialize (const langType language) +{ + Lang_prolog = language; +} + +extern parserDefinition* PrologParser (void) +{ + static const char *const extensions [] = {"pl", NULL}; + + /* Interpreters supporting shebang: + * + * + swipl + * https://www.swi-prolog.org/pldoc/man?section=plscript + * + gprolog + * http://www.gprolog.org/manual/html_node/gprolog007.html + * + yap + * https://github.com/search?q=repo%3Avscosta%2Fyap%20%20%22%23!%22&type=code + */ + static const char *const aliases [] = { + "swipl", + "gprolog", + "yap", + NULL + }; + + static selectLanguage selectors[] = { selectPerlOrPrologByDistinctiveToken, NULL }; + + parserDefinition* const def = parserNew ("Prolog"); + def->initialize = initialize; + def->parser = findPrologTags; + def->extensions = extensions; + def->aliases = aliases; + def->selectLanguage = selectors; + def->keywordTable = PrologKeywords; + def->keywordCount = ARRAY_SIZE(PrologKeywords); + def->useCork = CORK_QUEUE; + def->kindTable = PrologKinds; + def->kindCount = ARRAY_SIZE(PrologKinds); + def->fieldTable = PrologFields; + def->fieldCount = ARRAY_SIZE(PrologFields); + def->xtagTable = PrologXtags; + def->xtagCount = ARRAY_SIZE(PrologXtags); + def->paramTable = PrologParams; + def->paramCount = ARRAY_SIZE(PrologParams); + def->requestAutomaticFQTag = true; + def->defaultScopeSeparator = ":"; + + return def; +} diff --git a/source.mak b/source.mak index 521a2a37a7..3568f19341 100644 --- a/source.mak +++ b/source.mak @@ -399,6 +399,7 @@ PARSER_SRCS = \ parsers/perl-moose.c \ parsers/php.c \ parsers/powershell.c \ + parsers/prolog.c \ parsers/protobuf.c \ parsers/python.c \ parsers/python-entry-points.c \ diff --git a/win32/ctags_vs2013.vcxproj b/win32/ctags_vs2013.vcxproj index 088e606811..0082c1c2ed 100644 --- a/win32/ctags_vs2013.vcxproj +++ b/win32/ctags_vs2013.vcxproj @@ -347,6 +347,7 @@ + diff --git a/win32/ctags_vs2013.vcxproj.filters b/win32/ctags_vs2013.vcxproj.filters index ae70a81c10..2205e2d0bb 100644 --- a/win32/ctags_vs2013.vcxproj.filters +++ b/win32/ctags_vs2013.vcxproj.filters @@ -564,6 +564,9 @@ Source Files\parsers + + Source Files\parsers + Source Files\parsers From c99c2f4acfb40fbeb8d92da15eab6cf2953e6744 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Sun, 18 May 2025 17:44:54 +0900 Subject: [PATCH 6/6] validate-input: add swipl input validator Signed-off-by: Masatake YAMATO --- Units/parser-prolog.r/module.d/validator | 1 + .../simple-flat-comment.d/validator | 2 ++ Units/parser-prolog.r/validator | 1 + circle.yml | 2 +- misc/validators/validator-swipl | 34 +++++++++++++++++++ 5 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 Units/parser-prolog.r/module.d/validator create mode 100644 Units/parser-prolog.r/simple-flat-comment.d/validator create mode 100644 Units/parser-prolog.r/validator create mode 100755 misc/validators/validator-swipl diff --git a/Units/parser-prolog.r/module.d/validator b/Units/parser-prolog.r/module.d/validator new file mode 100644 index 0000000000..3b656016ee --- /dev/null +++ b/Units/parser-prolog.r/module.d/validator @@ -0,0 +1 @@ +KNOWN-INVALIDATION diff --git a/Units/parser-prolog.r/simple-flat-comment.d/validator b/Units/parser-prolog.r/simple-flat-comment.d/validator new file mode 100644 index 0000000000..67ee2f64c9 --- /dev/null +++ b/Units/parser-prolog.r/simple-flat-comment.d/validator @@ -0,0 +1,2 @@ +KNOWN-INVALIDATION + diff --git a/Units/parser-prolog.r/validator b/Units/parser-prolog.r/validator new file mode 100644 index 0000000000..8910b3134f --- /dev/null +++ b/Units/parser-prolog.r/validator @@ -0,0 +1 @@ +swipl diff --git a/circle.yml b/circle.yml index 78911df7f1..d73eee3ed8 100644 --- a/circle.yml +++ b/circle.yml @@ -24,7 +24,7 @@ jobs: dnf -y install awk gcc automake autoconf pkgconfig make libseccomp-devel libxml2-devel jansson-devel libyaml-devel pcre2-devel findutils diffutils sudo dnf -y install jq puppet python3-sphinx # These are for input-validation. - dnf -y install g++ jq puppet nodejs gcc-gfortran gcc-gnat typescript + dnf -y install g++ jq puppet nodejs gcc-gfortran gcc-gnat typescript swi-prolog # nodejs requires libsqlite.so.0 with sqlite-session feature # It was turned off in 3.46.1-1. dnf -y update sqlite-libs diff --git a/misc/validators/validator-swipl b/misc/validators/validator-swipl new file mode 100755 index 0000000000..998aeb927c --- /dev/null +++ b/misc/validators/validator-swipl @@ -0,0 +1,34 @@ +# -*- sh -*- +# validator-swipl - validating Prolog input files with swipl +# +# Copyright (c) 2025 Masatake YAMATO +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. +# +action=$1 +input="$2" +cmd=swipl +flags="--on-error=status -g halt." +case "$action" in + is_runnable) + type $cmd > /dev/null 2>&1 + exit $? + ;; + validate) + $cmd $flags "$input" > /dev/null + exit $? + ;; +esac