Skip to content

Commit 9f01d3e

Browse files
committed
xml_parsert: construct with message handler
This both avoids an object of static lifetime as well as it fixes the (transitive) use of the deprecated messaget() constructor. Avoid global objects in the lexer (as side-effect making it reentrant) as initialisation is required. The parser continues to have global state, so guard against reentrant use.
1 parent 7232457 commit 9f01d3e

File tree

4 files changed

+55
-27
lines changed

4 files changed

+55
-27
lines changed

src/xmllang/parser.y

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
#include "xml_parser.h"
55

6-
int yyxmllex();
7-
extern char *yyxmltext;
6+
int yyxmllex(void *);
7+
char *yyxmlget_text(void *);
88

9-
int yyxmlerror(const std::string &error)
9+
int yyxmlerror(xml_parsert &xml_parser, void *scanner, const std::string &error)
1010
{
11-
xml_parser.parse_error(error, yyxmltext);
11+
xml_parser.parse_error(error, yyxmlget_text(scanner));
1212
return 0;
1313
}
1414

@@ -26,6 +26,10 @@ int yyxmlerror(const std::string &error)
2626
#endif
2727
%}
2828

29+
%parse-param {xml_parsert &xml_parser}
30+
%parse-param {void *scanner}
31+
%lex-param {void *scanner}
32+
2933
%union {char *s;}
3034

3135
%token STARTXMLDECL

src/xmllang/scanner.l

+5-6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
%option noinput
44
%option nounistd
55
%option never-interactive
6+
%option noyywrap
7+
%option reentrant
8+
%option extra-type="xml_parsert *"
69

710
%{
811

@@ -19,7 +22,7 @@
1922
#include "xml_parser.h"
2023
#include "xml_y.tab.h"
2124

22-
#define PARSER xml_parser
25+
#define PARSER (*yyextra)
2326

2427
//static int keep; /* To store start condition */
2528

@@ -87,9 +90,5 @@ string \"([^"&]|{esc})*\"|\'([^'&]|{esc})*\'
8790
<DTD>. {/* skip */}
8891
<DTD>\]{close} {BEGIN(INITIAL); /* skip */}
8992

90-
. { yyxmlerror("unexpected character"); }
93+
. { yyxmlerror(*yyextra, yyscanner, "unexpected character"); }
9194
{nl} {/* skip, must be an extra one at EOF */;}
92-
93-
%%
94-
95-
int yywrap() { return 1; }

src/xmllang/xml_parser.cpp

+17-7
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,20 @@ Author: Daniel Kroening, [email protected]
1010

1111
#include <fstream>
1212

13-
xml_parsert xml_parser;
13+
int xml_parsert::instance_count = 0;
14+
15+
int yyxmllex_init_extra(xml_parsert *, void **);
16+
int yyxmllex_destroy(void *);
17+
int yyxmlparse(xml_parsert &, void *);
18+
19+
bool xml_parsert::parse()
20+
{
21+
void *scanner;
22+
yyxmllex_init_extra(this, &scanner);
23+
bool parse_fail = yyxmlparse(*this, scanner) != 0;
24+
yyxmllex_destroy(scanner);
25+
return parse_fail;
26+
}
1427

1528
// 'do it all' function
1629
bool parse_xml(
@@ -19,19 +32,16 @@ bool parse_xml(
1932
message_handlert &message_handler,
2033
xmlt &dest)
2134
{
22-
xml_parser.clear();
35+
xml_parsert xml_parser{message_handler};
36+
2337
xml_parser.set_file(filename);
2438
xml_parser.in=&in;
25-
xml_parser.log.set_message_handler(message_handler);
2639

27-
bool result=yyxmlparse()!=0;
40+
bool result = xml_parser.parse();
2841

2942
// save result
3043
xml_parser.parse_tree.element.swap(dest);
3144

32-
// save some memory
33-
xml_parser.clear();
34-
3545
return result;
3646
}
3747

src/xmllang/xml_parser.h

+25-10
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,25 @@ Author: Daniel Kroening, [email protected]
1414

1515
#include "xml_parse_tree.h"
1616

17-
int yyxmlparse();
18-
1917
class xml_parsert:public parsert
2018
{
2119
public:
20+
explicit xml_parsert(message_handlert &message_handler)
21+
: parsert(message_handler)
22+
{
23+
// Simplistic check that we don't attempt to do reentrant parsing as the
24+
// Bison-generated parser has global state.
25+
PRECONDITION(++instance_count == 1);
26+
stack.push_back(&parse_tree.element);
27+
}
28+
29+
xml_parsert(const xml_parsert &) = delete;
30+
31+
~xml_parsert() override
32+
{
33+
--instance_count;
34+
}
35+
2236
xml_parse_treet parse_tree;
2337

2438
std::list<xmlt *> stack;
@@ -28,29 +42,30 @@ class xml_parsert:public parsert
2842
return *stack.back();
2943
}
3044

31-
virtual bool parse()
32-
{
33-
return yyxmlparse()!=0;
34-
}
45+
bool parse() override;
3546

3647
void new_level()
3748
{
3849
current().elements.push_back(xmlt());
3950
stack.push_back(&current().elements.back());
4051
}
4152

42-
virtual void clear()
53+
/// Clears the parser state. May be removed in future as there should not be a
54+
/// need to re-use an existing parser object.
55+
void clear() override
4356
{
4457
parse_tree.clear();
4558
// set up stack
4659
stack.clear();
4760
stack.push_back(&parse_tree.element);
61+
parsert::clear();
4862
}
49-
};
5063

51-
extern xml_parsert xml_parser;
64+
protected:
65+
static int instance_count;
66+
};
5267

53-
int yyxmlerror(const std::string &error);
68+
int yyxmlerror(xml_parsert &, void *, const std::string &);
5469

5570
// 'do it all' functions
5671
bool parse_xml(

0 commit comments

Comments
 (0)