cppparser: Fix slow parser performance

This commit is contained in:
rdb 2024-03-29 12:22:54 +01:00
parent acf118c96a
commit 04a9264e68
6 changed files with 31 additions and 62 deletions

View File

@ -31,37 +31,6 @@ CPPFile(const Filename &filename, const Filename &filename_as_referenced,
_filename_as_referenced.set_text(); _filename_as_referenced.set_text();
} }
/**
*
*/
CPPFile::
CPPFile(const CPPFile &copy) :
_filename(copy._filename),
_filename_as_referenced(copy._filename_as_referenced),
_source(copy._source),
_pragma_once(copy._pragma_once)
{
}
/**
*
*/
void CPPFile::
operator = (const CPPFile &copy) {
_filename = copy._filename;
_filename_as_referenced = copy._filename_as_referenced;
_source = copy._source;
_pragma_once = copy._pragma_once;
}
/**
*
*/
CPPFile::
~CPPFile() {
}
/** /**
* Returns true if the file appears to be a C or C++ source code file based on * Returns true if the file appears to be a C or C++ source code file based on
* its extension. That is, returns true if the filename ends in .c, .C, .cc, * its extension. That is, returns true if the filename ends in .c, .C, .cc,

View File

@ -34,9 +34,6 @@ public:
CPPFile(const Filename &filename = "", CPPFile(const Filename &filename = "",
const Filename &filename_as_referenced = "", const Filename &filename_as_referenced = "",
Source source = S_none); Source source = S_none);
CPPFile(const CPPFile &copy);
void operator = (const CPPFile &copy);
~CPPFile();
bool is_c_or_i_file() const; bool is_c_or_i_file() const;
static bool is_c_or_i_file(const Filename &filename); static bool is_c_or_i_file(const Filename &filename);

View File

@ -325,8 +325,8 @@ extract_args(vector_string &args, const string &expr, size_t &p) const {
* *
*/ */
string CPPManifest:: string CPPManifest::
expand(const vector_string &args, const Manifests &manifests, bool expand_undefined) const { expand(const vector_string &args, bool expand_undefined, const Ignores &ignores) const {
return r_expand(_expansion, args, manifests, expand_undefined); return r_expand(_expansion, args, expand_undefined, ignores);
} }
/** /**
@ -601,7 +601,7 @@ save_expansion(Expansion &expansion, const string &exp, const vector_string &par
*/ */
string CPPManifest:: string CPPManifest::
r_expand(const Expansion &expansion, const vector_string &args, r_expand(const Expansion &expansion, const vector_string &args,
const Manifests &manifests, bool expand_undefined) const { bool expand_undefined, const Ignores &ignores) const {
std::string result; std::string result;
for (const ExpansionNode &node : expansion) { for (const ExpansionNode &node : expansion) {
@ -631,7 +631,7 @@ r_expand(const Expansion &expansion, const vector_string &args,
} }
if (node._expand) { if (node._expand) {
_parser.expand_manifests(subst, manifests, expand_undefined); _parser.expand_manifests(subst, expand_undefined, ignores);
} }
if (!subst.empty()) { if (!subst.empty()) {
@ -654,7 +654,7 @@ r_expand(const Expansion &expansion, const vector_string &args,
if (!node._nested.empty()) { if (!node._nested.empty()) {
string nested_result; string nested_result;
if (node._optional && args.size() >= _num_parameters) { if (node._optional && args.size() >= _num_parameters) {
nested_result = r_expand(node._nested, args, manifests, expand_undefined); nested_result = r_expand(node._nested, args, expand_undefined, ignores);
} }
if (node._stringify) { if (node._stringify) {
nested_result = stringify(nested_result); nested_result = stringify(nested_result);

View File

@ -21,6 +21,7 @@
#include "cppBisonDefs.h" #include "cppBisonDefs.h"
#include "vector_string.h" #include "vector_string.h"
#include <unordered_set>
class CPPExpression; class CPPExpression;
class CPPType; class CPPType;
@ -30,7 +31,7 @@ class CPPType;
*/ */
class CPPManifest { class CPPManifest {
public: public:
typedef std::map<std::string, CPPManifest *> Manifests; typedef std::unordered_set<const CPPManifest *> Ignores;
CPPManifest(const CPPPreprocessor &parser, const std::string &args, const cppyyltype &loc); CPPManifest(const CPPPreprocessor &parser, const std::string &args, const cppyyltype &loc);
CPPManifest(const CPPPreprocessor &parser, const std::string &macro, const std::string &definition); CPPManifest(const CPPPreprocessor &parser, const std::string &macro, const std::string &definition);
@ -39,8 +40,8 @@ public:
static std::string stringify(const std::string &source); static std::string stringify(const std::string &source);
void extract_args(vector_string &args, const std::string &expr, size_t &p) const; void extract_args(vector_string &args, const std::string &expr, size_t &p) const;
std::string expand(const vector_string &args = vector_string(), std::string expand(const vector_string &args = vector_string(),
const Manifests &manifests = Manifests(), bool expand_undefined = false,
bool expand_undefined = false) const; const Ignores &ignores = Ignores()) const;
CPPType *determine_type() const; CPPType *determine_type() const;
@ -86,7 +87,7 @@ private:
const vector_string &parameter_names); const vector_string &parameter_names);
std::string r_expand(const Expansion &expansion, const vector_string &args, std::string r_expand(const Expansion &expansion, const vector_string &args,
const Manifests &manifests, bool expand_undefined) const; bool expand_undefined, const Ignores &ignores) const;
Expansion _expansion; Expansion _expansion;
}; };

View File

@ -902,7 +902,8 @@ push_expansion(const string &input, const CPPManifest *manifest, const YYLTYPE &
* Given a string, expand all manifests within the string. * Given a string, expand all manifests within the string.
*/ */
void CPPPreprocessor:: void CPPPreprocessor::
expand_manifests(string &expr, const Manifests &manifests, bool expand_undefined) const { expand_manifests(string &expr, bool expand_undefined,
const CPPManifest::Ignores &ignores) const {
size_t p = 0; size_t p = 0;
while (p < expr.size()) { while (p < expr.size()) {
if (isalpha(expr[p]) || expr[p] == '_') { if (isalpha(expr[p]) || expr[p] == '_') {
@ -925,8 +926,8 @@ expand_manifests(string &expr, const Manifests &manifests, bool expand_undefined
} }
else { else {
// Is it a manifest? // Is it a manifest?
Manifests::const_iterator mi = manifests.find(ident); Manifests::const_iterator mi = _manifests.find(ident);
if (mi != manifests.end()) { if (mi != _manifests.end() && ignores.count((*mi).second) == 0) {
const CPPManifest *manifest = (*mi).second; const CPPManifest *manifest = (*mi).second;
vector_string args; vector_string args;
if (manifest->_has_parameters) { if (manifest->_has_parameters) {
@ -943,11 +944,11 @@ expand_manifests(string &expr, const Manifests &manifests, bool expand_undefined
// Don't consider this manifest when expanding the arguments or // Don't consider this manifest when expanding the arguments or
// result, to prevent recursion. // result, to prevent recursion.
Manifests nested_manifests(manifests); CPPManifest::Ignores nested_ignores(ignores);
nested_manifests.erase((*mi).first); nested_ignores.insert(manifest);
string result = manifest->expand(args); string result = manifest->expand(args, expand_undefined, nested_ignores);
expand_manifests(result, nested_manifests, expand_undefined); expand_manifests(result, expand_undefined, nested_ignores);
expr = expr.substr(0, q) + result + expr.substr(p); expr = expr.substr(0, q) + result + expr.substr(p);
p = q + result.size(); p = q + result.size();
@ -1008,7 +1009,7 @@ CPPExpression *CPPPreprocessor::
parse_expr(const string &input_expr, CPPScope *current_scope, parse_expr(const string &input_expr, CPPScope *current_scope,
CPPScope *global_scope, const YYLTYPE &loc) { CPPScope *global_scope, const YYLTYPE &loc) {
string expr = input_expr; string expr = input_expr;
expand_manifests(expr, _manifests, false); expand_manifests(expr, false);
CPPExpressionParser ep(current_scope, global_scope); CPPExpressionParser ep(current_scope, global_scope);
ep._verbose = 0; ep._verbose = 0;
@ -1685,7 +1686,7 @@ void CPPPreprocessor::
handle_if_directive(const string &args, const YYLTYPE &loc) { handle_if_directive(const string &args, const YYLTYPE &loc) {
// When expanding manifests, we should replace unknown macros with 0. // When expanding manifests, we should replace unknown macros with 0.
string expr = args; string expr = args;
expand_manifests(expr, _manifests, true); expand_manifests(expr, true);
int expression_result = 0; int expression_result = 0;
CPPExpressionParser ep(current_scope, global_scope); CPPExpressionParser ep(current_scope, global_scope);
@ -1730,7 +1731,7 @@ handle_include_directive(const string &args, const YYLTYPE &loc) {
// filter out quotes and angle brackets properly, we'll only expand // filter out quotes and angle brackets properly, we'll only expand
// manifests if we don't begin with a quote or bracket. // manifests if we don't begin with a quote or bracket.
if (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) { if (!expr.empty() && (expr[0] != '"' && expr[0] != '<')) {
expand_manifests(expr, _manifests, false); expand_manifests(expr, false);
} }
if (!expr.empty()) { if (!expr.empty()) {
@ -2332,17 +2333,17 @@ expand_manifest(const CPPManifest *manifest, const YYLTYPE &loc) {
manifest->_variadic_param, args); manifest->_variadic_param, args);
} }
// Make a copy of the manifests, without the ones we're supposed to ignore. // Keep track of the manifests we're supposed to ignore.
Manifests manifests = _manifests; CPPManifest::Ignores ignores;
manifests.erase(manifest->_name); ignores.insert(manifest);
for (const InputFile &infile : _files) { for (const InputFile &infile : _files) {
if (infile._ignore_manifest) { if (infile._ignore_manifest) {
manifests.erase(infile._manifest->_name); ignores.insert(infile._manifest);
} }
} }
string expanded = " " + manifest->expand(args, manifests, false) + " "; string expanded = " " + manifest->expand(args, false, ignores) + " ";
push_expansion(expanded, manifest, loc); push_expansion(expanded, manifest, loc);
#ifdef CPP_VERBOSE_LEX #ifdef CPP_VERBOSE_LEX
@ -2575,7 +2576,7 @@ expand_has_include_function(string &expr, size_t q, size_t &p) const {
// Only expand if we've encountered unquoted identifier-valid characters, // Only expand if we've encountered unquoted identifier-valid characters,
// to be on the safe side. // to be on the safe side.
if (needs_expansion) { if (needs_expansion) {
expand_manifests(inc, _manifests, false); expand_manifests(inc, false);
} }
Filename filename; Filename filename;

View File

@ -27,6 +27,7 @@
#include <map> #include <map>
#include <list> #include <list>
#include <vector> #include <vector>
#include <unordered_map>
class CPPScope; class CPPScope;
class CPPTemplateParameterList; class CPPTemplateParameterList;
@ -71,7 +72,7 @@ public:
int get_warning_count() const; int get_warning_count() const;
int get_error_count() const; int get_error_count() const;
typedef CPPManifest::Manifests Manifests; typedef std::unordered_map<std::string, CPPManifest *> Manifests;
Manifests _manifests; Manifests _manifests;
typedef std::vector<CPPManifest *> ManifestStack; typedef std::vector<CPPManifest *> ManifestStack;
@ -119,8 +120,8 @@ protected:
const YYLTYPE &loc); const YYLTYPE &loc);
public: public:
void expand_manifests(std::string &expr, const Manifests &manifests, void expand_manifests(std::string &expr, bool expand_undefined = false,
bool expand_undefined = false) const; const CPPManifest::Ignores &ignores = CPPManifest::Ignores()) const;
CPPExpression *parse_expr(const std::string &expr, CPPScope *current_scope, CPPExpression *parse_expr(const std::string &expr, CPPScope *current_scope,
CPPScope *global_scope, const YYLTYPE &loc); CPPScope *global_scope, const YYLTYPE &loc);