diff --git a/Source/FrameSequenceParser.cpp b/Source/FrameSequenceParser.cpp index 34e003e..e7c855e 100644 --- a/Source/FrameSequenceParser.cpp +++ b/Source/FrameSequenceParser.cpp @@ -10,11 +10,7 @@ #include "FrameSequenceParser.h" -// -// Fileprivate -// - -std::vector parseSlope (const String& input, +std::vector FrameSequenceParser::parseSlope (const String& input, int minValue, int maxValue, ParseError* error) @@ -115,7 +111,7 @@ std::vector parseSlope (const String& input, return retval; } -std::vector parseRepeat (const String& input, +std::vector FrameSequenceParser::parseRepeat (const String& input, int minValue, int maxValue, ParseError* error) @@ -172,7 +168,7 @@ std::vector parseRepeat (const String& input, return retval; } -std::vector parseSegment (const String& input, +std::vector FrameSequenceParser::parseSegment (const String& input, int minValue, int maxValue, ParseError* error) @@ -228,6 +224,121 @@ std::vector parseSegment (const String& input, return retval; } +FrameSequenceParser::SegmentIndexes FrameSequenceParser::findSegment(const String& input) { + int releaseBlockIndex = -1; + int repeatStartIndex = -1; + int repeatEndIndex = -1; + int openBracketCount = 0; + int closeBracketCount = 0; + + SegmentIndexes retval = SegmentIndexes(); + + // loop by character + for (int i = 0; i < input.length(); i++) + { + if (input[i] == '|') // found "|": + { + if (releaseBlockIndex >= 0) + { + // if releaseBlockIndex is already determined: Duplication Error + retval.error = kParseErrorDuplicatedReleaseDelimiter; + return retval; + } + + // if(repeatStartIndex >= 0) { + // // if appeard before "[" or "]": Repetition After Release Error + // throw new FrameSequenceParseException(TRANS("You cannot repeat in release phase"), true); + // } + // set releaseBlockIndex + releaseBlockIndex = i + 1; + + if (repeatEndIndex < 0) + { + // if "]" is omitted: Also set repeatEndIndex + repeatEndIndex = i; + } + } + + if (input[i] == '[') /// found "[": + { + openBracketCount++; + + if (openBracketCount > 1) + { + // Duplication Error + retval.error = kParseErrorDuplicatedOpenBracket; + return retval; + } + + if (releaseBlockIndex >= 0) + { + // if repeat end is already defined: Repetition After Release Error + retval.error = kParseErrorRepeatingInReleaseBlock; + return retval; + } + + if (repeatEndIndex >= 0) + { + // if repeat end is already defined: Repetition After Release Error + retval.error = kParseErrorDuplicatedOpenBracket; + return retval; + } + + // set repeatStartIndex + repeatStartIndex = i + 1; + } + + if (input[i] == ']') // found "]": + { + closeBracketCount++; + + if (closeBracketCount > 1) + { + // Duplication Error + retval.error = kParseErrorDuplicatedCloseBracket; + return retval; + } + + if (repeatStartIndex < 0) + { + // if repeatStartIndex hasn't set: Syntax Error + retval.error = kParseErrorUnmatchingCloseBracket; + return retval; + } + + if (releaseBlockIndex >= 0) + { + // if repeat end is already defined: Repetition After Release Error + retval.error = kParseErrorRepeatingInReleaseBlock; + return retval; + } + + repeatEndIndex = i; + } + } + + // if (releaseBlockIndex < 0) { // "|" didn't explicitly specified + // releaseBlockIndex = trimmed.length(); + // } + + if (openBracketCount != closeBracketCount) + { + retval.error = kParseErrorUnmatchingBracketNumber; + return retval; + } + + if (releaseBlockIndex - repeatEndIndex > 1) + { + // throw new FrameSequenceParseException(TRANS("Elements between repeat block and release block will be ignored"), false); + // FiXME: non-fatal exceptionをどう扱うか + } + + retval.releaseBlockIndex = releaseBlockIndex; + retval.repeatStartIndex = repeatStartIndex; + retval.repeatEndIndex = repeatEndIndex; + return retval; +} + FrameSequence FrameSequenceParser::parse (const String& input, int minValue, int maxValue, diff --git a/Source/FrameSequenceParser.h b/Source/FrameSequenceParser.h index 67c8cc0..15ca5d5 100644 --- a/Source/FrameSequenceParser.h +++ b/Source/FrameSequenceParser.h @@ -15,5 +15,34 @@ struct FrameSequenceParser { + /* + Public + */ FrameSequence parse (const String& input, int minValue, int maxValue, ParseError* error); + + /* + Semantically private (leave them open for unit testing) + */ + struct SegmentIndexes { + const int NONE = -1; + + int releaseBlockIndex = NONE; + int repeatStartIndex = NONE; + int repeatEndIndex = NONE; + ParseError error; + }; + + std::vector parseSlope (const String& input, + int minValue, + int maxValue, + ParseError* error); + std::vector parseRepeat (const String& input, + int minValue, + int maxValue, + ParseError* error); + std::vector parseSegment (const String& input, + int minValue, + int maxValue, + ParseError* error); + SegmentIndexes findSegment(const String& input); };