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
gaoqiong
yaml-cpp
Commits
a372bfdc
Commit
a372bfdc
authored
Oct 29, 2009
by
Jesse Beder
Browse files
Merged r295:305 from the tags branch to the trunk
parent
fe57829a
Changes
27
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
297 additions
and
96 deletions
+297
-96
include/emitter.h
include/emitter.h
+1
-0
include/emittermanip.h
include/emittermanip.h
+10
-0
include/exceptions.h
include/exceptions.h
+6
-0
include/node.h
include/node.h
+4
-1
include/parser.h
include/parser.h
+5
-5
src/emitter.cpp
src/emitter.cpp
+35
-4
src/emitterutils.cpp
src/emitterutils.cpp
+18
-0
src/emitterutils.h
src/emitterutils.h
+1
-0
src/exp.h
src/exp.h
+5
-0
src/node.cpp
src/node.cpp
+9
-6
src/parser.cpp
src/parser.cpp
+32
-23
src/parserstate.cpp
src/parserstate.cpp
+7
-8
src/parserstate.h
src/parserstate.h
+5
-4
src/regex.h
src/regex.h
+1
-1
src/scanner.cpp
src/scanner.cpp
+25
-13
src/scanner.h
src/scanner.h
+6
-3
src/scanscalar.h
src/scanscalar.h
+1
-0
src/scantag.cpp
src/scantag.cpp
+84
-0
src/scantag.h
src/scantag.h
+18
-0
src/scantoken.cpp
src/scantoken.cpp
+24
-28
No files found.
include/emitter.h
View file @
a372bfdc
...
@@ -52,6 +52,7 @@ namespace YAML
...
@@ -52,6 +52,7 @@ namespace YAML
Emitter
&
Write
(
double
d
);
Emitter
&
Write
(
double
d
);
Emitter
&
Write
(
const
_Alias
&
alias
);
Emitter
&
Write
(
const
_Alias
&
alias
);
Emitter
&
Write
(
const
_Anchor
&
anchor
);
Emitter
&
Write
(
const
_Anchor
&
anchor
);
Emitter
&
Write
(
const
_Tag
&
tag
);
Emitter
&
Write
(
const
_Comment
&
comment
);
Emitter
&
Write
(
const
_Comment
&
comment
);
Emitter
&
Write
(
const
_Null
&
null
);
Emitter
&
Write
(
const
_Null
&
null
);
...
...
include/emittermanip.h
View file @
a372bfdc
...
@@ -80,6 +80,16 @@ namespace YAML
...
@@ -80,6 +80,16 @@ namespace YAML
inline
_Anchor
Anchor
(
const
std
::
string
content
)
{
inline
_Anchor
Anchor
(
const
std
::
string
content
)
{
return
_Anchor
(
content
);
return
_Anchor
(
content
);
}
}
struct
_Tag
{
_Tag
(
const
std
::
string
&
content_
)
:
content
(
content_
),
verbatim
(
true
)
{}
std
::
string
content
;
bool
verbatim
;
};
inline
_Tag
VerbatimTag
(
const
std
::
string
&
content
)
{
return
_Tag
(
content
);
}
struct
_Comment
{
struct
_Comment
{
_Comment
(
const
std
::
string
&
content_
)
:
content
(
content_
)
{}
_Comment
(
const
std
::
string
&
content_
)
:
content
(
content_
)
{}
...
...
include/exceptions.h
View file @
a372bfdc
...
@@ -17,7 +17,12 @@ namespace YAML
...
@@ -17,7 +17,12 @@ namespace YAML
const
std
::
string
YAML_DIRECTIVE_ARGS
=
"YAML directives must have exactly one argument"
;
const
std
::
string
YAML_DIRECTIVE_ARGS
=
"YAML directives must have exactly one argument"
;
const
std
::
string
YAML_VERSION
=
"bad YAML version: "
;
const
std
::
string
YAML_VERSION
=
"bad YAML version: "
;
const
std
::
string
YAML_MAJOR_VERSION
=
"YAML major version too large"
;
const
std
::
string
YAML_MAJOR_VERSION
=
"YAML major version too large"
;
const
std
::
string
REPEATED_YAML_DIRECTIVE
=
"repeated YAML directive"
;
const
std
::
string
TAG_DIRECTIVE_ARGS
=
"TAG directives must have exactly two arguments"
;
const
std
::
string
TAG_DIRECTIVE_ARGS
=
"TAG directives must have exactly two arguments"
;
const
std
::
string
REPEATED_TAG_DIRECTIVE
=
"repeated TAG directive"
;
const
std
::
string
CHAR_IN_TAG_HANDLE
=
"illegal character found while scanning tag handle"
;
const
std
::
string
TAG_WITH_NO_SUFFIX
=
"tag handle with no suffix"
;
const
std
::
string
END_OF_VERBATIM_TAG
=
"end of verbatim tag not found"
;
const
std
::
string
END_OF_MAP
=
"end of map not found"
;
const
std
::
string
END_OF_MAP
=
"end of map not found"
;
const
std
::
string
END_OF_MAP_FLOW
=
"end of map flow not found"
;
const
std
::
string
END_OF_MAP_FLOW
=
"end of map flow not found"
;
const
std
::
string
END_OF_SEQ
=
"end of sequence not found"
;
const
std
::
string
END_OF_SEQ
=
"end of sequence not found"
;
...
@@ -57,6 +62,7 @@ namespace YAML
...
@@ -57,6 +62,7 @@ namespace YAML
const
std
::
string
SINGLE_QUOTED_CHAR
=
"invalid character in single-quoted string"
;
const
std
::
string
SINGLE_QUOTED_CHAR
=
"invalid character in single-quoted string"
;
const
std
::
string
INVALID_ANCHOR
=
"invalid anchor"
;
const
std
::
string
INVALID_ANCHOR
=
"invalid anchor"
;
const
std
::
string
INVALID_ALIAS
=
"invalid alias"
;
const
std
::
string
INVALID_ALIAS
=
"invalid alias"
;
const
std
::
string
INVALID_TAG
=
"invalid tag"
;
const
std
::
string
EXPECTED_KEY_TOKEN
=
"expected key token"
;
const
std
::
string
EXPECTED_KEY_TOKEN
=
"expected key token"
;
const
std
::
string
EXPECTED_VALUE_TOKEN
=
"expected value token"
;
const
std
::
string
EXPECTED_VALUE_TOKEN
=
"expected value token"
;
const
std
::
string
UNEXPECTED_KEY_TOKEN
=
"unexpected key token"
;
const
std
::
string
UNEXPECTED_KEY_TOKEN
=
"unexpected key token"
;
...
...
include/node.h
View file @
a372bfdc
...
@@ -9,7 +9,6 @@
...
@@ -9,7 +9,6 @@
#include "iterator.h"
#include "iterator.h"
#include "mark.h"
#include "mark.h"
#include "noncopyable.h"
#include "noncopyable.h"
#include "parserstate.h"
#include <iostream>
#include <iostream>
#include <string>
#include <string>
#include <vector>
#include <vector>
...
@@ -21,6 +20,7 @@ namespace YAML
...
@@ -21,6 +20,7 @@ namespace YAML
class
Content
;
class
Content
;
class
Scanner
;
class
Scanner
;
class
Emitter
;
class
Emitter
;
class
ParserState
;
enum
CONTENT_TYPE
{
CT_NONE
,
CT_SCALAR
,
CT_SEQUENCE
,
CT_MAP
};
enum
CONTENT_TYPE
{
CT_NONE
,
CT_SCALAR
,
CT_SEQUENCE
,
CT_MAP
};
...
@@ -75,6 +75,9 @@ namespace YAML
...
@@ -75,6 +75,9 @@ namespace YAML
const
Node
*
Identity
()
const
{
return
m_pIdentity
;
}
const
Node
*
Identity
()
const
{
return
m_pIdentity
;
}
bool
IsAlias
()
const
{
return
m_alias
;
}
bool
IsAlias
()
const
{
return
m_alias
;
}
bool
IsReferenced
()
const
{
return
m_referenced
;
}
bool
IsReferenced
()
const
{
return
m_referenced
;
}
// for tags
const
std
::
string
GetTag
()
const
{
return
m_tag
;
}
// TODO: should an aliased node return its alias's tag?
// emitting
// emitting
friend
Emitter
&
operator
<<
(
Emitter
&
out
,
const
Node
&
node
);
friend
Emitter
&
operator
<<
(
Emitter
&
out
,
const
Node
&
node
);
...
...
include/parser.h
View file @
a372bfdc
...
@@ -5,7 +5,6 @@
...
@@ -5,7 +5,6 @@
#include "node.h"
#include "node.h"
#include "parserstate.h"
#include "noncopyable.h"
#include "noncopyable.h"
#include <ios>
#include <ios>
#include <string>
#include <string>
...
@@ -16,6 +15,7 @@
...
@@ -16,6 +15,7 @@
namespace
YAML
namespace
YAML
{
{
class
Scanner
;
class
Scanner
;
class
ParserState
;
struct
Token
;
struct
Token
;
class
Parser
:
private
noncopyable
class
Parser
:
private
noncopyable
...
@@ -33,13 +33,13 @@ namespace YAML
...
@@ -33,13 +33,13 @@ namespace YAML
private:
private:
void
ParseDirectives
();
void
ParseDirectives
();
void
HandleDirective
(
Token
*
pT
oken
);
void
HandleDirective
(
const
Token
&
t
oken
);
void
HandleYamlDirective
(
Token
*
pT
oken
);
void
HandleYamlDirective
(
const
Token
&
t
oken
);
void
HandleTagDirective
(
Token
*
pT
oken
);
void
HandleTagDirective
(
const
Token
&
t
oken
);
private:
private:
std
::
auto_ptr
<
Scanner
>
m_pScanner
;
std
::
auto_ptr
<
Scanner
>
m_pScanner
;
ParserState
m_
s
tate
;
std
::
auto_ptr
<
ParserState
>
m_
pS
tate
;
};
};
}
}
...
...
src/emitter.cpp
View file @
a372bfdc
...
@@ -146,6 +146,8 @@ namespace YAML
...
@@ -146,6 +146,8 @@ namespace YAML
switch
(
curState
)
{
switch
(
curState
)
{
// document-level
// document-level
case
ES_WAITING_FOR_DOC
:
case
ES_WAITING_FOR_DOC
:
m_stream
<<
"---"
;
m_pState
->
RequireSeparation
();
m_pState
->
SwitchState
(
ES_WRITING_DOC
);
m_pState
->
SwitchState
(
ES_WRITING_DOC
);
return
true
;
return
true
;
case
ES_WRITING_DOC
:
case
ES_WRITING_DOC
:
...
@@ -323,7 +325,10 @@ namespace YAML
...
@@ -323,7 +325,10 @@ namespace YAML
EMITTER_STATE
curState
=
m_pState
->
GetCurState
();
EMITTER_STATE
curState
=
m_pState
->
GetCurState
();
EMITTER_MANIP
flowType
=
m_pState
->
GetFlowType
(
GT_SEQ
);
EMITTER_MANIP
flowType
=
m_pState
->
GetFlowType
(
GT_SEQ
);
if
(
flowType
==
Block
)
{
if
(
flowType
==
Block
)
{
if
(
curState
==
ES_WRITING_BLOCK_SEQ_ENTRY
||
curState
==
ES_WRITING_BLOCK_MAP_KEY
||
curState
==
ES_WRITING_BLOCK_MAP_VALUE
)
{
if
(
curState
==
ES_WRITING_BLOCK_SEQ_ENTRY
||
curState
==
ES_WRITING_BLOCK_MAP_KEY
||
curState
==
ES_WRITING_BLOCK_MAP_VALUE
||
curState
==
ES_WRITING_DOC
)
{
m_stream
<<
"
\n
"
;
m_stream
<<
"
\n
"
;
m_pState
->
UnsetSeparation
();
m_pState
->
UnsetSeparation
();
}
}
...
@@ -354,8 +359,12 @@ namespace YAML
...
@@ -354,8 +359,12 @@ namespace YAML
// to a flow sequence if it is
// to a flow sequence if it is
assert
(
curState
==
ES_DONE_WITH_BLOCK_SEQ_ENTRY
||
curState
==
ES_WAITING_FOR_BLOCK_SEQ_ENTRY
);
assert
(
curState
==
ES_DONE_WITH_BLOCK_SEQ_ENTRY
||
curState
==
ES_WAITING_FOR_BLOCK_SEQ_ENTRY
);
if
(
curState
==
ES_WAITING_FOR_BLOCK_SEQ_ENTRY
)
{
if
(
curState
==
ES_WAITING_FOR_BLOCK_SEQ_ENTRY
)
{
// Note: only one of these will actually output anything for a given situation
EmitSeparationIfNecessary
();
unsigned
curIndent
=
m_pState
->
GetCurIndent
();
unsigned
curIndent
=
m_pState
->
GetCurIndent
();
m_stream
<<
IndentTo
(
curIndent
)
<<
"[]"
;
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
"[]"
;
}
}
}
else
if
(
flowType
==
FT_FLOW
)
{
}
else
if
(
flowType
==
FT_FLOW
)
{
// Note: flow sequences are allowed to be empty
// Note: flow sequences are allowed to be empty
...
@@ -384,7 +393,10 @@ namespace YAML
...
@@ -384,7 +393,10 @@ namespace YAML
EMITTER_STATE
curState
=
m_pState
->
GetCurState
();
EMITTER_STATE
curState
=
m_pState
->
GetCurState
();
EMITTER_MANIP
flowType
=
m_pState
->
GetFlowType
(
GT_MAP
);
EMITTER_MANIP
flowType
=
m_pState
->
GetFlowType
(
GT_MAP
);
if
(
flowType
==
Block
)
{
if
(
flowType
==
Block
)
{
if
(
curState
==
ES_WRITING_BLOCK_SEQ_ENTRY
||
curState
==
ES_WRITING_BLOCK_MAP_KEY
||
curState
==
ES_WRITING_BLOCK_MAP_VALUE
)
{
if
(
curState
==
ES_WRITING_BLOCK_SEQ_ENTRY
||
curState
==
ES_WRITING_BLOCK_MAP_KEY
||
curState
==
ES_WRITING_BLOCK_MAP_VALUE
||
curState
==
ES_WRITING_DOC
)
{
m_stream
<<
"
\n
"
;
m_stream
<<
"
\n
"
;
m_pState
->
UnsetSeparation
();
m_pState
->
UnsetSeparation
();
}
}
...
@@ -415,8 +427,11 @@ namespace YAML
...
@@ -415,8 +427,11 @@ namespace YAML
// to a flow sequence if it is
// to a flow sequence if it is
assert
(
curState
==
ES_DONE_WITH_BLOCK_MAP_VALUE
||
curState
==
ES_WAITING_FOR_BLOCK_MAP_ENTRY
);
assert
(
curState
==
ES_DONE_WITH_BLOCK_MAP_VALUE
||
curState
==
ES_WAITING_FOR_BLOCK_MAP_ENTRY
);
if
(
curState
==
ES_WAITING_FOR_BLOCK_MAP_ENTRY
)
{
if
(
curState
==
ES_WAITING_FOR_BLOCK_MAP_ENTRY
)
{
// Note: only one of these will actually output anything for a given situation
EmitSeparationIfNecessary
();
unsigned
curIndent
=
m_pState
->
GetCurIndent
();
unsigned
curIndent
=
m_pState
->
GetCurIndent
();
m_stream
<<
IndentTo
(
curIndent
)
<<
"{}"
;
m_stream
<<
IndentTo
(
curIndent
);
m_stream
<<
"{}"
;
}
}
}
else
if
(
flowType
==
FT_FLOW
)
{
}
else
if
(
flowType
==
FT_FLOW
)
{
// Note: flow maps are allowed to be empty
// Note: flow maps are allowed to be empty
...
@@ -675,6 +690,22 @@ namespace YAML
...
@@ -675,6 +690,22 @@ namespace YAML
return
*
this
;
return
*
this
;
}
}
Emitter
&
Emitter
::
Write
(
const
_Tag
&
tag
)
{
if
(
!
good
())
return
*
this
;
PreAtomicWrite
();
EmitSeparationIfNecessary
();
if
(
!
Utils
::
WriteTag
(
m_stream
,
tag
.
content
))
{
m_pState
->
SetError
(
ErrorMsg
::
INVALID_TAG
);
return
*
this
;
}
m_pState
->
RequireSeparation
();
// Note: no PostAtomicWrite() because we need another value for this node
return
*
this
;
}
Emitter
&
Emitter
::
Write
(
const
_Comment
&
comment
)
Emitter
&
Emitter
::
Write
(
const
_Comment
&
comment
)
{
{
if
(
!
good
())
if
(
!
good
())
...
...
src/emitterutils.cpp
View file @
a372bfdc
...
@@ -293,6 +293,24 @@ namespace YAML
...
@@ -293,6 +293,24 @@ namespace YAML
out
<<
"&"
;
out
<<
"&"
;
return
WriteAliasName
(
out
,
str
);
return
WriteAliasName
(
out
,
str
);
}
}
bool
WriteTag
(
ostream
&
out
,
const
std
::
string
&
str
)
{
out
<<
"!<"
;
StringCharSource
buffer
(
str
.
c_str
(),
str
.
size
());
while
(
buffer
)
{
int
n
=
Exp
::
URI
.
Match
(
buffer
);
if
(
n
<=
0
)
return
false
;
while
(
--
n
>=
0
)
{
out
<<
buffer
[
0
];
++
buffer
;
}
}
out
<<
">"
;
return
true
;
}
}
}
}
}
src/emitterutils.h
View file @
a372bfdc
...
@@ -18,6 +18,7 @@ namespace YAML
...
@@ -18,6 +18,7 @@ namespace YAML
bool
WriteComment
(
ostream
&
out
,
const
std
::
string
&
str
,
int
postCommentIndent
);
bool
WriteComment
(
ostream
&
out
,
const
std
::
string
&
str
,
int
postCommentIndent
);
bool
WriteAlias
(
ostream
&
out
,
const
std
::
string
&
str
);
bool
WriteAlias
(
ostream
&
out
,
const
std
::
string
&
str
);
bool
WriteAnchor
(
ostream
&
out
,
const
std
::
string
&
str
);
bool
WriteAnchor
(
ostream
&
out
,
const
std
::
string
&
str
);
bool
WriteTag
(
ostream
&
out
,
const
std
::
string
&
str
);
}
}
}
}
...
...
src/exp.h
View file @
a372bfdc
...
@@ -25,6 +25,7 @@ namespace YAML
...
@@ -25,6 +25,7 @@ namespace YAML
const
RegEx
Digit
=
RegEx
(
'0'
,
'9'
);
const
RegEx
Digit
=
RegEx
(
'0'
,
'9'
);
const
RegEx
Alpha
=
RegEx
(
'a'
,
'z'
)
||
RegEx
(
'A'
,
'Z'
);
const
RegEx
Alpha
=
RegEx
(
'a'
,
'z'
)
||
RegEx
(
'A'
,
'Z'
);
const
RegEx
AlphaNumeric
=
Alpha
||
Digit
;
const
RegEx
AlphaNumeric
=
Alpha
||
Digit
;
const
RegEx
Word
=
AlphaNumeric
||
RegEx
(
'-'
);
const
RegEx
Hex
=
Digit
||
RegEx
(
'A'
,
'F'
)
||
RegEx
(
'a'
,
'f'
);
const
RegEx
Hex
=
Digit
||
RegEx
(
'A'
,
'F'
)
||
RegEx
(
'a'
,
'f'
);
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
// Valid Unicode code points that are not part of c-printable (YAML 1.2, sec. 5.1)
const
RegEx
NotPrintable
=
RegEx
(
0
)
||
const
RegEx
NotPrintable
=
RegEx
(
0
)
||
...
@@ -45,6 +46,8 @@ namespace YAML
...
@@ -45,6 +46,8 @@ namespace YAML
ValueInFlow
=
RegEx
(
':'
)
+
(
BlankOrBreak
||
RegEx
(
",}"
,
REGEX_OR
));
ValueInFlow
=
RegEx
(
':'
)
+
(
BlankOrBreak
||
RegEx
(
",}"
,
REGEX_OR
));
const
RegEx
Comment
=
RegEx
(
'#'
);
const
RegEx
Comment
=
RegEx
(
'#'
);
const
RegEx
AnchorEnd
=
RegEx
(
"?:,]}%@`"
,
REGEX_OR
)
||
BlankOrBreak
;
const
RegEx
AnchorEnd
=
RegEx
(
"?:,]}%@`"
,
REGEX_OR
)
||
BlankOrBreak
;
const
RegEx
URI
=
Word
||
RegEx
(
"#;/?:@&=+$,_.!~*'()[]"
,
REGEX_OR
)
||
(
RegEx
(
'%'
)
+
Hex
+
Hex
);
const
RegEx
Tag
=
Word
||
RegEx
(
"#;/?:@&=+$_.~*'"
,
REGEX_OR
)
||
(
RegEx
(
'%'
)
+
Hex
+
Hex
);
// Plain scalar rules:
// Plain scalar rules:
// . Cannot start with a blank.
// . Cannot start with a blank.
...
@@ -79,6 +82,8 @@ namespace YAML
...
@@ -79,6 +82,8 @@ namespace YAML
const
char
Tag
=
'!'
;
const
char
Tag
=
'!'
;
const
char
LiteralScalar
=
'|'
;
const
char
LiteralScalar
=
'|'
;
const
char
FoldedScalar
=
'>'
;
const
char
FoldedScalar
=
'>'
;
const
char
VerbatimTagStart
=
'<'
;
const
char
VerbatimTagEnd
=
'>'
;
}
}
}
}
...
...
src/node.cpp
View file @
a372bfdc
...
@@ -9,6 +9,7 @@
...
@@ -9,6 +9,7 @@
#include "aliascontent.h"
#include "aliascontent.h"
#include "iterpriv.h"
#include "iterpriv.h"
#include "emitter.h"
#include "emitter.h"
#include "tag.h"
#include <stdexcept>
#include <stdexcept>
namespace
YAML
namespace
YAML
...
@@ -137,10 +138,8 @@ namespace YAML
...
@@ -137,10 +138,8 @@ namespace YAML
if
(
m_tag
!=
""
)
if
(
m_tag
!=
""
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
MULTIPLE_TAGS
);
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
MULTIPLE_TAGS
);
m_tag
=
state
.
TranslateTag
(
token
.
value
);
Tag
tag
(
token
);
m_tag
=
tag
.
Translate
(
state
);
for
(
std
::
size_t
i
=
0
;
i
<
token
.
params
.
size
();
i
++
)
m_tag
+=
token
.
params
[
i
];
pScanner
->
pop
();
pScanner
->
pop
();
}
}
...
@@ -241,7 +240,10 @@ namespace YAML
...
@@ -241,7 +240,10 @@ namespace YAML
bool
Node
::
GetScalar
(
std
::
string
&
s
)
const
bool
Node
::
GetScalar
(
std
::
string
&
s
)
const
{
{
if
(
!
m_pContent
)
{
if
(
!
m_pContent
)
{
s
=
"~"
;
if
(
m_tag
.
empty
())
s
=
"~"
;
else
s
=
""
;
return
true
;
return
true
;
}
}
...
@@ -258,7 +260,8 @@ namespace YAML
...
@@ -258,7 +260,8 @@ namespace YAML
out
<<
Anchor
(
node
.
m_anchor
);
out
<<
Anchor
(
node
.
m_anchor
);
}
}
// TODO: write tag
if
(
node
.
m_tag
!=
""
)
out
<<
VerbatimTag
(
node
.
m_tag
);
// write content
// write content
if
(
node
.
m_pContent
)
if
(
node
.
m_pContent
)
...
...
src/parser.cpp
View file @
a372bfdc
...
@@ -2,6 +2,7 @@
...
@@ -2,6 +2,7 @@
#include "scanner.h"
#include "scanner.h"
#include "token.h"
#include "token.h"
#include "exceptions.h"
#include "exceptions.h"
#include "parserstate.h"
#include <sstream>
#include <sstream>
#include <cstdio>
#include <cstdio>
...
@@ -28,7 +29,7 @@ namespace YAML
...
@@ -28,7 +29,7 @@ namespace YAML
void
Parser
::
Load
(
std
::
istream
&
in
)
void
Parser
::
Load
(
std
::
istream
&
in
)
{
{
m_pScanner
.
reset
(
new
Scanner
(
in
));
m_pScanner
.
reset
(
new
Scanner
(
in
));
m_
s
tate
.
R
eset
();
m_
pS
tate
.
r
eset
(
new
ParserState
);
}
}
// GetNextDocument
// GetNextDocument
...
@@ -54,7 +55,7 @@ namespace YAML
...
@@ -54,7 +55,7 @@ namespace YAML
m_pScanner
->
pop
();
m_pScanner
->
pop
();
// now parse our root node
// now parse our root node
document
.
Parse
(
m_pScanner
.
get
(),
m_
s
tate
);
document
.
Parse
(
m_pScanner
.
get
(),
*
m_
pS
tate
);
// and finally eat any doc ends we see
// and finally eat any doc ends we see
while
(
!
m_pScanner
->
empty
()
&&
m_pScanner
->
peek
().
type
==
Token
::
DOC_END
)
while
(
!
m_pScanner
->
empty
()
&&
m_pScanner
->
peek
().
type
==
Token
::
DOC_END
)
...
@@ -83,51 +84,59 @@ namespace YAML
...
@@ -83,51 +84,59 @@ namespace YAML
// we keep the directives from the last document if none are specified;
// we keep the directives from the last document if none are specified;
// but if any directives are specific, then we reset them
// but if any directives are specific, then we reset them
if
(
!
readDirective
)
if
(
!
readDirective
)
m_
s
tate
.
R
eset
();
m_
pS
tate
.
r
eset
(
new
ParserState
);
readDirective
=
true
;
readDirective
=
true
;
HandleDirective
(
&
token
);
HandleDirective
(
token
);
m_pScanner
->
pop
();
m_pScanner
->
pop
();
}
}
}
}
void
Parser
::
HandleDirective
(
Token
*
pT
oken
)
void
Parser
::
HandleDirective
(
const
Token
&
t
oken
)
{
{
if
(
pT
oken
->
value
==
"YAML"
)
if
(
t
oken
.
value
==
"YAML"
)
HandleYamlDirective
(
pT
oken
);
HandleYamlDirective
(
t
oken
);
else
if
(
pT
oken
->
value
==
"TAG"
)
else
if
(
t
oken
.
value
==
"TAG"
)
HandleTagDirective
(
pT
oken
);
HandleTagDirective
(
t
oken
);
}
}
// HandleYamlDirective
// HandleYamlDirective
// . Should be of the form 'major.minor' (like a version number)
// . Should be of the form 'major.minor' (like a version number)
void
Parser
::
HandleYamlDirective
(
Token
*
pT
oken
)
void
Parser
::
HandleYamlDirective
(
const
Token
&
t
oken
)
{
{
if
(
pToken
->
params
.
size
()
!=
1
)
if
(
token
.
params
.
size
()
!=
1
)
throw
ParserException
(
pToken
->
mark
,
ErrorMsg
::
YAML_DIRECTIVE_ARGS
);
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
YAML_DIRECTIVE_ARGS
);
if
(
!
m_pState
->
version
.
isDefault
)
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
REPEATED_YAML_DIRECTIVE
);
std
::
stringstream
str
(
pT
oken
->
params
[
0
]);
std
::
stringstream
str
(
t
oken
.
params
[
0
]);
str
>>
m_
s
tate
.
version
.
major
;
str
>>
m_
pS
tate
->
version
.
major
;
str
.
get
();
str
.
get
();
str
>>
m_
s
tate
.
version
.
minor
;
str
>>
m_
pS
tate
->
version
.
minor
;
if
(
!
str
||
str
.
peek
()
!=
EOF
)
if
(
!
str
||
str
.
peek
()
!=
EOF
)
throw
ParserException
(
pT
oken
->
mark
,
ErrorMsg
::
YAML_VERSION
+
pT
oken
->
params
[
0
]);
throw
ParserException
(
t
oken
.
mark
,
ErrorMsg
::
YAML_VERSION
+
t
oken
.
params
[
0
]);
if
(
m_
s
tate
.
version
.
major
>
1
)
if
(
m_
pS
tate
->
version
.
major
>
1
)
throw
ParserException
(
pT
oken
->
mark
,
ErrorMsg
::
YAML_MAJOR_VERSION
);
throw
ParserException
(
t
oken
.
mark
,
ErrorMsg
::
YAML_MAJOR_VERSION
);
m_pState
->
version
.
isDefault
=
false
;
// TODO: warning on major == 1, minor > 2?
// TODO: warning on major == 1, minor > 2?
}
}
// HandleTagDirective
// HandleTagDirective
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
// . Should be of the form 'handle prefix', where 'handle' is converted to 'prefix' in the file.
void
Parser
::
HandleTagDirective
(
Token
*
pT
oken
)
void
Parser
::
HandleTagDirective
(
const
Token
&
t
oken
)
{
{
if
(
pT
oken
->
params
.
size
()
!=
2
)
if
(
t
oken
.
params
.
size
()
!=
2
)
throw
ParserException
(
pT
oken
->
mark
,
ErrorMsg
::
TAG_DIRECTIVE_ARGS
);
throw
ParserException
(
t
oken
.
mark
,
ErrorMsg
::
TAG_DIRECTIVE_ARGS
);
std
::
string
handle
=
pToken
->
params
[
0
],
prefix
=
pToken
->
params
[
1
];
const
std
::
string
&
handle
=
token
.
params
[
0
];
m_state
.
tags
[
handle
]
=
prefix
;
const
std
::
string
&
prefix
=
token
.
params
[
1
];
if
(
m_pState
->
tags
.
find
(
handle
)
!=
m_pState
->
tags
.
end
())
throw
ParserException
(
token
.
mark
,
ErrorMsg
::
REPEATED_TAG_DIRECTIVE
);
m_pState
->
tags
[
handle
]
=
prefix
;
}
}
void
Parser
::
PrintTokens
(
std
::
ostream
&
out
)
void
Parser
::
PrintTokens
(
std
::
ostream
&
out
)
...
...
src/parserstate.cpp
View file @
a372bfdc
...
@@ -2,23 +2,22 @@
...
@@ -2,23 +2,22 @@
namespace
YAML
namespace
YAML
{
{
void
ParserState
::
Reset
()
ParserState
::
ParserState
()
{
{
// version
// version
version
.
isDefault
=
true
;
version
.
major
=
1
;
version
.
major
=
1
;
version
.
minor
=
2
;
version
.
minor
=
2
;
// and tags
tags
.
clear
();
tags
[
"!"
]
=
"!"
;
tags
[
"!!"
]
=
"tag:yaml.org,2002:"
;
}
}
std
::
string
ParserState
::
TranslateTag
(
const
std
::
string
&
handle
)
const
const
std
::
string
ParserState
::
TranslateTag
Handle
(
const
std
::
string
&
handle
)
const
{
{
std
::
map
<
std
::
string
,
std
::
string
>::
const_iterator
it
=
tags
.
find
(
handle
);
std
::
map
<
std
::
string
,
std
::
string
>::
const_iterator
it
=
tags
.
find
(
handle
);
if
(
it
==
tags
.
end
())
if
(
it
==
tags
.
end
())
{
if
(
handle
==
"!!"
)
return
"tag:yaml.org,2002:"
;
return
handle
;
return
handle
;
}
return
it
->
second
;
return
it
->
second
;
}
}
...
...
include
/parserstate.h
→
src
/parserstate.h
View file @
a372bfdc
...
@@ -10,16 +10,17 @@
...
@@ -10,16 +10,17 @@
namespace
YAML
namespace
YAML
{
{
struct
Version
{
struct
Version
{
bool
isDefault
;
int
major
,
minor
;
int
major
,
minor
;
};
};
struct
ParserState
struct
ParserState
{
{
ParserState
();
const
std
::
string
TranslateTagHandle
(
const
std
::
string
&
handle
)
const
;
Version
version
;
Version
version
;
std
::
map
<
std
::
string
,
std
::
string
>
tags
;
std
::
map
<
std
::
string
,
std
::
string
>
tags
;
void
Reset
();
std
::
string
TranslateTag
(
const
std
::
string
&
handle
)
const
;
};
};
}
}
...
...
src/regex.h
View file @
a372bfdc
...
@@ -37,12 +37,12 @@ namespace YAML
...
@@ -37,12 +37,12 @@ namespace YAML
int
Match
(
const
std
::
string
&
str
)
const
;
int
Match
(
const
std
::
string
&
str
)
const
;
int
Match
(
const
Stream
&
in
)
const
;
int
Match
(
const
Stream
&
in
)
const
;
template
<
typename
Source
>
int
Match
(
const
Source
&
source
)
const
;
private:
private:
RegEx
(
REGEX_OP
op
);
RegEx
(
REGEX_OP
op
);
template
<
typename
Source
>
bool
IsValidSource
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
bool
IsValidSource
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
Match
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchUnchecked
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchUnchecked
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpEmpty
(
const
Source
&
source
)
const
;
template
<
typename
Source
>
int
MatchOpEmpty
(
const
Source
&
source
)
const
;
...
...
src/scanner.cpp
View file @
a372bfdc
...
@@ -3,6 +3,7 @@
...
@@ -3,6 +3,7 @@
#include "exceptions.h"
#include "exceptions.h"
#include "exp.h"
#include "exp.h"
#include <cassert>
#include <cassert>
#include <memory>
namespace
YAML
namespace
YAML
{
{
...
@@ -13,6 +14,9 @@ namespace YAML
...
@@ -13,6 +14,9 @@ namespace YAML
Scanner
::~
Scanner
()
Scanner
::~
Scanner
()
{
{
for
(
unsigned
i
=
0
;
i
<
m_indentRefs
.
size
();
i
++
)
delete
m_indentRefs
[
i
];
m_indentRefs
.
clear
();
}
}
// empty
// empty
...
@@ -228,7 +232,9 @@ namespace YAML
...
@@ -228,7 +232,9 @@ namespace YAML
{
{
m_startedStream
=
true
;
m_startedStream
=
true
;
m_simpleKeyAllowed
=
true
;
m_simpleKeyAllowed
=
true
;
m_indents
.
push
(
IndentMarker
(
-
1
,
IndentMarker
::
NONE
));
IndentMarker
*
pIndent
=
new
IndentMarker
(
-
1
,
IndentMarker
::
NONE
);
m_indentRefs
.
push_back
(
pIndent
);
m_indents
.
push
(
pIndent
);
m_anchors
.
clear
();
m_anchors
.
clear
();
}
}
...
@@ -257,8 +263,9 @@ namespace YAML
...
@@ -257,8 +263,9 @@ namespace YAML
if
(
InFlowContext
())
if
(
InFlowContext
())
return
0
;
return
0
;
IndentMarker
indent
(
column
,
type
);
std
::
auto_ptr
<
IndentMarker
>
pIndent
(
new
IndentMarker
(
column
,
type
));
const
IndentMarker
&
lastIndent
=
m_indents
.
top
();
IndentMarker
&
indent
=
*
pIndent
;
const
IndentMarker
&
lastIndent
=
*
m_indents
.
top
();
// is this actually an indentation?
// is this actually an indentation?
if
(
indent
.
column
<
lastIndent
.
column
)
if
(
indent
.
column
<
lastIndent
.
column
)
...
@@ -276,13 +283,15 @@ namespace YAML
...
@@ -276,13 +283,15 @@ namespace YAML
indent
.
pStartToken
=
&
m_tokens
.
back
();
indent
.
pStartToken
=
&
m_tokens
.
back
();
// and then the indent
// and then the indent
m_indents
.
push
(
indent
);
m_indents
.
push
(
&
indent
);
return
&
m_indents
.
top
();
m_indentRefs
.
push_back
(
pIndent
.
release
());
return
m_indentRefs
.
back
();
}
}
// PopIndentToHere
// PopIndentToHere
// . Pops indentations off the stack until we reach the current indentation level,
// . Pops indentations off the stack until we reach the current indentation level,
// and enqueues the proper token each time.
// and enqueues the proper token each time.
// . Then pops all invalid indentations off.
void
Scanner
::
PopIndentToHere
()
void
Scanner
::
PopIndentToHere
()
{
{
// are we in flow?
// are we in flow?
...
@@ -291,7 +300,7 @@ namespace YAML
...
@@ -291,7 +300,7 @@ namespace YAML
// now pop away
// now pop away
while
(
!
m_indents
.
empty
())
{
while
(
!
m_indents
.
empty
())
{
const
IndentMarker
&
indent
=
m_indents
.
top
();
const
IndentMarker
&
indent
=
*
m_indents
.
top
();
if
(
indent
.
column
<
INPUT
.
column
())
if
(
indent
.
column
<
INPUT
.
column
())
break
;
break
;
if
(
indent
.
column
==
INPUT
.
column
()
&&
!
(
indent
.
type
==
IndentMarker
::
SEQ
&&
!
Exp
::
BlockEntry
.
Matches
(
INPUT
)))
if
(
indent
.
column
==
INPUT
.
column
()
&&
!
(
indent
.
type
==
IndentMarker
::
SEQ
&&
!
Exp
::
BlockEntry
.
Matches
(
INPUT
)))
...
@@ -299,6 +308,9 @@ namespace YAML
...
@@ -299,6 +308,9 @@ namespace YAML
PopIndent
();
PopIndent
();
}
}
while
(
!
m_indents
.
empty
()
&&
m_indents
.
top
()
->
status
==
IndentMarker
::
INVALID
)
PopIndent
();
}
}
// PopAllIndents
// PopAllIndents
...
@@ -312,7 +324,7 @@ namespace YAML
...
@@ -312,7 +324,7 @@ namespace YAML
// now pop away
// now pop away
while
(
!
m_indents
.
empty
())
{
while
(
!
m_indents
.
empty
())
{
const
IndentMarker
&
indent
=
m_indents
.
top
();
const
IndentMarker
&
indent
=
*
m_indents
.
top
();
if
(
indent
.
type
==
IndentMarker
::
NONE
)
if
(
indent
.
type
==
IndentMarker
::
NONE
)
break
;
break
;
...
@@ -324,17 +336,17 @@ namespace YAML
...
@@ -324,17 +336,17 @@ namespace YAML
// . Pops a single indent, pushing the proper token
// . Pops a single indent, pushing the proper token
void
Scanner
::
PopIndent
()
void
Scanner
::
PopIndent
()
{
{
IndentMarker
indent
=
m_indents
.
top
();
const
IndentMarker
&
indent
=
*
m_indents
.
top
();
IndentMarker
::
INDENT_TYPE
type
=
indent
.
type
;
m_indents
.
pop
();
m_indents
.
pop
();
if
(
!
indent
.
isValid
)
{
if
(
indent
.
status
!=
IndentMarker
::
VALID
)
{
InvalidateSimpleKey
();
InvalidateSimpleKey
();
return
;
return
;
}
}
if
(
type
==
IndentMarker
::
SEQ
)
if
(
indent
.
type
==
IndentMarker
::
SEQ
)
m_tokens
.
push
(
Token
(
Token
::
BLOCK_SEQ_END
,
INPUT
.
mark
()));
m_tokens
.
push
(
Token
(
Token
::
BLOCK_SEQ_END
,
INPUT
.
mark
()));
else
if
(
type
==
IndentMarker
::
MAP
)
else
if
(
indent
.
type
==
IndentMarker
::
MAP
)
m_tokens
.
push
(
Token
(
Token
::
BLOCK_MAP_END
,
INPUT
.
mark
()));
m_tokens
.
push
(
Token
(
Token
::
BLOCK_MAP_END
,
INPUT
.
mark
()));
}
}
...
@@ -343,7 +355,7 @@ namespace YAML
...
@@ -343,7 +355,7 @@ namespace YAML
{
{
if
(
m_indents
.
empty
())
if
(
m_indents
.
empty
())
return
0
;
return
0
;
return
m_indents
.
top
()
.
column
;
return
m_indents
.
top
()
->
column
;
}
}
// Save
// Save
...
...
src/scanner.h
View file @
a372bfdc
...
@@ -36,11 +36,12 @@ namespace YAML
...
@@ -36,11 +36,12 @@ namespace YAML
private:
private:
struct
IndentMarker
{
struct
IndentMarker
{
enum
INDENT_TYPE
{
MAP
,
SEQ
,
NONE
};
enum
INDENT_TYPE
{
MAP
,
SEQ
,
NONE
};
IndentMarker
(
int
column_
,
INDENT_TYPE
type_
)
:
column
(
column_
),
type
(
type_
),
isValid
(
true
),
pStartToken
(
0
)
{}
enum
STATUS
{
VALID
,
INVALID
,
UNKNOWN
};
IndentMarker
(
int
column_
,
INDENT_TYPE
type_
)
:
column
(
column_
),
type
(
type_
),
status
(
VALID
),
pStartToken
(
0
)
{}
int
column
;
int
column
;
INDENT_TYPE
type
;
INDENT_TYPE
type
;
bool
isValid
;
STATUS
status
;
Token
*
pStartToken
;
Token
*
pStartToken
;
};
};
...
@@ -118,10 +119,12 @@ namespace YAML
...
@@ -118,10 +119,12 @@ namespace YAML
bool
m_startedStream
,
m_endedStream
;
bool
m_startedStream
,
m_endedStream
;
bool
m_simpleKeyAllowed
;
bool
m_simpleKeyAllowed
;
std
::
stack
<
SimpleKey
>
m_simpleKeys
;
std
::
stack
<
SimpleKey
>
m_simpleKeys
;
std
::
stack
<
IndentMarker
>
m_indents
;
std
::
stack
<
IndentMarker
*>
m_indents
;
std
::
vector
<
IndentMarker
*>
m_indentRefs
;
// for "garbage collection"
std
::
stack
<
FLOW_MARKER
>
m_flows
;
std
::
stack
<
FLOW_MARKER
>
m_flows
;
std
::
map
<
std
::
string
,
const
Node
*>
m_anchors
;
std
::
map
<
std
::
string
,
const
Node
*>
m_anchors
;
};
};
}
}
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif // SCANNER_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scanscalar.h
View file @
a372bfdc
...
@@ -40,3 +40,4 @@ namespace YAML
...
@@ -40,3 +40,4 @@ namespace YAML
}
}
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#endif // SCANSCALAR_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scantag.cpp
0 → 100644
View file @
a372bfdc
#include "scanner.h"
#include "regex.h"
#include "exp.h"
#include "exceptions.h"
namespace
YAML
{
const
std
::
string
ScanVerbatimTag
(
Stream
&
INPUT
)
{
std
::
string
tag
;
// eat the start character
INPUT
.
get
();
while
(
INPUT
)
{
if
(
INPUT
.
peek
()
==
Keys
::
VerbatimTagEnd
)
{
// eat the end character
INPUT
.
get
();
return
tag
;
}
int
n
=
Exp
::
URI
.
Match
(
INPUT
);
if
(
n
<=
0
)
break
;
tag
+=
INPUT
.
get
(
n
);
}
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
END_OF_VERBATIM_TAG
);
}
const
std
::
string
ScanTagHandle
(
Stream
&
INPUT
,
bool
&
canBeHandle
)
{
std
::
string
tag
;
canBeHandle
=
true
;
Mark
firstNonWordChar
;
while
(
INPUT
)
{
if
(
INPUT
.
peek
()
==
Keys
::
Tag
)
{
if
(
!
canBeHandle
)
throw
ParserException
(
firstNonWordChar
,
ErrorMsg
::
CHAR_IN_TAG_HANDLE
);
break
;
}
int
n
=
0
;
if
(
canBeHandle
)
{
n
=
Exp
::
Word
.
Match
(
INPUT
);
if
(
n
<=
0
)
{
canBeHandle
=
false
;
firstNonWordChar
=
INPUT
.
mark
();
}
}
if
(
!
canBeHandle
)
n
=
Exp
::
Tag
.
Match
(
INPUT
);
if
(
n
<=
0
)
break
;
tag
+=
INPUT
.
get
(
n
);
}
return
tag
;
}
const
std
::
string
ScanTagSuffix
(
Stream
&
INPUT
)
{
std
::
string
tag
;
while
(
INPUT
)
{
int
n
=
Exp
::
Tag
.
Match
(
INPUT
);
if
(
n
<=
0
)
break
;
tag
+=
INPUT
.
get
(
n
);
}
if
(
tag
.
empty
())
throw
ParserException
(
INPUT
.
mark
(),
ErrorMsg
::
TAG_WITH_NO_SUFFIX
);
return
tag
;
}
}
src/scantag.h
0 → 100644
View file @
a372bfdc
#pragma once
#ifndef SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#define SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
#include <string>
#include "stream.h"
namespace
YAML
{
const
std
::
string
ScanVerbatimTag
(
Stream
&
INPUT
);
const
std
::
string
ScanTagHandle
(
Stream
&
INPUT
,
bool
&
canBeHandle
);
const
std
::
string
ScanTagSuffix
(
Stream
&
INPUT
);
}
#endif // SCANTAG_H_62B23520_7C8E_11DE_8A39_0800200C9A66
src/scantoken.cpp
View file @
a372bfdc
...
@@ -3,6 +3,8 @@
...
@@ -3,6 +3,8 @@
#include "exceptions.h"
#include "exceptions.h"
#include "exp.h"
#include "exp.h"
#include "scanscalar.h"
#include "scanscalar.h"
#include "scantag.h"
#include "tag.h"
#include <sstream>
#include <sstream>
namespace
YAML
namespace
YAML
...
@@ -24,12 +26,12 @@ namespace YAML
...
@@ -24,12 +26,12 @@ namespace YAML
m_simpleKeyAllowed
=
false
;
m_simpleKeyAllowed
=
false
;
// store pos and eat indicator
// store pos and eat indicator
Mark
mark
=
INPUT
.
mark
();
Token
token
(
Token
::
DIRECTIVE
,
INPUT
.
mark
()
)
;
INPUT
.
eat
(
1
);
INPUT
.
eat
(
1
);
// read name
// read name
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
nam
e
+=
INPUT
.
get
();
token
.
valu
e
+=
INPUT
.
get
();
// read parameters
// read parameters
while
(
1
)
{
while
(
1
)
{
...
@@ -46,12 +48,9 @@ namespace YAML
...
@@ -46,12 +48,9 @@ namespace YAML
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
param
+=
INPUT
.
get
();
param
+=
INPUT
.
get
();
params
.
push_back
(
param
);
token
.
params
.
push_back
(
param
);
}
}
Token
token
(
Token
::
DIRECTIVE
,
mark
);
token
.
value
=
name
;
token
.
params
=
params
;
m_tokens
.
push
(
token
);
m_tokens
.
push
(
token
);
}
}
...
@@ -242,37 +241,34 @@ namespace YAML
...
@@ -242,37 +241,34 @@ namespace YAML
// Tag
// Tag
void
Scanner
::
ScanTag
()
void
Scanner
::
ScanTag
()
{
{
std
::
string
handle
,
suffix
;
// insert a potential simple key
// insert a potential simple key
InsertPotentialSimpleKey
();
InsertPotentialSimpleKey
();
m_simpleKeyAllowed
=
false
;
m_simpleKeyAllowed
=
false
;
// eat the indicator
Token
token
(
Token
::
TAG
,
INPUT
.
mark
());
Mark
mark
=
INPUT
.
mark
();
handle
+=
INPUT
.
get
();
// read the handle
while
(
INPUT
&&
INPUT
.
peek
()
!=
Keys
::
Tag
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
handle
+=
INPUT
.
get
();
// is there a suffix?
// eat the indicator
if
(
INPUT
.
peek
()
==
Keys
::
Tag
)
{
INPUT
.
get
();
// eat the indicator
handle
+=
INPUT
.
get
();
if
(
INPUT
&&
INPUT
.
peek
()
==
Keys
::
VerbatimTagStart
){
std
::
string
tag
=
ScanVerbatimTag
(
INPUT
);
// then read it
token
.
value
=
tag
;
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
token
.
data
=
Tag
::
VERBATIM
;
suffix
+=
INPUT
.
get
();
}
else
{
}
else
{
// this is a bit weird: we keep just the '!' as the handle and move the rest to the suffix
bool
canBeHandle
;
suffix
=
handle
.
substr
(
1
);
token
.
value
=
ScanTagHandle
(
INPUT
,
canBeHandle
);
handle
=
"!"
;
token
.
data
=
(
token
.
value
.
empty
()
?
Tag
::
SECONDARY_HANDLE
:
Tag
::
PRIMARY_HANDLE
);
// is there a suffix?
if
(
canBeHandle
&&
INPUT
.
peek
()
==
Keys
::
Tag
)
{
// eat the indicator
INPUT
.
get
();
token
.
params
.
push_back
(
ScanTagSuffix
(
INPUT
));
token
.
data
=
Tag
::
NAMED_HANDLE
;
}
}
}
Token
token
(
Token
::
TAG
,
mark
);
token
.
value
=
handle
;
token
.
params
.
push_back
(
suffix
);
m_tokens
.
push
(
token
);
m_tokens
.
push
(
token
);
}
}
...
...
Prev
1
2
Next
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