Commit da4614eb authored by Jesse Beder's avatar Jesse Beder
Browse files

Fixed flow folding, and made the separation slightly cleaner (but the whole...

Fixed flow folding, and made the separation slightly cleaner (but the whole scanscalar thing could use a major refactoring)
parent 4dcd222d
...@@ -19,7 +19,8 @@ namespace YAML ...@@ -19,7 +19,8 @@ namespace YAML
// and different places in the above flow. // and different places in the above flow.
std::string ScanScalar(Stream& INPUT, ScanScalarParams& params) std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
{ {
bool foundNonEmptyLine = false, pastOpeningBreak = false; bool foundNonEmptyLine = false;
bool pastOpeningBreak = (params.fold == FOLD_FLOW);
bool emptyLine = false, moreIndented = false; bool emptyLine = false, moreIndented = false;
int foldedNewlineCount = 0; int foldedNewlineCount = 0;
bool foldedNewlineStartedMoreIndented = false; bool foldedNewlineStartedMoreIndented = false;
...@@ -29,6 +30,8 @@ namespace YAML ...@@ -29,6 +30,8 @@ namespace YAML
while(INPUT) { while(INPUT) {
// ******************************** // ********************************
// Phase #1: scan until line ending // Phase #1: scan until line ending
std::size_t lastNonWhitespaceChar = scalar.size();
while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) { while(!params.end.Matches(INPUT) && !Exp::Break.Matches(INPUT)) {
if(!INPUT) if(!INPUT)
break; break;
...@@ -48,17 +51,22 @@ namespace YAML ...@@ -48,17 +51,22 @@ namespace YAML
if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) { if(params.escape == '\\' && Exp::EscBreak.Matches(INPUT)) {
int n = Exp::EscBreak.Match(INPUT); int n = Exp::EscBreak.Match(INPUT);
INPUT.eat(n); INPUT.eat(n);
lastNonWhitespaceChar = scalar.size();
continue; continue;
} }
// escape this? // escape this?
if(INPUT.peek() == params.escape) { if(INPUT.peek() == params.escape) {
scalar += Exp::Escape(INPUT); scalar += Exp::Escape(INPUT);
lastNonWhitespaceChar = scalar.size();
continue; continue;
} }
// otherwise, just add the damn character // otherwise, just add the damn character
scalar += INPUT.get(); char ch = INPUT.get();
scalar += ch;
if(ch != ' ' && ch != '\t')
lastNonWhitespaceChar = scalar.size();
} }
// eof? if we're looking to eat something, then we throw // eof? if we're looking to eat something, then we throw
...@@ -79,7 +87,11 @@ namespace YAML ...@@ -79,7 +87,11 @@ namespace YAML
INPUT.eat(n); INPUT.eat(n);
break; break;
} }
// do we remove trailing whitespace?
if(params.fold == FOLD_FLOW)
scalar.erase(lastNonWhitespaceChar);
// ******************************** // ********************************
// Phase #2: eat line ending // Phase #2: eat line ending
n = Exp::Break.Match(INPUT); n = Exp::Break.Match(INPUT);
...@@ -111,27 +123,36 @@ namespace YAML ...@@ -111,27 +123,36 @@ namespace YAML
// was this an empty line? // was this an empty line?
bool nextEmptyLine = Exp::Break.Matches(INPUT); bool nextEmptyLine = Exp::Break.Matches(INPUT);
bool nextMoreIndented = Exp::Blank.Matches(INPUT); bool nextMoreIndented = Exp::Blank.Matches(INPUT);
if(params.fold && foldedNewlineCount == 0 && nextEmptyLine) if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
foldedNewlineStartedMoreIndented = moreIndented; foldedNewlineStartedMoreIndented = moreIndented;
// for block scalars, we always start with a newline, so we should ignore it (not fold or keep) // for block scalars, we always start with a newline, so we should ignore it (not fold or keep)
if(pastOpeningBreak) { if(pastOpeningBreak) {
if(params.fold) { switch(params.fold) {
if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent) case DONT_FOLD:
scalar += " ";
else if(nextEmptyLine)
foldedNewlineCount++;
else
scalar += "\n"; scalar += "\n";
break;
if(!nextEmptyLine && foldedNewlineCount > 0) { case FOLD_BLOCK:
scalar += std::string(foldedNewlineCount - 1, '\n'); if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent)
if(foldedNewlineStartedMoreIndented || nextMoreIndented) scalar += " ";
else if(nextEmptyLine)
foldedNewlineCount++;
else
scalar += "\n"; scalar += "\n";
foldedNewlineCount = 0;
} if(!nextEmptyLine && foldedNewlineCount > 0) {
} else { scalar += std::string(foldedNewlineCount - 1, '\n');
scalar += "\n"; if(foldedNewlineStartedMoreIndented || nextMoreIndented)
scalar += "\n";
foldedNewlineCount = 0;
}
break;
case FOLD_FLOW:
if(nextEmptyLine)
scalar += "\n";
else if(!emptyLine && !nextEmptyLine)
scalar += " ";
break;
} }
} }
......
...@@ -12,9 +12,10 @@ namespace YAML ...@@ -12,9 +12,10 @@ namespace YAML
{ {
enum CHOMP { STRIP = -1, CLIP, KEEP }; enum CHOMP { STRIP = -1, CLIP, KEEP };
enum ACTION { NONE, BREAK, THROW }; enum ACTION { NONE, BREAK, THROW };
enum FOLD { DONT_FOLD, FOLD_BLOCK, FOLD_FLOW };
struct ScanScalarParams { struct ScanScalarParams {
ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(false), ScanScalarParams(): eatEnd(false), indent(0), detectIndent(false), eatLeadingWhitespace(0), escape(0), fold(DONT_FOLD),
trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {} trimTrailingSpaces(0), chomp(CLIP), onDocIndicator(NONE), onTabInIndentation(NONE), leadingSpaces(false) {}
// input: // input:
...@@ -24,7 +25,7 @@ namespace YAML ...@@ -24,7 +25,7 @@ namespace YAML
bool detectIndent; // should we try to autodetect the indent? bool detectIndent; // should we try to autodetect the indent?
bool eatLeadingWhitespace; // should we continue eating this delicious indentation after 'indent' spaces? bool eatLeadingWhitespace; // should we continue eating this delicious indentation after 'indent' spaces?
char escape; // what character do we escape on (i.e., slash or single quote) (0 for none) char escape; // what character do we escape on (i.e., slash or single quote) (0 for none)
bool fold; // do we fold line ends? FOLD fold; // how do we fold line ends?
bool trimTrailingSpaces; // do we remove all trailing spaces (at the very end) bool trimTrailingSpaces; // do we remove all trailing spaces (at the very end)
CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very end) CHOMP chomp; // do we strip, clip, or keep trailing newlines (at the very end)
// Note: strip means kill all, clip means keep at most one, keep means keep all // Note: strip means kill all, clip means keep at most one, keep means keep all
......
...@@ -287,7 +287,7 @@ namespace YAML ...@@ -287,7 +287,7 @@ namespace YAML
params.end = (InFlowContext() ? Exp::EndScalarInFlow : Exp::EndScalar) || (Exp::BlankOrBreak + Exp::Comment); params.end = (InFlowContext() ? Exp::EndScalarInFlow : Exp::EndScalar) || (Exp::BlankOrBreak + Exp::Comment);
params.eatEnd = false; params.eatEnd = false;
params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1); params.indent = (InFlowContext() ? 0 : GetTopIndent() + 1);
params.fold = true; params.fold = FOLD_BLOCK;
params.eatLeadingWhitespace = true; params.eatLeadingWhitespace = true;
params.trimTrailingSpaces = true; params.trimTrailingSpaces = true;
params.chomp = STRIP; params.chomp = STRIP;
...@@ -327,7 +327,7 @@ namespace YAML ...@@ -327,7 +327,7 @@ namespace YAML
params.eatEnd = true; params.eatEnd = true;
params.escape = (single ? '\'' : '\\'); params.escape = (single ? '\'' : '\\');
params.indent = 0; params.indent = 0;
params.fold = true; params.fold = FOLD_FLOW;
params.eatLeadingWhitespace = true; params.eatLeadingWhitespace = true;
params.trimTrailingSpaces = false; params.trimTrailingSpaces = false;
params.chomp = CLIP; params.chomp = CLIP;
...@@ -365,7 +365,7 @@ namespace YAML ...@@ -365,7 +365,7 @@ namespace YAML
// eat block indicator ('|' or '>') // eat block indicator ('|' or '>')
Mark mark = INPUT.mark(); Mark mark = INPUT.mark();
char indicator = INPUT.get(); char indicator = INPUT.get();
params.fold = (indicator == Keys::FoldedScalar); params.fold = (indicator == Keys::FoldedScalar ? FOLD_BLOCK : DONT_FOLD);
// eat chomping/indentation indicators // eat chomping/indentation indicators
params.chomp = CLIP; params.chomp = CLIP;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment