From 806f296ceb780fff3d0820606334651ce33d6471 Mon Sep 17 00:00:00 2001 From: Hadriel Kaplan Date: Thu, 9 Aug 2018 19:34:14 -0400 Subject: [PATCH] CMake: new parser As mentioned in issue #1816, this is a CMake file parser using the optlib multitable regex feature. --- .../cmake-comments.d/expected.tags | 3 + .../cmake-comments.d/input.cmake | 17 ++ .../cmake-function.d/expected.tags | 5 + .../cmake-function.d/input.cmake | 19 ++ .../cmake-macro.d/expected.tags | 5 + .../parser-cmake.r/cmake-macro.d/input.cmake | 19 ++ .../cmake-option.d/expected.tags | 5 + .../parser-cmake.r/cmake-option.d/input.cmake | 15 ++ .../cmake-project.d/expected.tags | 5 + .../cmake-project.d/input.cmake | 15 ++ .../cmake-simple.d/expected.tags | 6 + .../parser-cmake.r/cmake-simple.d/input.cmake | 34 +++ .../cmake-target.d/expected.tags | 15 ++ .../parser-cmake.r/cmake-target.d/input.cmake | 49 +++++ .../cmake-variable.d/expected.tags | 5 + .../cmake-variable.d/input.cmake | 13 ++ docs/news.rst | 1 + main/parsers.h | 1 + makefiles/translator_input.mak | 5 +- optlib/cmake.c | 203 ++++++++++++++++++ optlib/cmake.ctags | 167 ++++++++++++++ win32/ctags_vs2013.vcxproj | 1 + win32/ctags_vs2013.vcxproj.filters | 3 + 23 files changed, 609 insertions(+), 2 deletions(-) create mode 100644 Units/parser-cmake.r/cmake-comments.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-comments.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-function.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-function.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-macro.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-macro.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-option.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-option.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-project.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-project.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-simple.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-simple.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-target.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-target.d/input.cmake create mode 100644 Units/parser-cmake.r/cmake-variable.d/expected.tags create mode 100644 Units/parser-cmake.r/cmake-variable.d/input.cmake create mode 100644 optlib/cmake.c create mode 100644 optlib/cmake.ctags diff --git a/Units/parser-cmake.r/cmake-comments.d/expected.tags b/Units/parser-cmake.r/cmake-comments.d/expected.tags new file mode 100644 index 0000000000..98726ff297 --- /dev/null +++ b/Units/parser-cmake.r/cmake-comments.d/expected.tags @@ -0,0 +1,3 @@ +another_good_target input.cmake /^add_library(another_good_target# <-- target$/;" t +good_target input.cmake /^ good_target# this is legal comment placement set(NO_TAG foo)$/;" t +tag_this input.cmake /^]]set(tag_this)$/;" v diff --git a/Units/parser-cmake.r/cmake-comments.d/input.cmake b/Units/parser-cmake.r/cmake-comments.d/input.cmake new file mode 100644 index 0000000000..e10a1642c1 --- /dev/null +++ b/Units/parser-cmake.r/cmake-comments.d/input.cmake @@ -0,0 +1,17 @@ +# this is a test of comments set(DO_NOT_TAG "foo") + +#[[ +multi-linecomments +option(DO_NOT_TAG "foo" OFF) +] not the end +]]set(tag_this) + +add_custom_target(# comment set(NO_TAG "foo") + # anothe rline comment + good_target# this is legal comment placement set(NO_TAG foo) + ALL) + +add_library(another_good_target# <-- target + SHARED # set(NO_TAG bar) + gmock-all.cc + ) diff --git a/Units/parser-cmake.r/cmake-function.d/expected.tags b/Units/parser-cmake.r/cmake-function.d/expected.tags new file mode 100644 index 0000000000..2fc7474cab --- /dev/null +++ b/Units/parser-cmake.r/cmake-function.d/expected.tags @@ -0,0 +1,5 @@ +Bfunctiontag_this_2 input.cmake /^ function( Bfunctiontag_this_2 ${BAR})$/;" f +cxx_shared_library input.cmake /^function(cxx_shared_library name cxx_flags)$/;" f +d_ALSO_Tag_this input.cmake /^ d_ALSO_Tag_this$/;" f +eLastlyTagThis_ input.cmake /^eLastlyTagThis_ "hello")$/;" f +tag_this1 input.cmake /^function(tag_this1)$/;" f diff --git a/Units/parser-cmake.r/cmake-function.d/input.cmake b/Units/parser-cmake.r/cmake-function.d/input.cmake new file mode 100644 index 0000000000..902d0602b5 --- /dev/null +++ b/Units/parser-cmake.r/cmake-function.d/input.cmake @@ -0,0 +1,19 @@ +function(tag_this1) +endfunction(tag_this1) + function( Bfunctiontag_this_2 ${BAR}) + +function(cxx_shared_library name cxx_flags) + cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN}) +endfunction() + + FUNCTION ( + d_ALSO_Tag_this + true) + +Function( +eLastlyTagThis_ "hello") + +function(${not_this} foo) +function(not-this foo) +function(not.this foo) +function(1notthis foo) diff --git a/Units/parser-cmake.r/cmake-macro.d/expected.tags b/Units/parser-cmake.r/cmake-macro.d/expected.tags new file mode 100644 index 0000000000..36f38b98d8 --- /dev/null +++ b/Units/parser-cmake.r/cmake-macro.d/expected.tags @@ -0,0 +1,5 @@ +Bmacrotag_this_2 input.cmake /^ macro( Bmacrotag_this_2 ${BAR})$/;" m +cxx_shared_library input.cmake /^macro(cxx_shared_library name cxx_flags)$/;" m +d_ALSO_Tag_this input.cmake /^ d_ALSO_Tag_this$/;" m +eLastlyTagThis_ input.cmake /^eLastlyTagThis_ "hello")$/;" m +tag_this1 input.cmake /^macro(tag_this1)$/;" m diff --git a/Units/parser-cmake.r/cmake-macro.d/input.cmake b/Units/parser-cmake.r/cmake-macro.d/input.cmake new file mode 100644 index 0000000000..692b985d19 --- /dev/null +++ b/Units/parser-cmake.r/cmake-macro.d/input.cmake @@ -0,0 +1,19 @@ +macro(tag_this1) +endmacro(tag_this1) + macro( Bmacrotag_this_2 ${BAR}) + +macro(cxx_shared_library name cxx_flags) + cxx_library_with_type(${name} SHARED "${cxx_flags}" ${ARGN}) +endmacro() + + MACRO ( + d_ALSO_Tag_this + true) + +Macro( +eLastlyTagThis_ "hello") + +macro(${not_this} foo) +macro(not-this foo) +macro(not.this foo) +macro(1not_this foo) diff --git a/Units/parser-cmake.r/cmake-option.d/expected.tags b/Units/parser-cmake.r/cmake-option.d/expected.tags new file mode 100644 index 0000000000..12c8d643b9 --- /dev/null +++ b/Units/parser-cmake.r/cmake-option.d/expected.tags @@ -0,0 +1,5 @@ +1_tag_this input.cmake /^option(1_tag_this foo)$/;" D +B-option-tag_this_2 input.cmake /^option(B-option-tag_this_2 ${BAR})$/;" D +c_TAG_THIS input.cmake /^ option ( c_TAG_THIS but_not_this)$/;" D +d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" D +e.LastlyTagThis input.cmake /^e.LastlyTagThis "hello")$/;" D diff --git a/Units/parser-cmake.r/cmake-option.d/input.cmake b/Units/parser-cmake.r/cmake-option.d/input.cmake new file mode 100644 index 0000000000..c7f2fa9b8b --- /dev/null +++ b/Units/parser-cmake.r/cmake-option.d/input.cmake @@ -0,0 +1,15 @@ +option(1_tag_this foo) +option(B-option-tag_this_2 ${BAR}) + + option ( c_TAG_THIS but_not_this) + + OPTION ( + d-ALSO-Tag.this + true) + +Option( +e.LastlyTagThis "hello") + +option(${not_this} foo) +option(${ not_this } foo) +option(not~this foo) diff --git a/Units/parser-cmake.r/cmake-project.d/expected.tags b/Units/parser-cmake.r/cmake-project.d/expected.tags new file mode 100644 index 0000000000..2f696efce4 --- /dev/null +++ b/Units/parser-cmake.r/cmake-project.d/expected.tags @@ -0,0 +1,5 @@ +1_tag_this input.cmake /^project(1_tag_this)$/;" p +B-project-tag_this_2 input.cmake /^project(B-project-tag_this_2 ${BAR})$/;" p +c_TAG_THIS input.cmake /^ project ( c_TAG_THIS but_not_this)$/;" p +d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" p +e.LastlyTagThis input.cmake /^e.LastlyTagThis "hello")$/;" p diff --git a/Units/parser-cmake.r/cmake-project.d/input.cmake b/Units/parser-cmake.r/cmake-project.d/input.cmake new file mode 100644 index 0000000000..88407ff688 --- /dev/null +++ b/Units/parser-cmake.r/cmake-project.d/input.cmake @@ -0,0 +1,15 @@ +project(1_tag_this) +project(B-project-tag_this_2 ${BAR}) + + project ( c_TAG_THIS but_not_this) + + PROJECT ( + d-ALSO-Tag.this + ) + +Project( +e.LastlyTagThis "hello") + +project(${not_this}) +project(${ not_this }) +project(not/this) diff --git a/Units/parser-cmake.r/cmake-simple.d/expected.tags b/Units/parser-cmake.r/cmake-simple.d/expected.tags new file mode 100644 index 0000000000..a463ac6f14 --- /dev/null +++ b/Units/parser-cmake.r/cmake-simple.d/expected.tags @@ -0,0 +1,6 @@ +BUILD_GMOCK input.cmake /^option(BUILD_GMOCK "Builds the googlemock subproject" ON)$/;" D +BUILD_GTEST input.cmake /^option(BUILD_GTEST "Builds the googletest subproject" OFF)$/;" D +CMAKE_INSTALL_BINDIR input.cmake /^ set(CMAKE_INSTALL_BINDIR "bin" CACHE STRING "User executables (bin)")$/;" v +CMAKE_INSTALL_INCLUDEDIR input.cmake /^ set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "C header files (include)")$/;" v +CMAKE_INSTALL_LIBDIR input.cmake /^ set(CMAKE_INSTALL_LIBDIR "lib${LIB_SUFFIX}" CACHE STRING "Object code libraries (lib)")$/;" v +googletest-distribution input.cmake /^project( googletest-distribution )$/;" p diff --git a/Units/parser-cmake.r/cmake-simple.d/input.cmake b/Units/parser-cmake.r/cmake-simple.d/input.cmake new file mode 100644 index 0000000000..5e231141dd --- /dev/null +++ b/Units/parser-cmake.r/cmake-simple.d/input.cmake @@ -0,0 +1,34 @@ +# taken from https://github.com/google/googletest/blob/master/CMakeLists.txt +cmake_minimum_required(VERSION 2.6.4) + +if (POLICY CMP0048) + cmake_policy(SET CMP0048 NEW) +endif (POLICY CMP0048) + +project( googletest-distribution ) + +enable_testing() + +include(CMakeDependentOption) +if (CMAKE_VERSION VERSION_LESS 2.8.5) + set(CMAKE_INSTALL_BINDIR "bin" CACHE STRING "User executables (bin)") + set(CMAKE_INSTALL_LIBDIR "lib${LIB_SUFFIX}" CACHE STRING "Object code libraries (lib)") + set(CMAKE_INSTALL_INCLUDEDIR "include" CACHE STRING "C header files (include)") + mark_as_advanced(CMAKE_INSTALL_BINDIR CMAKE_INSTALL_LIBDIR CMAKE_INSTALL_INCLUDEDIR) +else() + include(GNUInstallDirs) +endif() + +option(BUILD_GTEST "Builds the googletest subproject" OFF) + +#Note that googlemock target already builds googletest +option(BUILD_GMOCK "Builds the googlemock subproject" ON) + +cmake_dependent_option(INSTALL_GTEST "Enable installation of googletest. (Projects embedding googletest may want to turn this OFF.)" ON "BUILD_GTEST OR BUILD_GMOCK" OFF) +cmake_dependent_option(INSTALL_GMOCK "Enable installation of googlemock. (Projects embedding googlemock may want to turn this OFF.)" ON "BUILD_GMOCK" OFF) + +if(BUILD_GMOCK) + add_subdirectory( googlemock ) +elseif(BUILD_GTEST) + add_subdirectory( googletest ) +endif() diff --git a/Units/parser-cmake.r/cmake-target.d/expected.tags b/Units/parser-cmake.r/cmake-target.d/expected.tags new file mode 100644 index 0000000000..5e58d31811 --- /dev/null +++ b/Units/parser-cmake.r/cmake-target.d/expected.tags @@ -0,0 +1,15 @@ +1_tag_this input.cmake /^add_custom_target(1_tag_this)$/;" t +1_tag_this input.cmake /^add_executable(1_tag_this)$/;" t +1_tag_this input.cmake /^add_library(1_tag_this)$/;" t +B-add_custom_target-tag_this_2 input.cmake /^add_custom_target(B-add_custom_target-tag_this_2 ${BAR})$/;" t +B-add_executable-tag_this_2 input.cmake /^add_executable(B-add_executable-tag_this_2 ${BAR})$/;" t +B-add_library-tag_this_2 input.cmake /^add_library(B-add_library-tag_this_2 ${BAR})$/;" t +c_TAG_THIS input.cmake /^ add_custom_target ( c_TAG_THIS but_not_this)$/;" t +c_TAG_THIS input.cmake /^ add_executable ( c_TAG_THIS but_not_this)$/;" t +c_TAG_THIS input.cmake /^ add_library ( c_TAG_THIS but_not_this)$/;" t +d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" t +d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this $/;" t +d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" t +e.LastlyTagThis input.cmake /^e.LastlyTagThis "CustomTarget")$/;" t +e.LastlyTagThis input.cmake /^e.LastlyTagThis "Executable")$/;" t +e.LastlyTagThis input.cmake /^e.LastlyTagThis "Library")$/;" t diff --git a/Units/parser-cmake.r/cmake-target.d/input.cmake b/Units/parser-cmake.r/cmake-target.d/input.cmake new file mode 100644 index 0000000000..32e27e326d --- /dev/null +++ b/Units/parser-cmake.r/cmake-target.d/input.cmake @@ -0,0 +1,49 @@ +add_custom_target(1_tag_this) +add_custom_target(B-add_custom_target-tag_this_2 ${BAR}) + + add_custom_target ( c_TAG_THIS but_not_this) + + ADD_CUSTOM_TARGET ( + d-ALSO-Tag.this + ) + +Add_Custom_target( +e.LastlyTagThis "CustomTarget") + +add_custom_target(${not_this}) +add_custom_target(${ not_this }) +add_custom_target(not/this) + + +add_executable(1_tag_this) +add_executable(B-add_executable-tag_this_2 ${BAR}) + + add_executable ( c_TAG_THIS but_not_this) + + ADD_EXECUTABLE ( + d-ALSO-Tag.this + ) + +Add_Executable( +e.LastlyTagThis "Executable") + +add_executable(${not_this}) +add_executable(${ not_this }) +add_executable(not/this) + + +add_library(1_tag_this) +add_library(B-add_library-tag_this_2 ${BAR}) + + add_library ( c_TAG_THIS but_not_this) + + ADD_LIBRARY ( + d-ALSO-Tag.this + ) + +Add_Library( +e.LastlyTagThis "Library") + +add_library(${not_this}) +add_library(${ not_this }) +add_library(not/this) diff --git a/Units/parser-cmake.r/cmake-variable.d/expected.tags b/Units/parser-cmake.r/cmake-variable.d/expected.tags new file mode 100644 index 0000000000..ed82fa930c --- /dev/null +++ b/Units/parser-cmake.r/cmake-variable.d/expected.tags @@ -0,0 +1,5 @@ +1_tag_this input.cmake /^set(1_tag_this foo)$/;" v +B-set-tag_this_2 input.cmake /^set(B-set-tag_this_2 ${BAR})$/;" v +c_TAG_THIS input.cmake /^ set ( c_TAG_THIS but_not_this)$/;" v +d-ALSO-Tag.this input.cmake /^ d-ALSO-Tag.this$/;" v +e.LastlyTagThis input.cmake /^e.LastlyTagThis "hello")$/;" v diff --git a/Units/parser-cmake.r/cmake-variable.d/input.cmake b/Units/parser-cmake.r/cmake-variable.d/input.cmake new file mode 100644 index 0000000000..950566187a --- /dev/null +++ b/Units/parser-cmake.r/cmake-variable.d/input.cmake @@ -0,0 +1,13 @@ +set(1_tag_this foo) +set(B-set-tag_this_2 ${BAR}) + + set ( c_TAG_THIS but_not_this) + + SET ( + d-ALSO-Tag.this + true) + +Set( +e.LastlyTagThis "hello") + +set(${not_this} foo) diff --git a/docs/news.rst b/docs/news.rst index 91a8f493a4..ef770a2c75 100644 --- a/docs/news.rst +++ b/docs/news.rst @@ -42,6 +42,7 @@ The following parsers have been added: * Automake * AutoIt * Clojure +* CMake *optlib* * CSS * Ctags option library *optlib* * CUDA diff --git a/main/parsers.h b/main/parsers.h index 4fc8ffbcea..49664eca54 100644 --- a/main/parsers.h +++ b/main/parsers.h @@ -47,6 +47,7 @@ BasicParser, \ BetaParser, \ ClojureParser, \ + CMakeParser, \ CParser, \ CppParser, \ CPreProParser, \ diff --git a/makefiles/translator_input.mak b/makefiles/translator_input.mak index 757f989222..3ca00217ca 100644 --- a/makefiles/translator_input.mak +++ b/makefiles/translator_input.mak @@ -1,8 +1,9 @@ # -*- makefile -*- TRANSLATOR_INPUT = \ - optlib/RSpec.ctags \ + optlib/RSpec.ctags \ + optlib/cmake.ctags \ optlib/ctags-optlib.ctags \ - optlib/elm.ctags \ + optlib/elm.ctags \ optlib/gdbinit.ctags \ optlib/man.ctags \ optlib/markdown.ctags \ diff --git a/optlib/cmake.c b/optlib/cmake.c new file mode 100644 index 0000000000..b6b553dfee --- /dev/null +++ b/optlib/cmake.c @@ -0,0 +1,203 @@ +/* + * Generated by ./misc/optlib2c from optlib/cmake.ctags, Don't edit this manually. + */ +#include "general.h" +#include "parse.h" +#include "routines.h" + + +static void initializeCMakeParser (const langType language CTAGS_ATTR_UNUSED) +{ + + addLanguageRegexTable (language, "main"); + addLanguageRegexTable (language, "variable"); + addLanguageRegexTable (language, "function"); + addLanguageRegexTable (language, "macro"); + addLanguageRegexTable (language, "target"); + addLanguageRegexTable (language, "option"); + addLanguageRegexTable (language, "project"); + addLanguageRegexTable (language, "commentBegin"); + addLanguageRegexTable (language, "commentMultiline"); + addLanguageRegexTable (language, "skipComment"); + addLanguageRegexTable (language, "skipWhiteSpace"); + addLanguageRegexTable (language, "skipToName"); + addLanguageRegexTable (language, "nextToken"); + + addLanguageTagMultiTableRegex (language, "main", + "^[^sSfFmMaAoOpP# \t\n][^ #\t\n]*[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^set[ \t]*\\(", + "", "", "{icase}{tenter=variable}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^function[ \t]*\\(", + "", "", "{icase}{tenter=function}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^macro[ \t]*\\(", + "", "", "{icase}{tenter=macro}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^add_(custom_target|executable|library)[ \t]*\\(", + "", "", "{icase}{tenter=target}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^option[ \t]*\\(", + "", "", "{icase}{tenter=option}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^project[ \t]*\\(", + "", "", "{icase}{tenter=project}", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^[^ \t\n]+[ \t\n]*", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "main", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "variable", + "^([A-Za-z0-9_.-]+)[ \t\n\\)]+", + "\\1", "v", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "variable", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "variable", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "variable", + "^([A-Za-z0-9_.-]+)(#)", + "\\1", "v", "{tleave}{_advanceTo=2start}", NULL); + addLanguageTagMultiTableRegex (language, "function", + "^([A-Za-z_][A-Za-z0-9_]*)[ \t\n\\)]+", + "\\1", "f", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "function", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "function", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "function", + "^([A-Za-z_][A-Za-z0-9_]*)(#)", + "\\1", "f", "{tleave}{_advanceTo=2start}", NULL); + addLanguageTagMultiTableRegex (language, "macro", + "^([A-Za-z_][A-Za-z0-9_]*)[ \t\n\\)]+", + "\\1", "m", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "macro", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "macro", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "macro", + "^([A-Za-z_][A-Za-z0-9_]*)(#)", + "\\1", "m", "{tleave}{_advanceTo=2start}", NULL); + addLanguageTagMultiTableRegex (language, "target", + "^([A-Za-z0-9_.-]+)[ \t\n\\)]+", + "\\1", "t", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "target", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "target", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "target", + "^([A-Za-z0-9_.-]+)(#)", + "\\1", "t", "{tleave}{_advanceTo=2start}", NULL); + addLanguageTagMultiTableRegex (language, "option", + "^([A-Za-z0-9_.-]+)[ \t\n\\)]+", + "\\1", "D", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "option", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "option", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "option", + "^([A-Za-z0-9_.-]+)(#)", + "\\1", "D", "{tleave}{_advanceTo=2start}", NULL); + addLanguageTagMultiTableRegex (language, "project", + "^([A-Za-z0-9_.-]+)([# \t\n\\)])", + "\\1", "p", "{tleave}{_advanceTo=2start}", NULL); + addLanguageTagMultiTableRegex (language, "project", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "project", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "commentBegin", + "^\\[\\[", + "", "", "{tjump=commentMultiline}", NULL); + addLanguageTagMultiTableRegex (language, "commentBegin", + "^[^\n]*[ \t\n]*", + "", "", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "commentMultiline", + "^\\]\\][ \t\n]*", + "", "", "{tleave}", NULL); + addLanguageTagMultiTableRegex (language, "commentMultiline", + "^.[^]]*", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "skipComment", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "skipWhiteSpace", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "skipToName", + "^[ \t\n]+", + "", "", "", NULL); + addLanguageTagMultiTableRegex (language, "skipToName", + "^#", + "", "", "{tenter=commentBegin}", NULL); + addLanguageTagMultiTableRegex (language, "nextToken", + "^[^ \t\n]+[ \t\n]*", + "", "", "", NULL); +} + +extern parserDefinition* CMakeParser (void) +{ + static const char *const extensions [] = { + "cmake", + NULL + }; + + static const char *const aliases [] = { + NULL + }; + + static const char *const patterns [] = { + "CMakeLists.txt", + NULL + }; + + static kindDefinition CMakeKindTable [] = { + { + true, 'f', "function", "functions", + }, + { + true, 'm', "macro", "macros", + }, + { + true, 't', "target", "targets", + }, + { + true, 'v', "variable", "variable definitions", + }, + { + true, 'D', "option", "options specified with -D", + }, + { + true, 'p', "project", "projects", + }, + }; + + parserDefinition* const def = parserNew ("CMake"); + + def->enabled = true; + def->extensions = extensions; + def->patterns = patterns; + def->aliases = aliases; + def->method = METHOD_NOT_CRAFTED|METHOD_REGEX; + def->kindTable = CMakeKindTable; + def->kindCount = ARRAY_SIZE(CMakeKindTable); + def->initialize = initializeCMakeParser; + + return def; +} diff --git a/optlib/cmake.ctags b/optlib/cmake.ctags new file mode 100644 index 0000000000..7d7414cc95 --- /dev/null +++ b/optlib/cmake.ctags @@ -0,0 +1,167 @@ +# +# cmake.ctags --- multitable regex parser for CMake's files +# +# Copyright (c) 2018, 128 Technology, Inc. +# +# Author: Hadriel Kaplan (hadrielk@yahoo.com) +# +# 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. +# +# +# Overview: +# +# This universal-ctags optlib option file defines the parser for tagging +# CMake files. It supports tagging the following: +# +# - cmake function and macro names +# - build target, executable, and library target names +# - cmake variables and options +# - cmake project names +# +# Caveats: +# +# Names that are ${} references to variables are not tagged. +# +# For example, given the following: +# +# set(PROJECT_NAME_STR ${PROJECT_NAME}) +# add_executable( ${PROJECT_NAME_STR} ... ) +# add_custom_target( ${PROJECT_NAME_STR}_tests ... ) +# add_library( sharedlib ... ) +# +# the variable 'PROJECT_NAME_STR' and target 'sharedlib' will both be tagged, +# but the other targets will not be. +# +# +# References: +# +# - https://cmake.org/cmake/help/latest/manual/cmake-language.7.html +# + +--langdef=CMake +--map-CMake=+.cmake +--map-CMake=+(CMakeLists.txt) + +# +# Kinds +# +--kinddef-CMake=f,function,functions +--kinddef-CMake=m,macro,macros +--kinddef-CMake=t,target,targets +--kinddef-CMake=v,variable,variable definitions +--kinddef-CMake=D,option,options specified with -D +--kinddef-CMake=p,project,projects + +# +# Tables +# +--_tabledef-CMake=main +--_tabledef-CMake=variable +--_tabledef-CMake=function +--_tabledef-CMake=macro +--_tabledef-CMake=target +--_tabledef-CMake=option +--_tabledef-CMake=project + +# +# comment +# +--_tabledef-CMake=commentBegin +--_tabledef-CMake=commentMultiline + +--_mtable-regex-CMake=commentBegin/\[\[//{tjump=commentMultiline} +--_mtable-regex-CMake=commentBegin/[^\n]*[ \t\n]*//{tleave} + +--_mtable-regex-CMake=commentMultiline/\]\][ \t\n]*//{tleave} +--_mtable-regex-CMake=commentMultiline/.[^]]*// + +--_tabledef-CMake=skipComment +--_mtable-regex-CMake=skipComment/#//{tenter=commentBegin} + +# +# Utilities +# +--_tabledef-CMake=skipWhiteSpace +--_tabledef-CMake=skipToName +--_tabledef-CMake=nextToken + +--_mtable-regex-CMake=skipWhiteSpace/[ \t\n]+// + +--_mtable-extend-CMake=skipToName+skipWhiteSpace +--_mtable-extend-CMake=skipToName+skipComment + +--_mtable-regex-CMake=nextToken/[^ \t\n]+[ \t\n]*// + +# +# main +# +# This first regex entry may seem odd - it's purely for improving performance, by +# matching tokens with leading characters that could not possibly match a later regex, +# and just skipping the whole token (and trailing whitespace). This one regex line +# improved performance by an order of magnitude. +--_mtable-regex-CMake=main/[^sSfFmMaAoOpP# \t\n][^ #\t\n]*[ \t\n]+// +--_mtable-extend-CMake=main+skipComment +--_mtable-regex-CMake=main/set[ \t]*\(//{icase}{tenter=variable} +--_mtable-regex-CMake=main/function[ \t]*\(//{icase}{tenter=function} +--_mtable-regex-CMake=main/macro[ \t]*\(//{icase}{tenter=macro} +--_mtable-regex-CMake=main/add_(custom_target|executable|library)[ \t]*\(//{icase}{tenter=target} +--_mtable-regex-CMake=main/option[ \t]*\(//{icase}{tenter=option} +--_mtable-regex-CMake=main/project[ \t]*\(//{icase}{tenter=project} +--_mtable-extend-CMake=main+nextToken +--_mtable-extend-CMake=main+skipWhiteSpace + + +# +# Each of the following basically work the same way, and only differ in the +# exact pattern allowed to be their name, and the Kind they add. Note that they +# capture a required trailing '[ \t\n\)]' or '#', to verify the full name token +# matched the name's pattern, but then we advanceTo=2start for the next round, +# so that we don't go past a potential '#' comment token but instead match it +# again in the main table as a comment. The odds of a comment '#' immediately +# following the name is very low, so we split it into its own check and do it +# last in each table - this improves real-world performance ~10%, because in +# the common case we can capture the whitespace at the same time as the name, +# and not have to skip it again in the 'main' table. +# + +# +# variable +# +--_mtable-regex-CMake=variable/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/v/{tleave} +--_mtable-extend-CMake=variable+skipToName +--_mtable-regex-CMake=variable/([A-Za-z0-9_.-]+)(#)/\1/v/{tleave}{_advanceTo=2start} + +# +# function +# +--_mtable-regex-CMake=function/([A-Za-z_][A-Za-z0-9_]*)[ \t\n\)]+/\1/f/{tleave} +--_mtable-extend-CMake=function+skipToName +--_mtable-regex-CMake=function/([A-Za-z_][A-Za-z0-9_]*)(#)/\1/f/{tleave}{_advanceTo=2start} + +# +# macro +# +--_mtable-regex-CMake=macro/([A-Za-z_][A-Za-z0-9_]*)[ \t\n\)]+/\1/m/{tleave} +--_mtable-extend-CMake=macro+skipToName +--_mtable-regex-CMake=macro/([A-Za-z_][A-Za-z0-9_]*)(#)/\1/m/{tleave}{_advanceTo=2start} + +# +# target +# +--_mtable-regex-CMake=target/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/t/{tleave} +--_mtable-extend-CMake=target+skipToName +--_mtable-regex-CMake=target/([A-Za-z0-9_.-]+)(#)/\1/t/{tleave}{_advanceTo=2start} + +# +# option +# +--_mtable-regex-CMake=option/([A-Za-z0-9_.-]+)[ \t\n\)]+/\1/D/{tleave} +--_mtable-extend-CMake=option+skipToName +--_mtable-regex-CMake=option/([A-Za-z0-9_.-]+)(#)/\1/D/{tleave}{_advanceTo=2start} + +# +# project +# +--_mtable-regex-CMake=project/([A-Za-z0-9_.-]+)([# \t\n\)])/\1/p/{tleave}{_advanceTo=2start} +--_mtable-extend-CMake=project+skipToName diff --git a/win32/ctags_vs2013.vcxproj b/win32/ctags_vs2013.vcxproj index c026e88bac..4508ae70cf 100644 --- a/win32/ctags_vs2013.vcxproj +++ b/win32/ctags_vs2013.vcxproj @@ -140,6 +140,7 @@ + diff --git a/win32/ctags_vs2013.vcxproj.filters b/win32/ctags_vs2013.vcxproj.filters index 5ef4986123..91e25a3b58 100644 --- a/win32/ctags_vs2013.vcxproj.filters +++ b/win32/ctags_vs2013.vcxproj.filters @@ -174,6 +174,9 @@ Source Files\optlib + + Source Files\optlib + Source Files\optlib