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
8dfb5c0e
Commit
8dfb5c0e
authored
Jun 29, 2008
by
beder
Browse files
Refactored common scalar scanning code (from plain, quoted, and block) to one function.
parent
3c56fd49
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
305 additions
and
187 deletions
+305
-187
exp.cpp
exp.cpp
+8
-2
regex.cpp
regex.cpp
+41
-8
regex.h
regex.h
+7
-1
scanner.h
scanner.h
+2
-0
scanscalar.cpp
scanscalar.cpp
+243
-163
test.yaml
test.yaml
+4
-13
No files found.
exp.cpp
View file @
8dfb5c0e
...
@@ -62,7 +62,7 @@ namespace YAML
...
@@ -62,7 +62,7 @@ namespace YAML
}
}
// Escape
// Escape
// . Escapes the sequence starting 'in' (it must begin with a '\')
// . Escapes the sequence starting 'in' (it must begin with a '\'
or single quote
)
// and returns the result.
// and returns the result.
// . Fills 'length' with how many characters we ate.
// . Fills 'length' with how many characters we ate.
// . Throws if it's an unknown escape character.
// . Throws if it's an unknown escape character.
...
@@ -72,10 +72,16 @@ namespace YAML
...
@@ -72,10 +72,16 @@ namespace YAML
length
=
2
;
length
=
2
;
// eat slash
// eat slash
in
.
get
();
char
escape
=
in
.
get
();
// switch on escape character
// switch on escape character
char
ch
=
in
.
get
();
char
ch
=
in
.
get
();
// first do single quote, since it's easier
if
(
escape
==
'\''
&&
ch
==
'\''
)
return
"
\'
"
;
// now do the slash (we're not gonna check if it's a slash - you better pass one!)
switch
(
ch
)
{
switch
(
ch
)
{
case
'0'
:
return
"
\0
"
;
case
'0'
:
return
"
\0
"
;
case
'a'
:
return
"
\x07
"
;
case
'a'
:
return
"
\x07
"
;
...
...
regex.cpp
View file @
8dfb5c0e
...
@@ -53,6 +53,7 @@ namespace YAML
...
@@ -53,6 +53,7 @@ namespace YAML
case
REGEX_MATCH
:
m_pOp
=
new
MatchOperator
;
break
;
case
REGEX_MATCH
:
m_pOp
=
new
MatchOperator
;
break
;
case
REGEX_RANGE
:
m_pOp
=
new
RangeOperator
;
break
;
case
REGEX_RANGE
:
m_pOp
=
new
RangeOperator
;
break
;
case
REGEX_OR
:
m_pOp
=
new
OrOperator
;
break
;
case
REGEX_OR
:
m_pOp
=
new
OrOperator
;
break
;
case
REGEX_AND
:
m_pOp
=
new
AndOperator
;
break
;
case
REGEX_NOT
:
m_pOp
=
new
NotOperator
;
break
;
case
REGEX_NOT
:
m_pOp
=
new
NotOperator
;
break
;
case
REGEX_SEQ
:
m_pOp
=
new
SeqOperator
;
break
;
case
REGEX_SEQ
:
m_pOp
=
new
SeqOperator
;
break
;
}
}
...
@@ -80,19 +81,13 @@ namespace YAML
...
@@ -80,19 +81,13 @@ namespace YAML
// . Returns the number of characters matched.
// . Returns the number of characters matched.
// . Returns -1 if no characters were matched (the reason for
// . Returns -1 if no characters were matched (the reason for
// not returning zero is that we may have an empty regex
// not returning zero is that we may have an empty regex
// which SHOULD be considered successfully matching nothing,
// which is ALWAYS successful at matching zero characters).
// but that of course matches zero characters).
int
RegEx
::
Match
(
const
std
::
string
&
str
)
const
int
RegEx
::
Match
(
const
std
::
string
&
str
)
const
{
{
if
(
!
m_pOp
)
if
(
!
m_pOp
)
return
-
1
;
return
0
;
return
m_pOp
->
Match
(
str
,
*
this
);
return
m_pOp
->
Match
(
str
,
*
this
);
//case REGEX_EMPTY:
// if(str.empty())
// return 0;
// return -1;
}
}
// Match
// Match
...
@@ -131,6 +126,14 @@ namespace YAML
...
@@ -131,6 +126,14 @@ namespace YAML
return
ret
;
return
ret
;
}
}
RegEx
operator
&&
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
RegEx
ret
(
REGEX_AND
);
ret
.
m_params
.
push_back
(
ex1
);
ret
.
m_params
.
push_back
(
ex2
);
return
ret
;
}
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
)
{
{
RegEx
ret
(
REGEX_SEQ
);
RegEx
ret
(
REGEX_SEQ
);
...
@@ -194,6 +197,36 @@ namespace YAML
...
@@ -194,6 +197,36 @@ namespace YAML
return
-
1
;
return
-
1
;
}
}
// AndOperator
// Note: 'AND' is a little funny, since we may be required to match things
// of different lengths. If we find a match, we return the length of
// the FIRST entry on the list.
int
RegEx
::
AndOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
int
first
=
-
1
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
str
);
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
int
RegEx
::
AndOperator
::
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
{
int
first
=
-
1
;
for
(
unsigned
i
=
0
;
i
<
regex
.
m_params
.
size
();
i
++
)
{
int
n
=
regex
.
m_params
[
i
].
Match
(
in
);
if
(
n
==
-
1
)
return
-
1
;
if
(
i
==
0
)
first
=
n
;
}
return
first
;
}
// NotOperator
// NotOperator
int
RegEx
::
NotOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
int
RegEx
::
NotOperator
::
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
{
{
...
...
regex.h
View file @
8dfb5c0e
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
namespace
YAML
namespace
YAML
{
{
enum
REGEX_OP
{
REGEX_EMPTY
,
REGEX_MATCH
,
REGEX_RANGE
,
REGEX_OR
,
REGEX_NOT
,
REGEX_SEQ
};
enum
REGEX_OP
{
REGEX_EMPTY
,
REGEX_MATCH
,
REGEX_RANGE
,
REGEX_OR
,
REGEX_AND
,
REGEX_NOT
,
REGEX_SEQ
};
// simplified regular expressions
// simplified regular expressions
// . Only straightforward matches (no repeated characters)
// . Only straightforward matches (no repeated characters)
...
@@ -35,6 +35,11 @@ namespace YAML
...
@@ -35,6 +35,11 @@ namespace YAML
virtual
int
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
;
virtual
int
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
;
};
};
struct
AndOperator
:
public
Operator
{
virtual
int
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
;
virtual
int
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
;
};
struct
NotOperator
:
public
Operator
{
struct
NotOperator
:
public
Operator
{
virtual
int
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
;
virtual
int
Match
(
const
std
::
string
&
str
,
const
RegEx
&
regex
)
const
;
virtual
int
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
;
virtual
int
Match
(
std
::
istream
&
in
,
const
RegEx
&
regex
)
const
;
...
@@ -63,6 +68,7 @@ namespace YAML
...
@@ -63,6 +68,7 @@ namespace YAML
friend
RegEx
operator
!
(
const
RegEx
&
ex
);
friend
RegEx
operator
!
(
const
RegEx
&
ex
);
friend
RegEx
operator
||
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
||
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
&&
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
friend
RegEx
operator
+
(
const
RegEx
&
ex1
,
const
RegEx
&
ex2
);
private:
private:
...
...
scanner.h
View file @
8dfb5c0e
...
@@ -5,6 +5,7 @@
...
@@ -5,6 +5,7 @@
#include <queue>
#include <queue>
#include <stack>
#include <stack>
#include <set>
#include <set>
#include "regex.h"
namespace
YAML
namespace
YAML
{
{
...
@@ -44,6 +45,7 @@ namespace YAML
...
@@ -44,6 +45,7 @@ namespace YAML
bool
IsPlainScalar
();
bool
IsPlainScalar
();
void
GetBlockIndentation
(
int
&
indent
,
std
::
string
&
breaks
);
void
GetBlockIndentation
(
int
&
indent
,
std
::
string
&
breaks
);
std
::
string
ScanScalar
(
RegEx
end
,
bool
eatEnd
,
int
indent
,
char
escape
,
bool
fold
,
bool
eatLeadingWhitespace
,
bool
trimTrailingSpaces
,
int
chomp
);
struct
SimpleKey
{
struct
SimpleKey
{
SimpleKey
(
int
pos_
,
int
line_
,
int
column_
,
int
flowLevel_
);
SimpleKey
(
int
pos_
,
int
line_
,
int
column_
,
int
flowLevel_
);
...
...
scanscalar.cpp
View file @
8dfb5c0e
...
@@ -75,74 +75,77 @@ namespace YAML
...
@@ -75,74 +75,77 @@ namespace YAML
// and in-line whitespace (which is kept) separately.
// and in-line whitespace (which is kept) separately.
template
<
>
PlainScalarToken
*
Scanner
::
ScanToken
(
PlainScalarToken
*
pToken
)
template
<
>
PlainScalarToken
*
Scanner
::
ScanToken
(
PlainScalarToken
*
pToken
)
{
{
//// now eat and store the scalar
//std::string scalar;
//WhitespaceInfo info;
//while(INPUT) {
// // doc start/end tokens
// if(IsDocumentStart() || IsDocumentEnd())
// break;
// // comment
// if(Exp::Comment.Matches(INPUT))
// break;
// // first eat non-blanks
// while(INPUT && !Exp::BlankOrBreak.Matches(INPUT)) {
// // illegal colon in flow context
// if(m_flowLevel > 0 && Exp::IllegalColonInScalar.Matches(INPUT))
// throw IllegalScalar();
// // characters that might end the scalar
// if(m_flowLevel > 0 && Exp::EndScalarInFlow.Matches(INPUT))
// break;
// if(m_flowLevel == 0 && Exp::EndScalar.Matches(INPUT))
// break;
// // finally, read the character!
// scalar += GetChar();
// }
// // did we hit a non-blank character that ended us?
// if(!Exp::BlankOrBreak.Matches(INPUT))
// break;
// // now eat blanks
// while(INPUT && Exp::BlankOrBreak.Matches(INPUT)) {
// if(Exp::Blank.Matches(INPUT)) {
// // can't use tabs as indentation! only spaces!
// if(INPUT.peek() == '\t' && info.leadingBlanks && m_column <= m_indents.top())
// throw IllegalTabInScalar();
// info.AddBlank(GetChar());
// } else {
// // we know it's a line break; see how many characters to read
// int n = Exp::Break.Match(INPUT);
// std::string line = GetChar(n);
// info.AddBreak(line);
// // and we can't continue a simple key to the next line
// ValidateSimpleKey();
// }
// }
// // break if we're below the indentation level
// if(m_flowLevel == 0 && m_column <= m_indents.top())
// break;
// // finally join whitespace
// scalar += info.Join();
//}
RegEx
end
=
(
m_flowLevel
>
0
?
Exp
::
EndScalarInFlow
:
Exp
::
EndScalar
)
||
(
RegEx
(
' '
)
+
Exp
::
Comment
);
int
indent
=
(
m_flowLevel
>
0
?
0
:
m_indents
.
top
()
+
1
);
// insert a potential simple key
// insert a potential simple key
if
(
m_simpleKeyAllowed
)
if
(
m_simpleKeyAllowed
)
InsertSimpleKey
();
InsertSimpleKey
();
m_simpleKeyAllowed
=
false
;
// now eat and store the scalar
std
::
string
scalar
;
WhitespaceInfo
info
;
while
(
INPUT
)
{
pToken
->
value
=
ScanScalar
(
end
,
false
,
indent
,
0
,
true
,
true
,
true
,
0
);
// doc start/end tokens
if
(
IsDocumentStart
()
||
IsDocumentEnd
())
break
;
// comment
if
(
Exp
::
Comment
.
Matches
(
INPUT
))
break
;
// first eat non-blanks
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
{
// illegal colon in flow context
if
(
m_flowLevel
>
0
&&
Exp
::
IllegalColonInScalar
.
Matches
(
INPUT
))
throw
IllegalScalar
();
// characters that might end the scalar
if
(
m_flowLevel
>
0
&&
Exp
::
EndScalarInFlow
.
Matches
(
INPUT
))
break
;
if
(
m_flowLevel
==
0
&&
Exp
::
EndScalar
.
Matches
(
INPUT
))
break
;
// finally, read the character!
scalar
+=
GetChar
();
}
// did we hit a non-blank character that ended us?
m_simpleKeyAllowed
=
false
;
if
(
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
if
(
true
/*info.leadingBlanks*/
)
break
;
// now eat blanks
while
(
INPUT
&&
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
{
if
(
Exp
::
Blank
.
Matches
(
INPUT
))
{
// can't use tabs as indentation! only spaces!
if
(
INPUT
.
peek
()
==
'\t'
&&
info
.
leadingBlanks
&&
m_column
<=
m_indents
.
top
())
throw
IllegalTabInScalar
();
info
.
AddBlank
(
GetChar
());
}
else
{
// we know it's a line break; see how many characters to read
int
n
=
Exp
::
Break
.
Match
(
INPUT
);
std
::
string
line
=
GetChar
(
n
);
info
.
AddBreak
(
line
);
// and we can't continue a simple key to the next line
ValidateSimpleKey
();
}
}
// break if we're below the indentation level
if
(
m_flowLevel
==
0
&&
m_column
<=
m_indents
.
top
())
break
;
// finally join whitespace
scalar
+=
info
.
Join
();
}
// now modify our token
pToken
->
value
=
scalar
;
if
(
info
.
leadingBlanks
)
m_simpleKeyAllowed
=
true
;
m_simpleKeyAllowed
=
true
;
return
pToken
;
return
pToken
;
...
@@ -151,91 +154,92 @@ namespace YAML
...
@@ -151,91 +154,92 @@ namespace YAML
// QuotedScalarToken
// QuotedScalarToken
template
<
>
QuotedScalarToken
*
Scanner
::
ScanToken
(
QuotedScalarToken
*
pToken
)
template
<
>
QuotedScalarToken
*
Scanner
::
ScanToken
(
QuotedScalarToken
*
pToken
)
{
{
// insert a potential simple key
//// now eat and store the scalar
if
(
m_simpleKeyAllowed
)
//std::string scalar;
InsertSimpleKey
();
//WhitespaceInfo info;
m_simpleKeyAllowed
=
false
;
//while(INPUT) {
// if(IsDocumentStart() || IsDocumentEnd())
// throw DocIndicatorInQuote();
// if(INPUT.peek() == EOF)
// throw EOFInQuote();
// // first eat non-blanks
// while(INPUT && !Exp::BlankOrBreak.Matches(INPUT)) {
// // escaped single quote?
// if(pToken->single && Exp::EscSingleQuote.Matches(INPUT)) {
// int n = Exp::EscSingleQuote.Match(INPUT);
// scalar += GetChar(n);
// continue;
// }
// // is the quote ending?
// if(INPUT.peek() == quote)
// break;
// // escaped newline?
// if(Exp::EscBreak.Matches(INPUT))
// break;
// // other escape sequence
// if(INPUT.peek() == '\\') {
// int length = 0;
// scalar += Exp::Escape(INPUT, length);
// m_column += length;
// continue;
// }
// // and finally, just add the damn character
// scalar += GetChar();
// }
// // is the quote ending?
// if(INPUT.peek() == quote) {
// // eat and go
// GetChar();
// break;
// }
// // now we eat blanks
// while(Exp::BlankOrBreak.Matches(INPUT)) {
// if(Exp::Blank.Matches(INPUT)) {
// info.AddBlank(GetChar());
// } else {
// // we know it's a line break; see how many characters to read
// int n = Exp::Break.Match(INPUT);
// std::string line = GetChar(n);
// info.AddBreak(line);
// // and we can't continue a simple key to the next line
// ValidateSimpleKey();
// }
// }
// // and finally join the whitespace
// scalar += info.Join();
//}
// eat single or double quote
// eat single or double quote
char
quote
=
GetChar
();
char
quote
=
GetChar
();
pToken
->
single
=
(
quote
==
'\''
);
pToken
->
single
=
(
quote
==
'\''
);
// now eat and store the scalar
RegEx
end
=
(
pToken
->
single
?
RegEx
(
quote
)
&&
!
Exp
::
EscSingleQuote
:
RegEx
(
quote
));
std
::
string
scalar
;
char
escape
=
(
pToken
->
single
?
'\''
:
'\\'
);
WhitespaceInfo
info
;
while
(
INPUT
)
{
if
(
IsDocumentStart
()
||
IsDocumentEnd
())
throw
DocIndicatorInQuote
();
if
(
INPUT
.
peek
()
==
EOF
)
// insert a potential simple key
throw
EOFInQuote
();
if
(
m_simpleKeyAllowed
)
InsertSimpleKey
();
// first eat non-blanks
while
(
INPUT
&&
!
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
{
// escaped single quote?
if
(
pToken
->
single
&&
Exp
::
EscSingleQuote
.
Matches
(
INPUT
))
{
int
n
=
Exp
::
EscSingleQuote
.
Match
(
INPUT
);
scalar
+=
GetChar
(
n
);
continue
;
}
// is the quote ending?
if
(
INPUT
.
peek
()
==
quote
)
break
;
// escaped newline?
if
(
Exp
::
EscBreak
.
Matches
(
INPUT
))
break
;
// other escape sequence
if
(
INPUT
.
peek
()
==
'\\'
)
{
int
length
=
0
;
scalar
+=
Exp
::
Escape
(
INPUT
,
length
);
m_column
+=
length
;
continue
;
}
// and finally, just add the damn character
scalar
+=
GetChar
();
}
// is the quote ending?
if
(
INPUT
.
peek
()
==
quote
)
{
// eat and go
GetChar
();
break
;
}
// now we eat blanks
while
(
Exp
::
BlankOrBreak
.
Matches
(
INPUT
))
{
if
(
Exp
::
Blank
.
Matches
(
INPUT
))
{
info
.
AddBlank
(
GetChar
());
}
else
{
// we know it's a line break; see how many characters to read
int
n
=
Exp
::
Break
.
Match
(
INPUT
);
std
::
string
line
=
GetChar
(
n
);
info
.
AddBreak
(
line
);
// and we can't continue a simple key to the next line
ValidateSimpleKey
();
}
}
// and finally join the whitespace
pToken
->
value
=
ScanScalar
(
end
,
true
,
0
,
escape
,
true
,
true
,
false
,
0
);
scalar
+=
info
.
Join
();
m_simpleKeyAllowed
=
false
;
}
pToken
->
value
=
scalar
;
return
pToken
;
return
pToken
;
}
}
// BlockScalarToken
// BlockScalarToken
template
<
>
BlockScalarToken
*
Scanner
::
ScanToken
(
BlockScalarToken
*
pToken
)
template
<
>
BlockScalarToken
*
Scanner
::
ScanToken
(
BlockScalarToken
*
pToken
)
{
{
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
m_simpleKeyAllowed
=
true
;
WhitespaceInfo
info
;
WhitespaceInfo
info
;
// eat block indicator ('|' or '>')
// eat block indicator ('|' or '>')
...
@@ -268,37 +272,13 @@ namespace YAML
...
@@ -268,37 +272,13 @@ namespace YAML
if
(
info
.
increment
&&
m_indents
.
top
()
>=
0
)
if
(
info
.
increment
&&
m_indents
.
top
()
>=
0
)
indent
+=
m_indents
.
top
();
indent
+=
m_indents
.
top
();
// finally, grab that scalar
std
::
string
scalar
;
while
(
INPUT
)
{
// initialize indentation
GetBlockIndentation
(
indent
,
info
.
trailingBreaks
);
GetBlockIndentation
(
indent
,
info
.
trailingBreaks
);
// are we done with this guy (i.e. at a lower indentation?)
bool
eatLeadingWhitespace
=
false
;
if
(
m_column
!=
indent
)
pToken
->
value
=
ScanScalar
(
RegEx
(),
false
,
indent
,
0
,
info
.
fold
,
eatLeadingWhitespace
,
false
,
info
.
chomp
);
break
;
bool
trailingBlank
=
Exp
::
Blank
.
Matches
(
INPUT
);
scalar
+=
info
.
Join
();
bool
leadingBlank
=
Exp
::
Blank
.
Matches
(
INPUT
);
// now eat and save the line
while
(
INPUT
.
peek
()
!=
EOF
&&
!
Exp
::
Break
.
Matches
(
INPUT
))
scalar
+=
GetChar
();
// we know it's a line break; see how many characters to read
int
n
=
Exp
::
Break
.
Match
(
INPUT
);
std
::
string
line
=
GetChar
(
n
);
info
.
AddBreak
(
line
);
}
// one last whitespace join (with chompers this time)
scalar
+=
info
.
Join
(
true
);
// finally set the scalar
pToken
->
value
=
scalar
;
// simple keys always ok after block scalars (since we're gonna start a new line anyways)
m_simpleKeyAllowed
=
true
;
return
pToken
;
return
pToken
;
}
}
...
@@ -340,4 +320,104 @@ namespace YAML
...
@@ -340,4 +320,104 @@ namespace YAML
indent
=
1
;
indent
=
1
;
}
}
}
}
// ScanScalar
std
::
string
Scanner
::
ScanScalar
(
RegEx
end
,
bool
eatEnd
,
int
indent
,
char
escape
,
bool
fold
,
bool
eatLeadingWhitespace
,
bool
trimTrailingSpaces
,
int
chomp
)
{
bool
emptyLine
=
false
,
moreIndented
=
false
;
std
::
string
scalar
;
while
(
INPUT
)
{
// ********************************
// Phase #1: scan until line ending
while
(
!
end
.
Matches
(
INPUT
)
&&
!
Exp
::
Break
.
Matches
(
INPUT
))
{
if
(
INPUT
.
peek
()
==
EOF
)
break
;
// escaped newline? (only if we're escaping on slash)
if
(
escape
==
'\\'
&&
Exp
::
EscBreak
.
Matches
(
INPUT
))
{
int
n
=
Exp
::
EscBreak
.
Match
(
INPUT
);
Eat
(
n
);
continue
;
}
// escape this?
if
(
INPUT
.
peek
()
==
escape
)
{
int
length
=
0
;
scalar
+=
Exp
::
Escape
(
INPUT
,
length
);
m_column
+=
length
;
continue
;
}
// otherwise, just add the damn character
scalar
+=
GetChar
();
}
// eof? if we're looking to eat something, then we throw
if
(
INPUT
.
peek
()
==
EOF
)
{
if
(
eatEnd
)
throw
EOFInQuote
();
break
;
}
// are we done via character match?
int
n
=
end
.
Match
(
INPUT
);
if
(
n
>=
0
)
{
if
(
eatEnd
)
Eat
(
n
);
break
;
}
// ********************************
// Phase #2: eat line ending
n
=
Exp
::
Break
.
Match
(
INPUT
);
Eat
(
n
);
// ********************************
// Phase #3: scan initial spaces
// first the required indentation
while
(
INPUT
.
peek
()
==
' '
&&
m_column
<
indent
)
Eat
(
1
);
// and then the rest of the whitespace
if
(
eatLeadingWhitespace
)
{
while
(
Exp
::
Blank
.
Matches
(
INPUT
))
Eat
(
1
);
}
// was this an empty line?
bool
nextEmptyLine
=
Exp
::
Break
.
Matches
(
INPUT
);
bool
nextMoreIndented
=
(
INPUT
.
peek
()
==
' '
);
if
(
fold
&&
!
emptyLine
&&
!
nextEmptyLine
&&
!
moreIndented
&&
!
nextMoreIndented
)
scalar
+=
" "
;
else
scalar
+=
"
\n
"
;
emptyLine
=
nextEmptyLine
;
moreIndented
=
nextMoreIndented
;
// are we done via indentation?
if
(
!
emptyLine
&&
m_column
<
indent
)
break
;
}
// post-processing
if
(
trimTrailingSpaces
)
{
unsigned
pos
=
scalar
.
find_last_not_of
(
' '
);
if
(
pos
<
scalar
.
size
())
scalar
.
erase
(
pos
+
1
);
}
if
(
chomp
<=
0
)
{
unsigned
pos
=
scalar
.
find_last_not_of
(
'\n'
);
if
(
chomp
==
0
&&
pos
+
1
<
scalar
.
size
())
scalar
.
erase
(
pos
+
2
);
else
if
(
chomp
==
-
1
&&
pos
<
scalar
.
size
())
scalar
.
erase
(
pos
+
1
);
}
return
scalar
;
}
}
}
test.yaml
View file @
8dfb5c0e
people
:
---
-
&jsb
-
"
quoted
scalar
that
contains
name
:
Jesse
---
age
:
23
the
document
start!"
-
&dab
\ No newline at end of file
name
:
'
Daniel'
age
:
25
-
&ncb
name
:
"
Naftali"
age
:
21
students
:
-
*jsb
-
*ncb
\ No newline at end of file
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