Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ISC Open Source Projects
Kea
Commits
45abe4f7
Commit
45abe4f7
authored
Nov 14, 2016
by
Tomek Mrugalski
🛰
Browse files
[5014] Parser type is now configurable.
parent
3b63aa51
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/bin/dhcp6/dhcp6_lexer.ll
View file @
45abe4f7
...
...
@@ -25,6 +25,10 @@
//
variable
will
be
useful
for
logging
errors
.
static
isc:
:
dhcp:
:location
loc
;
static
bool
start_token_flag
=
false
;
static
isc:
:
dhcp:
:
Parser6Context:
:ParserType
start_token_value
;
//
To
avoid
the
call
to
exit
...
oops
!
#
define
YY_FATAL_ERROR
(
msg
)
isc:
:
dhcp:
:
Parser6Context:
:fatal
(
msg
)
%
}
...
...
@@ -81,10 +85,24 @@ JSONString \"{JSONStringCharacter}*\"
%%
%
{
//
This
part
of
the
code
is
copied
over
to
the
verbatim
to
the
top
//
of
the
generated
yylex
function
.
Explanation:
//
http:
//www
.
gnu
.
org/software/bison/manual/html_node/Multiple-start_002dsymbols
.
html
//
Code
run
each
time
yylex
is
called
.
loc
.
step
()
;
int
comment_start_line
=
0
;
if
(
start_token_flag
)
{
start_token_flag
=
false
;
switch
(
start_token_value
)
{
case
Parser6Context:
:
PARSER_DHCP6:
return
isc:
:
dhcp:
:
Dhcp6Parser:
:make_TOPLEVEL_DHCP6
(
loc
)
;
case
Parser6Context:
:
PARSER_GENERIC_JSON:
return
isc:
:
dhcp:
:
Dhcp6Parser:
:make_TOPLEVEL_GENERIC_JSON
(
loc
)
;
}
}
%
}
#
.*
;
...
...
@@ -247,8 +265,11 @@ null {
using
namespace
isc:
:dhcp
;
void
Parser6Context:
:scanStringBegin
()
Parser6Context:
:scanStringBegin
(
ParserType
parser_type
)
{
start_token_flag
=
true
;
start_token_value
=
parser_type
;
loc
.
initialize
(
&file_
)
;
yy_flex_debug
=
trace_scanning_
;
YY_BUFFER_STATE
buffer
;
...
...
@@ -266,7 +287,11 @@ Parser6Context::scanStringEnd()
}
void
Parser6Context:
:scanFileBegin
(
FILE
*
f
)
{
Parser6Context:
:scanFileBegin
(
FILE
*
f
,
ParserType
parser_type
)
{
start_token_flag
=
true
;
start_token_value
=
parser_type
;
loc
.
initialize
(
&file_
)
;
yy_flex_debug
=
trace_scanning_
;
YY_BUFFER_STATE
buffer
;
...
...
src/bin/dhcp6/dhcp6_parser.yy
View file @
45abe4f7
...
...
@@ -115,6 +115,11 @@ using namespace std;
OUTPUT "output"
DEBUGLEVEL "debuglevel"
SEVERITY "severity"
// Not real tokens, just a way to signal what the parser is expected to
// parse.
TOPLEVEL_DHCP6
TOPLEVEL_GENERIC_JSON
;
%token <std::string> STRING "constant string"
...
...
@@ -127,11 +132,15 @@ using namespace std;
%printer { yyoutput << $$; } <*>;
%%
// The whole grammar starts with a map, because the config file
// constists of Dhcp, Logger and DhcpDdns entries in one big { }.
// %start map - this will parse everything as generic JSON
// %start dhcp6_map - this will parse everything with Dhcp6 syntax checking
%start syntax_map;
%start start;
start: TOPLEVEL_DHCP6 syntax_map
| TOPLEVEL_GENERIC_JSON map;
// ---- generic JSON parser ---------------------------------
...
...
src/bin/dhcp6/parser_context.cc
View file @
45abe4f7
...
...
@@ -25,11 +25,11 @@ Parser6Context::~Parser6Context()
}
isc
::
data
::
ConstElementPtr
Parser6Context
::
parseString
(
const
std
::
string
&
str
)
Parser6Context
::
parseString
(
const
std
::
string
&
str
,
ParserType
parser_type
)
{
file_
=
"<string>"
;
string_
=
str
;
scanStringBegin
();
scanStringBegin
(
parser_type
);
isc
::
dhcp
::
Dhcp6Parser
parser
(
*
this
);
// Uncomment this to get detailed parser logs.
// trace_parsing_ = true;
...
...
@@ -48,7 +48,7 @@ Parser6Context::parseString(const std::string& str)
}
isc
::
data
::
ConstElementPtr
Parser6Context
::
parseFile
(
const
std
::
string
&
filename
)
{
Parser6Context
::
parseFile
(
const
std
::
string
&
filename
,
ParserType
parser_type
)
{
ifstream
f
;
f
.
open
(
filename
);
...
...
@@ -66,7 +66,7 @@ Parser6Context::parseFile(const std::string& filename) {
file_
=
filename
;
scanStringBegin
();
scanStringBegin
(
parser_type
);
isc
::
dhcp
::
Dhcp6Parser
parser
(
*
this
);
// Uncomment this to get detailed parser logs.
// trace_parsing_ = true;
...
...
src/bin/dhcp6/parser_context.h
View file @
45abe4f7
...
...
@@ -34,6 +34,10 @@ public:
class
Parser6Context
{
public:
typedef
enum
{
PARSER_DHCP6
,
PARSER_GENERIC_JSON
}
ParserType
;
/// @brief Default constructor.
///
/// @param option_universe Option universe: DHCPv4 or DHCPv6. This is used
...
...
@@ -48,21 +52,23 @@ public:
std
::
vector
<
isc
::
data
::
ElementPtr
>
stack_
;
/// @brief Method called before scanning starts on a string.
void
scanStringBegin
();
void
scanStringBegin
(
ParserType
type
);
/// @brief Method called after the last tokens are scanned from a string.
void
scanStringEnd
();
void
scanFileBegin
(
FILE
*
f
);
void
scanFileBegin
(
FILE
*
f
,
ParserType
type
);
void
scanFileEnd
(
FILE
*
f
);
/// @brief Run the parser on the string specified.
///
/// @param str string to be written
/// @return true on success.
isc
::
data
::
ConstElementPtr
parseString
(
const
std
::
string
&
str
);
isc
::
data
::
ConstElementPtr
parseString
(
const
std
::
string
&
str
,
ParserType
parser_type
);
isc
::
data
::
ConstElementPtr
parseFile
(
const
std
::
string
&
filename
);
isc
::
data
::
ConstElementPtr
parseFile
(
const
std
::
string
&
filename
,
ParserType
parser_type
);
/// @brief The name of the file being parsed.
/// Used later to pass the file name to the location tracker.
...
...
src/bin/dhcp6/tests/parser_unittest.cc
View file @
45abe4f7
...
...
@@ -17,32 +17,33 @@ void compareJSON(ConstElementPtr a, ConstElementPtr b, bool print = true) {
ASSERT_TRUE
(
a
);
ASSERT_TRUE
(
b
);
if
(
print
)
{
std
::
cout
<<
a
->
str
()
<<
std
::
endl
;
std
::
cout
<<
b
->
str
()
<<
std
::
endl
;
std
::
cout
<<
"JSON A: -----"
<<
endl
<<
a
->
str
()
<<
std
::
endl
;
std
::
cout
<<
"JSON B: -----"
<<
endl
<<
b
->
str
()
<<
std
::
endl
;
cout
<<
"---------"
<<
endl
<<
endl
;
}
EXPECT_EQ
(
a
->
str
(),
b
->
str
());
}
void
testParser
(
const
std
::
string
&
txt
)
{
void
testParser
(
const
std
::
string
&
txt
,
Parser6Context
::
ParserType
parser_type
)
{
ElementPtr
reference_json
;
ConstElementPtr
test_json
;
EXPECT_NO_THROW
(
reference_json
=
Element
::
fromJSON
(
txt
,
true
));
EXPECT_NO_THROW
({
Parser6Context
ctx
;
test_json
=
ctx
.
parseString
(
txt
);
test_json
=
ctx
.
parseString
(
txt
,
parser_type
);
});
// Now compare if both representations are the same.
compareJSON
(
reference_json
,
test_json
);
}
void
testParser2
(
const
std
::
string
&
txt
)
{
void
testParser2
(
const
std
::
string
&
txt
,
Parser6Context
::
ParserType
parser_type
)
{
ConstElementPtr
test_json
;
EXPECT_NO_THROW
({
Parser6Context
ctx
;
test_json
=
ctx
.
parseString
(
txt
);
test_json
=
ctx
.
parseString
(
txt
,
parser_type
);
});
/// @todo: Implement actual validation here. since the original
/// Element::fromJSON does not support several comment types, we don't
...
...
@@ -53,35 +54,35 @@ void testParser2(const std::string& txt) {
TEST
(
ParserTest
,
mapInMap
)
{
string
txt
=
"{
\"
Dhcp6
\"
: {
\"
foo
\"
: 123,
\"
baz
\"
: 456 } }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
listInList
)
{
string
txt
=
"{
\"
countries
\"
: [ [
\"
Britain
\"
,
\"
Wales
\"
,
\"
Scotland
\"
], "
"[
\"
Pomorze
\"
,
\"
Wielkopolska
\"
,
\"
Tatry
\"
] ] }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
nestedMaps
)
{
string
txt
=
"{
\"
europe
\"
: {
\"
UK
\"
: {
\"
London
\"
: {
\"
street
\"
:
\"
221B Baker
\"
}}}}"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
nestedLists
)
{
string
txt
=
"{
\"
unity
\"
: [
\"
half
\"
, [
\"
quarter
\"
, [
\"
eighth
\"
, [
\"
sixteenth
\"
]]]] }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
listsInMaps
)
{
string
txt
=
"{
\"
constellations
\"
: {
\"
orion
\"
: [
\"
rigel
\"
,
\"
betelguese
\"
], "
"
\"
cygnus
\"
: [
\"
deneb
\"
,
\"
albireo
\"
] } }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
mapsInLists
)
{
string
txt
=
"{
\"
solar-system
\"
: [ {
\"
name
\"
:
\"
earth
\"
,
\"
gravity
\"
: 1.0 },"
" {
\"
name
\"
:
\"
mars
\"
,
\"
gravity
\"
: 0.376 } ] }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
types
)
{
...
...
@@ -91,7 +92,7 @@ TEST(ParserTest, types) {
"
\"
map
\"
: {
\"
foo
\"
:
\"
bar
\"
},"
"
\"
list
\"
: [ 1, 2, 3 ],"
"
\"
null
\"
: null }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
bashComments
)
{
...
...
@@ -111,7 +112,7 @@ TEST(ParserTest, bashComments) {
"
\"
interface
\"
:
\"
eth0
\"
"
" } ],"
"
\"
valid-lifetime
\"
: 4000 }"
;
testParser
(
txt
);
testParser
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
cComments
)
{
...
...
@@ -128,7 +129,7 @@ TEST(ParserTest, cComments) {
"
\"
interface
\"
:
\"
eth0
\"
"
" } ],"
"
\"
valid-lifetime
\"
: 4000 }"
;
testParser2
(
txt
);
testParser2
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
bashComments2
)
{
...
...
@@ -145,7 +146,7 @@ TEST(ParserTest, bashComments2) {
"
\"
interface
\"
:
\"
eth0
\"
"
" } ],"
"
\"
valid-lifetime
\"
: 4000 }"
;
testParser2
(
txt
);
testParser2
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
TEST
(
ParserTest
,
multilineComments
)
{
...
...
@@ -163,7 +164,7 @@ TEST(ParserTest, multilineComments) {
"
\"
interface
\"
:
\"
eth0
\"
"
" } ],"
"
\"
valid-lifetime
\"
: 4000 }"
;
testParser2
(
txt
);
testParser2
(
txt
,
Parser6Context
::
PARSER_GENERIC_JSON
);
}
...
...
@@ -177,7 +178,7 @@ void testFile(const std::string& fname, bool print) {
try
{
Parser6Context
ctx
;
test_json
=
ctx
.
parseFile
(
fname
);
test_json
=
ctx
.
parseFile
(
fname
,
Parser6Context
::
PARSER_DHCP6
);
}
catch
(
const
std
::
exception
&
x
)
{
cout
<<
"EXCEPTION: "
<<
x
.
what
()
<<
endl
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment