xref: /Universal-ctags/parsers/cxx/cxx.c (revision 11cf44dac568b33fb7b144993ae6239e0fe67a82)
1 /*
2 *   Copyright (c) 2016, Szymon Tomasz Stefanek
3 *
4 *   This source code is released for free distribution under the terms of the
5 *   GNU General Public License version 2 or (at your option) any later version.
6 *
7 *   This module contains functions for parsing and scanning C++ source files
8 */
9 
10 #include "general.h"
11 
12 #include "cxx_debug.h"
13 #include "cxx_keyword.h"
14 #include "cxx_token.h"
15 #include "cxx_token_chain.h"
16 #include "cxx_parser.h"
17 #include "cxx_scope.h"
18 #include "cxx_tag.h"
19 
20 #include "dependency.h"
21 #include "selectors.h"
22 
23 //
24 // ----------------------------------------------------------------------------
25 // Assumptions.
26 // ----------------------------------------------------------------------------
27 //
28 // - Parsing C/C++ is hard. Parsing C/C++ correctly without includes and
29 //   without a complete preprocessor is close to impossible in the general
30 //   case. Also ctags is not a compiler. This means that our parser must be
31 //   a "guessing" parser. It's hopeless to try to decode the syntax of the
32 //   language down to the last bit.
33 //
34 // - The input may contain syntax errors. This is because we don't have a full
35 //   preprocessor and also because ctags is often used "online" in editors,
36 //   while the user is typing. ctags should be tolerant and try to do its best
37 //   even with syntax errors but:
38 //   - Syntax errors that break the scope hierarchy should be detected and tag
39 //     emission should probably be stopped. Correct tags in a broken hierarchy
40 //     are useless (well, unless the hierarchy itself is ignored by the ctags
41 //     user).
42 //   - CTags should try to avoid emitting tags which involve syntax errors
43 //
44 // - There will always be pathologic cases. Don't cry, live with it.
45 //
46 // ----------------------------------------------------------------------------
47 // TODO LIST
48 // ----------------------------------------------------------------------------
49 //
50 // - In case of simple syntax error try to recover:
51 //       Skip to the next ; without entering or exiting scopes.
52 //       If this can be done then recovery is feasible.
53 // - Extension of each block/scope.
54 // - Unnamed blocks/scopes?
55 // - Handle syntax errors:
56 //   - If a special switch is used then stop on detecting a syntax error
57 //     (this is useful for code editors that frequently update tags for
58 //     single files)
59 //   - If the switch is not used then do NOT emit tags for a file on a syntax
60 //     error [but do not stop execution of the whole program and continue on
61 //     other files]
62 //   For this purpose:
63 //   - Do not emit tags until the end of the file, if scopes do not match we
64 //     either screwed up something or the programmer did
65 //     Maybe the cork api can be used for this?
66 //
67 // Handle variable declarations inside things like while() foreach() FOR() etc..
68 //
69 // - Friend classes.
70 // - Template parameters as field
71 // - Template specialisations (another field?)
72 // - Forward declarations might become tags
73 
74 
CParser(void)75 parserDefinition * CParser (void)
76 {
77 	static const char * const extensions [] =
78 	{
79 		"c",
80 		NULL
81 	};
82 
83 	static selectLanguage selectors[] = { selectByObjectiveCKeywords, NULL };
84 
85 	parserDefinition* def = parserNew("C");
86 
87 	def->kindTable = cxxTagGetCKindDefinitions();
88 	def->kindCount = cxxTagGetCKindDefinitionCount();
89 	def->fieldTable = cxxTagGetCFieldDefinitionifiers();
90 	def->fieldCount = cxxTagGetCFieldDefinitionifierCount();
91 	def->extensions = extensions;
92 	def->parser2 = cxxCParserMain;
93 	def->initialize = cxxCParserInitialize;
94 	def->finalize = cxxParserCleanup;
95 	def->selectLanguage = selectors;
96 	def->useCork = CORK_QUEUE|CORK_SYMTAB; // We use corking to block output until the end of file
97 
98 	return def;
99 }
100 
CppParser(void)101 parserDefinition * CppParser (void)
102 {
103 	static const char * const extensions [] =
104 	{
105 		"c++", "cc", "cp", "cpp", "cxx",
106 		"h", "h++", "hh", "hp", "hpp", "hxx", "inl",
107 #ifndef CASE_INSENSITIVE_FILENAMES
108 		"C", "H", "CPP", "CXX",
109 #endif
110 		NULL
111 	};
112 	static parserDependency dependencies [] = {
113 		{ DEPTYPE_KIND_OWNER, "C" },
114 	};
115 
116 	static selectLanguage selectors[] = { selectByObjectiveCKeywords, NULL };
117 
118 	parserDefinition* def = parserNew("C++");
119 
120 	def->dependencies = dependencies;
121 	def->dependencyCount = ARRAY_SIZE (dependencies);
122 	def->kindTable = cxxTagGetCPPKindDefinitions();
123 	def->kindCount = cxxTagGetCPPKindDefinitionCount();
124 	def->fieldTable = cxxTagGetCPPFieldDefinitionifiers();
125 	def->fieldCount = cxxTagGetCPPFieldDefinitionifierCount();
126 	def->extensions = extensions;
127 	def->parser2 = cxxCppParserMain;
128 	def->initialize = cxxCppParserInitialize;
129 	def->finalize = cxxParserCleanup;
130 	def->selectLanguage = selectors;
131 	def->useCork = CORK_QUEUE|CORK_SYMTAB; // We use corking to block output until the end of file
132 
133 	return def;
134 }
135 
CUDAParser(void)136 parserDefinition * CUDAParser (void)
137 {
138 	static const char * const extensions [] =
139 	{
140 		"cu", "cuh",
141 		NULL
142 	};
143 	static parserDependency dependencies [] = {
144 		{ DEPTYPE_KIND_OWNER, "C" },
145 	};
146 
147 	parserDefinition* def = parserNew("CUDA");
148 
149 	def->dependencies = dependencies;
150 	def->dependencyCount = ARRAY_SIZE (dependencies);
151 	def->kindTable = cxxTagGetCUDAKindDefinitions();
152 	def->kindCount = cxxTagGetCUDAKindDefinitionCount();
153 	def->fieldTable = cxxTagGetCUDAFieldDefinitionifiers();
154 	def->fieldCount = cxxTagGetCUDAFieldDefinitionifierCount();
155 	def->extensions = extensions;
156 	def->parser2 = cxxCUDAParserMain;
157 	def->initialize = cxxCUDAParserInitialize;
158 	def->finalize = cxxParserCleanup;
159 	def->selectLanguage = NULL;
160 	def->useCork = CORK_QUEUE|CORK_SYMTAB; // We use corking to block output until the end of file
161 
162 	return def;
163 }
164