diff --git a/src/xmllang/parser.y b/src/xmllang/parser.y index 9e3e7ccc5db..17e0d360051 100644 --- a/src/xmllang/parser.y +++ b/src/xmllang/parser.y @@ -3,12 +3,12 @@ #include "xml_parser.h" -int yyxmllex(); -extern char *yyxmltext; +int yyxmllex(void *); +char *yyxmlget_text(void *); -int yyxmlerror(const std::string &error) +int yyxmlerror(xml_parsert &xml_parser, void *scanner, const std::string &error) { - xml_parser.parse_error(error, yyxmltext); + xml_parser.parse_error(error, yyxmlget_text(scanner)); return 0; } @@ -26,6 +26,10 @@ int yyxmlerror(const std::string &error) #endif %} +%parse-param {xml_parsert &xml_parser} +%parse-param {void *scanner} +%lex-param {void *scanner} + %union {char *s;} %token STARTXMLDECL diff --git a/src/xmllang/scanner.l b/src/xmllang/scanner.l index a9907847c58..b4242d1a534 100755 --- a/src/xmllang/scanner.l +++ b/src/xmllang/scanner.l @@ -3,6 +3,9 @@ %option noinput %option nounistd %option never-interactive +%option noyywrap +%option reentrant +%option extra-type="xml_parsert *" %{ @@ -19,7 +22,7 @@ #include "xml_parser.h" #include "xml_y.tab.h" -#define PARSER xml_parser +#define PARSER (*yyextra) //static int keep; /* To store start condition */ @@ -87,9 +90,5 @@ string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\' . {/* skip */} \]{close} {BEGIN(INITIAL); /* skip */} -. { yyxmlerror("unexpected character"); } +. { yyxmlerror(*yyextra, yyscanner, "unexpected character"); } {nl} {/* skip, must be an extra one at EOF */;} - -%% - -int yywrap() { return 1; } diff --git a/src/xmllang/xml_parser.cpp b/src/xmllang/xml_parser.cpp index ed1c2d113b9..5ca25441ab2 100644 --- a/src/xmllang/xml_parser.cpp +++ b/src/xmllang/xml_parser.cpp @@ -10,7 +10,20 @@ Author: Daniel Kroening, kroening@kroening.com #include -xml_parsert xml_parser; +int xml_parsert::instance_count = 0; + +int yyxmllex_init_extra(xml_parsert *, void **); +int yyxmllex_destroy(void *); +int yyxmlparse(xml_parsert &, void *); + +bool xml_parsert::parse() +{ + void *scanner; + yyxmllex_init_extra(this, &scanner); + bool parse_fail = yyxmlparse(*this, scanner) != 0; + yyxmllex_destroy(scanner); + return parse_fail; +} // 'do it all' function bool parse_xml( @@ -19,19 +32,16 @@ bool parse_xml( message_handlert &message_handler, xmlt &dest) { - xml_parser.clear(); + xml_parsert xml_parser{message_handler}; + xml_parser.set_file(filename); xml_parser.in=∈ - xml_parser.log.set_message_handler(message_handler); - bool result=yyxmlparse()!=0; + bool result = xml_parser.parse(); // save result xml_parser.parse_tree.element.swap(dest); - // save some memory - xml_parser.clear(); - return result; } diff --git a/src/xmllang/xml_parser.h b/src/xmllang/xml_parser.h index f4659160653..27687b633cd 100644 --- a/src/xmllang/xml_parser.h +++ b/src/xmllang/xml_parser.h @@ -14,11 +14,25 @@ Author: Daniel Kroening, kroening@kroening.com #include "xml_parse_tree.h" -int yyxmlparse(); - class xml_parsert:public parsert { public: + explicit xml_parsert(message_handlert &message_handler) + : parsert(message_handler) + { + // Simplistic check that we don't attempt to do reentrant parsing as the + // Bison-generated parser has global state. + PRECONDITION(++instance_count == 1); + stack.push_back(&parse_tree.element); + } + + xml_parsert(const xml_parsert &) = delete; + + ~xml_parsert() override + { + --instance_count; + } + xml_parse_treet parse_tree; std::list stack; @@ -28,10 +42,7 @@ class xml_parsert:public parsert return *stack.back(); } - virtual bool parse() - { - return yyxmlparse()!=0; - } + bool parse() override; void new_level() { @@ -39,18 +50,22 @@ class xml_parsert:public parsert stack.push_back(¤t().elements.back()); } - virtual void clear() + /// Clears the parser state. May be removed in future as there should not be a + /// need to re-use an existing parser object. + void clear() override { parse_tree.clear(); // set up stack stack.clear(); stack.push_back(&parse_tree.element); + parsert::clear(); } -}; -extern xml_parsert xml_parser; +protected: + static int instance_count; +}; -int yyxmlerror(const std::string &error); +int yyxmlerror(xml_parsert &, void *, const std::string &); // 'do it all' functions bool parse_xml(