Go to the documentation of this file.00001 #include "scanscalar.h"
00002 #include "scanner.h"
00003 #include "exp.h"
00004 #include "yaml-cpp-pm/exceptions.h"
00005 #include "token.h"
00006
00007 namespace YAML_PM
00008 {
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 std::string ScanScalar(Stream& INPUT, ScanScalarParams& params)
00020 {
00021 bool foundNonEmptyLine = false;
00022 bool pastOpeningBreak = (params.fold == FOLD_FLOW);
00023 bool emptyLine = false, moreIndented = false;
00024 int foldedNewlineCount = 0;
00025 bool foldedNewlineStartedMoreIndented = false;
00026 std::size_t lastEscapedChar = std::string::npos;
00027 std::string scalar;
00028 params.leadingSpaces = false;
00029
00030 while(INPUT) {
00031
00032
00033
00034 std::size_t lastNonWhitespaceChar = scalar.size();
00035 bool escapedNewline = false;
00036 while(!params.end.Matches(INPUT) && !Exp::Break().Matches(INPUT)) {
00037 if(!INPUT)
00038 break;
00039
00040
00041 if(INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT)) {
00042 if(params.onDocIndicator == BREAK)
00043 break;
00044 else if(params.onDocIndicator == THROW)
00045 throw ParserException(INPUT.mark(), ErrorMsg::DOC_IN_SCALAR);
00046 }
00047
00048 foundNonEmptyLine = true;
00049 pastOpeningBreak = true;
00050
00051
00052 if(params.escape == '\\' && Exp::EscBreak().Matches(INPUT)) {
00053
00054 INPUT.get();
00055 lastNonWhitespaceChar = scalar.size();
00056 lastEscapedChar = scalar.size();
00057 escapedNewline = true;
00058 break;
00059 }
00060
00061
00062 if(INPUT.peek() == params.escape) {
00063 scalar += Exp::Escape(INPUT);
00064 lastNonWhitespaceChar = scalar.size();
00065 lastEscapedChar = scalar.size();
00066 continue;
00067 }
00068
00069
00070 char ch = INPUT.get();
00071 scalar += ch;
00072 if(ch != ' ' && ch != '\t')
00073 lastNonWhitespaceChar = scalar.size();
00074 }
00075
00076
00077 if(!INPUT) {
00078 if(params.eatEnd)
00079 throw ParserException(INPUT.mark(), ErrorMsg::EOF_IN_SCALAR);
00080 break;
00081 }
00082
00083
00084 if(params.onDocIndicator == BREAK && INPUT.column() == 0 && Exp::DocIndicator().Matches(INPUT))
00085 break;
00086
00087
00088 int n = params.end.Match(INPUT);
00089 if(n >= 0) {
00090 if(params.eatEnd)
00091 INPUT.eat(n);
00092 break;
00093 }
00094
00095
00096 if(params.fold == FOLD_FLOW)
00097 scalar.erase(lastNonWhitespaceChar);
00098
00099
00100
00101 n = Exp::Break().Match(INPUT);
00102 INPUT.eat(n);
00103
00104
00105
00106
00107
00108 while(INPUT.peek() == ' ' && (INPUT.column() < params.indent || (params.detectIndent && !foundNonEmptyLine)))
00109 INPUT.eat(1);
00110
00111
00112 if(params.detectIndent && !foundNonEmptyLine)
00113 params.indent = std::max(params.indent, INPUT.column());
00114
00115
00116 while(Exp::Blank().Matches(INPUT)) {
00117
00118 if(INPUT.peek() == '\t'&& INPUT.column() < params.indent && params.onTabInIndentation == THROW)
00119 throw ParserException(INPUT.mark(), ErrorMsg::TAB_IN_INDENTATION);
00120
00121 if(!params.eatLeadingWhitespace)
00122 break;
00123
00124 INPUT.eat(1);
00125 }
00126
00127
00128 bool nextEmptyLine = Exp::Break().Matches(INPUT);
00129 bool nextMoreIndented = Exp::Blank().Matches(INPUT);
00130 if(params.fold == FOLD_BLOCK && foldedNewlineCount == 0 && nextEmptyLine)
00131 foldedNewlineStartedMoreIndented = moreIndented;
00132
00133
00134 if(pastOpeningBreak) {
00135 switch(params.fold) {
00136 case DONT_FOLD:
00137 scalar += "\n";
00138 break;
00139 case FOLD_BLOCK:
00140 if(!emptyLine && !nextEmptyLine && !moreIndented && !nextMoreIndented && INPUT.column() >= params.indent)
00141 scalar += " ";
00142 else if(nextEmptyLine)
00143 foldedNewlineCount++;
00144 else
00145 scalar += "\n";
00146
00147 if(!nextEmptyLine && foldedNewlineCount > 0) {
00148 scalar += std::string(foldedNewlineCount - 1, '\n');
00149 if(foldedNewlineStartedMoreIndented || nextMoreIndented | !foundNonEmptyLine)
00150 scalar += "\n";
00151 foldedNewlineCount = 0;
00152 }
00153 break;
00154 case FOLD_FLOW:
00155 if(nextEmptyLine)
00156 scalar += "\n";
00157 else if(!emptyLine && !nextEmptyLine && !escapedNewline)
00158 scalar += " ";
00159 break;
00160 }
00161 }
00162
00163 emptyLine = nextEmptyLine;
00164 moreIndented = nextMoreIndented;
00165 pastOpeningBreak = true;
00166
00167
00168 if(!emptyLine && INPUT.column() < params.indent) {
00169 params.leadingSpaces = true;
00170 break;
00171 }
00172 }
00173
00174
00175 if(params.trimTrailingSpaces) {
00176 std::size_t pos = scalar.find_last_not_of(' ');
00177 if(lastEscapedChar != std::string::npos) {
00178 if(pos < lastEscapedChar || pos == std::string::npos)
00179 pos = lastEscapedChar;
00180 }
00181 if(pos < scalar.size())
00182 scalar.erase(pos + 1);
00183 }
00184
00185 switch(params.chomp) {
00186 case CLIP: {
00187 std::size_t pos = scalar.find_last_not_of('\n');
00188 if(lastEscapedChar != std::string::npos) {
00189 if(pos < lastEscapedChar || pos == std::string::npos)
00190 pos = lastEscapedChar;
00191 }
00192 if(pos == std::string::npos)
00193 scalar.erase();
00194 else if(pos + 1 < scalar.size())
00195 scalar.erase(pos + 2);
00196 } break;
00197 case STRIP: {
00198 std::size_t pos = scalar.find_last_not_of('\n');
00199 if(lastEscapedChar != std::string::npos) {
00200 if(pos < lastEscapedChar || pos == std::string::npos)
00201 pos = lastEscapedChar;
00202 }
00203 if(pos == std::string::npos)
00204 scalar.erase();
00205 else if(pos < scalar.size())
00206 scalar.erase(pos + 1);
00207 } break;
00208 default:
00209 break;
00210 }
00211
00212 return scalar;
00213 }
00214 }