-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathmode.cpp
143 lines (120 loc) · 3.85 KB
/
mode.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*******************************************************************\
Module:
Author: Daniel Kroening, [email protected]
\*******************************************************************/
#include "mode.h"
#include <list>
#include <memory>
#include <set>
#ifdef _WIN32
#include <cstring>
#endif
#include "language.h"
#include <util/invariant.h>
#include <util/namespace.h>
#include <util/symbol.h>
struct language_entryt
{
language_factoryt factory;
std::set<std::string> extensions;
irep_idt mode;
};
typedef std::list<language_entryt> languagest;
languagest languages;
/// Register a language
/// Note: registering a language is required for using the functions
/// in language_util.h
/// \param factory: a language factory, e.g. `new_ansi_c_language`
void register_language(language_factoryt factory)
{
languages.push_back(language_entryt());
std::unique_ptr<languaget> l(factory());
languages.back().factory=factory;
languages.back().extensions=l->extensions();
languages.back().mode=l->id();
}
/// Get the language corresponding to the given mode
/// \param mode: the mode, e.g. `ID_C`
/// \return the language or `nullptr` if the language has not been registered
std::unique_ptr<languaget> get_language_from_mode(const irep_idt &mode)
{
for(const auto &language : languages)
if(mode == language.mode)
return language.factory();
return nullptr;
}
/// Get the mode of the given identifier's symbol
/// \param ns: a namespace
/// \param identifier: an identifier
/// \return the mode, e.g. `ID_C`, if the identifier is in the given
/// symbol table, or `ID_unknown` otherwise
const irep_idt &
get_mode_from_identifier(const namespacet &ns, const irep_idt &identifier)
{
if(identifier.empty())
return ID_unknown;
const symbolt *symbol;
if(ns.lookup(identifier, symbol))
return ID_unknown;
return symbol->mode;
}
/// Get the language corresponding to the mode of the given identifier's symbol
/// \param ns: a namespace
/// \param identifier: an identifier
/// \return the corresponding language if the mode is not `ID_unknown`, or
/// the default language otherwise;
/// Note: It is assumed as an invariant that languages of symbols in the symbol
/// table have been registered.
std::unique_ptr<languaget>
get_language_from_identifier(const namespacet &ns, const irep_idt &identifier)
{
const irep_idt &mode = get_mode_from_identifier(ns, identifier);
if(mode == ID_unknown)
return get_default_language();
std::unique_ptr<languaget> language = get_language_from_mode(mode);
INVARIANT(
language,
"symbol '" + id2string(identifier) + "' has unknown mode '" +
id2string(mode) + "'");
return language;
}
/// Get the language corresponding to the registered file name extensions
/// \param filename: a filename
/// \return the corresponding language or `nullptr` if the extension cannot
/// be resolved to any registered language
std::unique_ptr<languaget> get_language_from_filename(
const std::string &filename)
{
std::size_t ext_pos=filename.rfind('.');
if(ext_pos==std::string::npos)
return nullptr;
std::string extension=
std::string(filename, ext_pos+1, std::string::npos);
if(extension.empty())
return nullptr;
for(languagest::const_iterator
l_it=languages.begin();
l_it!=languages.end();
l_it++)
{
#ifdef _WIN32
for(std::set<std::string>::const_iterator
e_it=l_it->extensions.begin();
e_it!=l_it->extensions.end();
e_it++)
if(_stricmp(extension.c_str(), e_it->c_str())==0)
return l_it->factory();
#else
if(l_it->extensions.find(extension)!=l_it->extensions.end())
return l_it->factory();
#endif
}
return nullptr;
}
/// Returns the default language
/// \return the first registered language
std::unique_ptr<languaget> get_default_language()
{
PRECONDITION(!languages.empty());
return languages.front().factory();
}