use enforce for most Scanner exceptions

This commit is contained in:
Cameron Ross 2019-03-17 19:56:25 -03:00
parent c7b8ff8a1b
commit dc9aa4ab9c
No known key found for this signature in database
GPG key ID: 777897D98DC91C54

View file

@ -749,12 +749,8 @@ struct Scanner
dchar c = reader_.peek(); dchar c = reader_.peek();
while(c.isAlphaNum || c.among!('-', '_')) { c = reader_.peek(++length); } while(c.isAlphaNum || c.among!('-', '_')) { c = reader_.peek(++length); }
if(length == 0) enforce(length > 0, new ScannerException("While scanning " ~ name,
{ startMark, expected("alphanumeric, '-' or '_'", c), reader_.mark));
enum contextMsg = "While scanning " ~ name;
throw new ScannerException(contextMsg, startMark, expected("alphanumeric, '-' or '_'", c),
reader_.mark);
}
reader_.sliceBuilder.write(reader_.get(length)); reader_.sliceBuilder.write(reader_.get(length));
} }
@ -863,9 +859,9 @@ struct Scanner
// Scan directive name. // Scan directive name.
scanAlphaNumericToSlice!"a directive"(startMark); scanAlphaNumericToSlice!"a directive"(startMark);
if(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029')) { return; } enforce(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
throw new ScannerException("While scanning a directive", startMark, new ScannerException("While scanning a directive", startMark,
expected("alphanumeric, '-' or '_'", reader_.peek()), reader_.mark); expected("alphanumeric, '-' or '_'", reader_.peek()), reader_.mark));
} }
/// Scan value of a YAML directive token. Returns major, minor version separated by '.'. /// Scan value of a YAML directive token. Returns major, minor version separated by '.'.
@ -878,22 +874,18 @@ struct Scanner
scanYAMLDirectiveNumberToSlice(startMark); scanYAMLDirectiveNumberToSlice(startMark);
if(reader_.peekByte() != '.') enforce(reader_.peekByte() == '.',
{ new ScannerException("While scanning a directive", startMark,
throw new ScannerException("While scanning a directive", startMark, expected("digit or '.'", reader_.peek()), reader_.mark));
expected("digit or '.'", reader_.peek()), reader_.mark);
}
// Skip the '.'. // Skip the '.'.
reader_.forward(); reader_.forward();
reader_.sliceBuilder.write('.'); reader_.sliceBuilder.write('.');
scanYAMLDirectiveNumberToSlice(startMark); scanYAMLDirectiveNumberToSlice(startMark);
if(!reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029')) enforce(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
{ new ScannerException("While scanning a directive", startMark,
throw new ScannerException("While scanning a directive", startMark, expected("digit or '.'", reader_.peek()), reader_.mark));
expected("digit or '.'", reader_.peek()), reader_.mark);
}
} }
/// Scan a number from a YAML directive. /// Scan a number from a YAML directive.
@ -902,11 +894,9 @@ struct Scanner
/// characters into that slice. /// characters into that slice.
void scanYAMLDirectiveNumberToSlice(const Mark startMark) @safe void scanYAMLDirectiveNumberToSlice(const Mark startMark) @safe
{ {
if(!isDigit(reader_.peek())) enforce(isDigit(reader_.peek()),
{ new ScannerException("While scanning a directive", startMark,
throw new ScannerException("While scanning a directive", startMark, expected("digit", reader_.peek()), reader_.mark));
expected("digit", reader_.peek()), reader_.mark);
}
// Already found the first digit in the enforce(), so set length to 1. // Already found the first digit in the enforce(), so set length to 1.
uint length = 1; uint length = 1;
@ -940,9 +930,9 @@ struct Scanner
void scanTagDirectiveHandleToSlice(const Mark startMark) @safe void scanTagDirectiveHandleToSlice(const Mark startMark) @safe
{ {
scanTagHandleToSlice!"directive"(startMark); scanTagHandleToSlice!"directive"(startMark);
if(reader_.peekByte() == ' ') { return; } enforce(reader_.peekByte() == ' ',
throw new ScannerException("While scanning a directive handle", startMark, new ScannerException("While scanning a directive handle", startMark,
expected("' '", reader_.peek()), reader_.mark); expected("' '", reader_.peek()), reader_.mark));
} }
/// Scan prefix of a tag directive. /// Scan prefix of a tag directive.
@ -952,9 +942,9 @@ struct Scanner
void scanTagDirectivePrefixToSlice(const Mark startMark) @safe void scanTagDirectivePrefixToSlice(const Mark startMark) @safe
{ {
scanTagURIToSlice!"directive"(startMark); scanTagURIToSlice!"directive"(startMark);
if(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029')) { return; } enforce(reader_.peek().among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
throw new ScannerException("While scanning a directive prefix", startMark, new ScannerException("While scanning a directive prefix", startMark,
expected("' '", reader_.peek()), reader_.mark); expected("' '", reader_.peek()), reader_.mark));
} }
/// Scan (and ignore) ignored line after a directive. /// Scan (and ignore) ignored line after a directive.
@ -962,13 +952,10 @@ struct Scanner
{ {
findNextNonSpace(); findNextNonSpace();
if(reader_.peekByte() == '#') { scanToNextBreak(); } if(reader_.peekByte() == '#') { scanToNextBreak(); }
if(reader_.peek().isBreak) enforce(reader_.peek().isBreak,
{ new ScannerException("While scanning a directive", startMark,
expected("comment or a line break", reader_.peek()), reader_.mark));
scanLineBreak(); scanLineBreak();
return;
}
throw new ScannerException("While scanning a directive", startMark,
expected("comment or a line break", reader_.peek()), reader_.mark);
} }
@ -993,14 +980,12 @@ struct Scanner
// On error, value is discarded as we return immediately // On error, value is discarded as we return immediately
char[] value = reader_.sliceBuilder.finish(); char[] value = reader_.sliceBuilder.finish();
if(!reader_.peek().isWhiteSpace &&
!reader_.peekByte().among!('?', ':', ',', ']', '}', '%', '@'))
{
enum anchorCtx = "While scanning an anchor"; enum anchorCtx = "While scanning an anchor";
enum aliasCtx = "While scanning an alias"; enum aliasCtx = "While scanning an alias";
throw new ScannerException(i == '*' ? aliasCtx : anchorCtx, startMark, enforce(reader_.peek().isWhiteSpace ||
expected("alphanumeric, '-' or '_'", reader_.peek()), reader_.mark); reader_.peekByte().among!('?', ':', ',', ']', '}', '%', '@'),
} new ScannerException(i == '*' ? aliasCtx : anchorCtx, startMark,
expected("alphanumeric, '-' or '_'", reader_.peek()), reader_.mark));
if(id == TokenID.alias_) if(id == TokenID.alias_)
{ {
@ -1031,11 +1016,9 @@ struct Scanner
handleEnd = 0; handleEnd = 0;
scanTagURIToSlice!"tag"(startMark); scanTagURIToSlice!"tag"(startMark);
if(reader_.peekByte() != '>') enforce(reader_.peekByte() == '>',
{ new ScannerException("While scanning a tag", startMark,
throw new ScannerException("While scanning a tag", startMark, expected("'>'", reader_.peek()), reader_.mark));
expected("'>'", reader_.peek()), reader_.mark);
}
reader_.forward(); reader_.forward();
} }
else if(c.isWhiteSpace) else if(c.isWhiteSpace)
@ -1075,16 +1058,14 @@ struct Scanner
scanTagURIToSlice!"tag"(startMark); scanTagURIToSlice!"tag"(startMark);
} }
if(reader_.peek().isBreakOrSpace) enforce(reader_.peek().isBreakOrSpace,
{ new ScannerException("While scanning a tag", startMark, expected("' '", reader_.peek()),
reader_.mark));
char[] slice = reader_.sliceBuilder.finish(); char[] slice = reader_.sliceBuilder.finish();
return tagToken(startMark, reader_.mark, slice, handleEnd); return tagToken(startMark, reader_.mark, slice, handleEnd);
} }
throw new ScannerException("While scanning a tag", startMark, expected("' '", reader_.peek()),
reader_.mark);
}
/// Scan a block scalar token with specified style. /// Scan a block scalar token with specified style.
Token scanBlockScalar(const ScalarStyle style) @safe Token scanBlockScalar(const ScalarStyle style) @safe
{ {
@ -1241,13 +1222,12 @@ struct Scanner
if(gotIncrement) { getChomping(c, chomping); } if(gotIncrement) { getChomping(c, chomping); }
} }
if(c.among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029')) enforce(c.among!(' ', '\0', '\n', '\r', '\u0085', '\u2028', '\u2029'),
{ new ScannerException("While scanning a block scalar", startMark,
expected("chomping or indentation indicator", c), reader_.mark));
return tuple(chomping, increment); return tuple(chomping, increment);
} }
throw new ScannerException("While scanning a block scalar", startMark,
expected("chomping or indentation indicator", c), reader_.mark);
}
/// Get chomping indicator, if detected. Return false otherwise. /// Get chomping indicator, if detected. Return false otherwise.
/// ///
@ -1283,15 +1263,15 @@ struct Scanner
// Convert a digit to integer. // Convert a digit to integer.
increment = c - '0'; increment = c - '0';
assert(increment < 10 && increment >= 0, "Digit has invalid value"); assert(increment < 10 && increment >= 0, "Digit has invalid value");
if(increment > 0)
{ enforce(increment > 0,
new ScannerException("While scanning a block scalar", startMark,
expected("indentation indicator in range 1-9", "0"), reader_.mark));
reader_.forward(); reader_.forward();
c = reader_.peek(); c = reader_.peek();
return true; return true;
} }
throw new ScannerException("While scanning a block scalar", startMark,
expected("indentation indicator in range 1-9", "0"), reader_.mark);
}
/// Scan (and ignore) ignored line in a block scalar. /// Scan (and ignore) ignored line in a block scalar.
void scanBlockScalarIgnoredLine(const Mark startMark) @safe void scanBlockScalarIgnoredLine(const Mark startMark) @safe
@ -1299,13 +1279,11 @@ struct Scanner
findNextNonSpace(); findNextNonSpace();
if(reader_.peekByte()== '#') { scanToNextBreak(); } if(reader_.peekByte()== '#') { scanToNextBreak(); }
if(reader_.peek().isBreak) enforce(reader_.peek().isBreak,
{ new ScannerException("While scanning a block scalar", startMark,
expected("comment or line break", reader_.peek()), reader_.mark));
scanLineBreak(); scanLineBreak();
return;
}
throw new ScannerException("While scanning a block scalar", startMark,
expected("comment or line break", reader_.peek()), reader_.mark);
} }
/// Scan indentation in a block scalar, returning line breaks, max indent and end mark. /// Scan indentation in a block scalar, returning line breaks, max indent and end mark.
@ -1391,11 +1369,10 @@ struct Scanner
// This will not necessarily make slice 32 chars longer, as not all // This will not necessarily make slice 32 chars longer, as not all
// code points are 1 char. // code points are 1 char.
const char[] slice = reader_.slice(numCodePoints + 32); const char[] slice = reader_.slice(numCodePoints + 32);
if(slice.length == oldSliceLength) enforce(slice.length != oldSliceLength,
{ new ScannerException("While reading a flow scalar", startMark,
throw new ScannerException("While reading a flow scalar", startMark, "reached end of file", reader_.mark));
"reached end of file", reader_.mark);
}
for(size_t i = oldSliceLength; i < slice.length;) for(size_t i = oldSliceLength; i < slice.length;)
{ {
// slice is UTF-8 - need to decode // slice is UTF-8 - need to decode
@ -1439,31 +1416,22 @@ struct Scanner
reader_.forward(); reader_.forward();
foreach(i; 0 .. hexLength) { foreach(i; 0 .. hexLength) {
if(!reader_.peek(i).isHexDigit) enforce(reader_.peek(i).isHexDigit,
{ new ScannerException("While scanning a double quoted scalar", startMark,
throw new ScannerException("While scanning a double quoted scalar", startMark,
expected("escape sequence of hexadecimal numbers", expected("escape sequence of hexadecimal numbers",
reader_.peek(i)), reader_.mark); reader_.peek(i)), reader_.mark));
}
} }
char[] hex = reader_.get(hexLength); char[] hex = reader_.get(hexLength);
enforce((hex.length > 0) && (hex.length <= 8),
new ScannerException("While scanning a double quoted scalar", startMark,
"overflow when parsing an escape sequence of " ~
"hexadecimal numbers.", reader_.mark));
char[2] escapeStart = ['\\', cast(char) c]; char[2] escapeStart = ['\\', cast(char) c];
reader_.sliceBuilder.write(escapeStart); reader_.sliceBuilder.write(escapeStart);
reader_.sliceBuilder.write(hex); reader_.sliceBuilder.write(hex);
// Note: This is just error checking; Parser does the actual
// escaping (otherwise we could accidentally create an
// escape sequence here that wasn't in input, breaking the
// escaping code in parser, which is in parser because it
// can't always be done in place)
try {
parse!int(hex, 16u);
}
catch (Exception)
{
throw new ScannerException("While scanning a double quoted scalar", startMark,
"overflow when parsing an escape sequence of " ~
"hexadecimal numbers.", reader_.mark);
}
} }
else if(c.among!('\n', '\r', '\u0085', '\u2028', '\u2029')) else if(c.among!('\n', '\r', '\u0085', '\u2028', '\u2029'))
{ {
@ -1494,11 +1462,9 @@ struct Scanner
// Can check the last byte without striding because '\0' is ASCII // Can check the last byte without striding because '\0' is ASCII
const c = reader_.peek(length); const c = reader_.peek(length);
if(c == '\0') enforce(c != '\0',
{ new ScannerException("While scanning a quoted scalar", startMark,
throw new ScannerException("While scanning a quoted scalar", startMark, "found unexpected end of buffer", reader_.mark));
"found unexpected end of buffer", reader_.mark);
}
// Spaces not followed by a line break. // Spaces not followed by a line break.
if(!c.among!('\n', '\r', '\u0085', '\u2028', '\u2029')) if(!c.among!('\n', '\r', '\u0085', '\u2028', '\u2029'))
@ -1534,12 +1500,10 @@ struct Scanner
{ {
// Instead of checking indentation, we check for document separators. // Instead of checking indentation, we check for document separators.
const prefix = reader_.prefix(3); const prefix = reader_.prefix(3);
if((prefix == "---" || prefix == "...") && enforce(!(prefix == "---" || prefix == "...") ||
reader_.peek(3).isWhiteSpace) !reader_.peek(3).isWhiteSpace,
{ new ScannerException("While scanning a quoted scalar", startMark,
throw new ScannerException("While scanning a quoted scalar", startMark, "found unexpected document separator", reader_.mark));
"found unexpected document separator", reader_.mark);
}
// Skip any whitespaces. // Skip any whitespaces.
while(reader_.peekByte().among!(' ', '\t')) { reader_.forward(); } while(reader_.peekByte().among!(' ', '\t')) { reader_.forward(); }
@ -1607,19 +1571,13 @@ struct Scanner
} }
// It's not clear what we should do with ':' in the flow context. // It's not clear what we should do with ':' in the flow context.
if(flowLevel_ > 0 && c == ':' && enforce(flowLevel_ == 0 || c != ':' ||
!reader_.peek(length + 1).isWhiteSpace && reader_.peek(length + 1).isWhiteSpace ||
!reader_.peek(length + 1).among!(',', '[', ']', '{', '}')) reader_.peek(length + 1).among!(',', '[', ']', '{', '}'),
{ new ScannerException("While scanning a plain scalar", startMark,
// This is an error; throw the slice away.
spacesTransaction.commit();
reader_.sliceBuilder.finish();
reader_.forward(length);
throw new ScannerException("While scanning a plain scalar", startMark,
"found unexpected ':' . Please check " ~ "found unexpected ':' . Please check " ~
"http://pyyaml.org/wiki/YAMLColonInFlowContext for details.", "http://pyyaml.org/wiki/YAMLColonInFlowContext for details.",
reader_.mark); reader_.mark));
}
if(length == 0) { break; } if(length == 0) { break; }
@ -1714,10 +1672,8 @@ struct Scanner
{ {
dchar c = reader_.peek(); dchar c = reader_.peek();
enum contextMsg = "While scanning a " ~ name; enum contextMsg = "While scanning a " ~ name;
if(c != '!') enforce(c == '!',
{ new ScannerException(contextMsg, startMark, expected("'!'", c), reader_.mark));
throw new ScannerException(contextMsg, startMark, expected("'!'", c), reader_.mark);
}
uint length = 1; uint length = 1;
c = reader_.peek(length); c = reader_.peek(length);
@ -1728,11 +1684,8 @@ struct Scanner
++length; ++length;
c = reader_.peek(length); c = reader_.peek(length);
} }
if(c != '!') enforce(c == '!',
{ new ScannerException(contextMsg, startMark, expected("'!'", c), reader_.mark));
reader_.forward(length);
throw new ScannerException(contextMsg, startMark, expected("'!'", c), reader_.mark);
}
++length; ++length;
} }
@ -1770,10 +1723,9 @@ struct Scanner
} }
} }
// OK if we scanned something, error otherwise. // OK if we scanned something, error otherwise.
if(reader_.sliceBuilder.length > startLen) { return; }
enum contextMsg = "While parsing a " ~ name; enum contextMsg = "While parsing a " ~ name;
throw new ScannerException(contextMsg, startMark, expected("URI", c), reader_.mark); enforce(reader_.sliceBuilder.length > startLen,
new ScannerException(contextMsg, startMark, expected("URI", c), reader_.mark));
} }
// Not @nogc yet because std.utf.decode is not @nogc // Not @nogc yet because std.utf.decode is not @nogc
@ -1794,12 +1746,12 @@ struct Scanner
{ {
reader_.forward(); reader_.forward();
char[2] nextByte = [reader_.peekByte(), reader_.peekByte(1)]; char[2] nextByte = [reader_.peekByte(), reader_.peekByte(1)];
if(!nextByte[0].isHexDigit || !nextByte[1].isHexDigit)
{ enforce(nextByte[0].isHexDigit && nextByte[1].isHexDigit,
auto msg = expected("URI escape sequence of 2 hexadecimal " ~ new ScannerException(contextMsg, startMark,
"numbers", nextByte); expected("URI escape sequence of 2 hexadecimal " ~
throw new ScannerException(contextMsg, startMark, msg, reader_.mark); "numbers", nextByte), reader_.mark));
}
buffer ~= nextByte[].to!ubyte(16); buffer ~= nextByte[].to!ubyte(16);
reader_.forward(2); reader_.forward(2);