/// <summary> /// Gets current character token /// </summary> /// <param name="nextline">Indicates if returning of line end sequence is allowed</param> /// <param name="inner">Optional function to check for inner sequences which will be treated as compound character token</param> /// <param name="token">Resulting token in case of match</param> /// <param name="increment">Indicates if current source position needs to be advanced in case of match</param> /// <returns>Returns <c>true</c> in case of match</returns> protected bool GetCharToken(bool nextline, InnerScan inner, out SourceToken token, bool increment = true) { var result = false; var len = IsBreak; // if current position isn't at line end if (len == 0) { // check for possible inner sequences, if requested if (inner != null) { len = inner(); } // no inner sequence found and end of source reached - return false if (len == 0 && _source.IsEnd) { // NOTE: just to c# compiler stop complaining token = new SourceToken(); return(false); } // return single character token, otherwise return token with corresponding // length token = new SourceToken(_source.Position, len == 0 ? 1 : len); result = true; } else { token = new SourceToken(_source.Position, nextline ? len : 0); // if reached here - line break was found, if skip to next line is allowed // increment lines counter and return line break sequence as a token if (nextline) { ++_lines; } result = nextline; } if (result && increment) { _source.Advance(token.Length); } return(result); }
/// <summary> /// Gets current character token and matches it agains provided set /// </summary> /// <param name="set">Character set to check current char belongs to</param> /// <param name="nextline">Indicates if returning of line end sequence is allowed</param> /// <param name="inner">Optional function to check for inner sequences which will be treated as compound character token</param> /// <param name="token">Resulting token in case of match</param> /// <param name="increment">Indicates if current source position needs to be advanced in case of match</param> /// <returns>Returns <c>true</c> in case of match</returns> /// <remarks> /// <paramref name="set"/> must not be <c>null</c>. /// If character doesn't match given set and it's not any inner sequence /// function returns <c>false</c> /// </remarks> protected bool CheckCharToken(CharSet set, bool nextline, InnerScan inner, out SourceToken token, bool increment = true) { Debug.Assert(set != null, "set must not be null"); var result = GetCharToken(nextline, inner, out token, false) && (token.Length > 1 || set.Contains(_source.CharCurrent)); if (result && increment) { _source.Advance(token.Length); } return(result); }
// try to scan verbatim string literal // verbatim string: @"<chars, no escapes, line breaks allowed>"("<chars>") private ScanResult ScanVerbatimString(InnerScan inner, out SourceToken token) { var result = FromTo("@\"", "\"", true, inner, false, out token); // continue with contigous double quoted strings only if there was full match if (result == ScanResult.Match) { SourceToken tok; ScanResult next; while (Match(next = FromTo("\"", "\"", true, inner, false, out tok))) { result = next; token.Length += tok.Length; } } return(result); }
/// <summary> /// Matches token given by starting and ending character sequences /// </summary> /// <param name="fromtoken">Character sequence with which token starts</param> /// <param name="totoken">Character sequence with which token ends</param> /// <param name="multiline">Indicates whether token is allowed to span for multiple lines</param> /// <param name="inner">Optional function to check for inner sequences which will be treated as compound character token</param> /// <param name="allownesting">Indicates if nesting of starting/ending sequences is allowed</param> /// <param name="token">Resulting token in case of match</param> /// <param name="increment">Indicates if current source position needs to be advanced in case of match</param> /// <returns>Returns match result</returns> /// <remarks> /// <paramref name="fromtoken"/> must not be <c>null</c> or empty string. /// <paramref name="totoken"/> must not be <c>null</c> or empty string. /// This function might return partial match. /// </remarks> protected ScanResult FromTo(string fromtoken, string totoken, bool multiline, InnerScan inner, bool allownesting, out SourceToken token, bool increment = true) { Debug.Assert(!string.IsNullOrEmpty(fromtoken), "fromtoken string must not be null or empty"); Debug.Assert(!string.IsNullOrEmpty(totoken), "totoken string must not be null or empty"); token = new SourceToken(_source.Position); // check "from" sequence match if (!Check(fromtoken)) { return(ScanResult.NoMatch); } int nestinglevel = 1; token.Length += fromtoken.Length; var result = ScanResult.NoMatch; // continue with characters up until match of "totoken" SourceToken cs; while (GetCharToken(multiline, inner, out cs, false)) { if (allownesting && Check(fromtoken)) { ++nestinglevel; token.Length += fromtoken.Length; continue; } if (Check(totoken)) { --nestinglevel; token.Length += totoken.Length; if (nestinglevel == 0) { result = ScanResult.Match; break; } continue; } _source.Advance(cs.Length); token.Length += cs.Length; } // check if token end matches ending sequence if (result != ScanResult.Match) { if (_source.IsEnd) { result = ScanResult.MatchTrimmedEOF; } else { result = ScanResult.MatchTrimmedEOL; } } // if increment wasn't requeseted - advance back (to position which was before this call) if (!increment) { _source.Advance(-token.Length); } return(result); }
/// <summary> /// Matches token given by possible starting character sequences and allowed character set /// </summary> /// <param name="from">Character sequences with which token starts</param> /// <param name="whileset">CharSet which holds allowed characters to be included in token after starting one</param> /// <param name="multiline">Indicates whether token is allowed to span for multiple lines</param> /// <param name="inner">Optional function to check for inner sequences which will be treated as compound character token</param> /// <param name="notemptywhile">Indicates that match should be returned only if there is at leas one match from while set</param> /// <param name="token">Resulting token in case of match</param> /// <param name="increment">Indicates if current source position needs to be advanced in case of match</param> /// <returns>Returns match result</returns> /// <remarks> /// <paramref name="from"/> must not be <c>null</c> and must not contain <c>null</c> or empty string. /// <paramref name="whileset"/> must not be <c>null</c>. /// This function does not return partial matches (it's not possible) in this case. /// </remarks> protected ScanResult FromTokenWhile(IEnumerable <string> from, CharSet whileset, bool multiline, InnerScan inner, bool notemptywhile, out SourceToken token, bool increment = true) { Debug.Assert(from != null, "from source must not be null"); Debug.Assert(whileset != null, "whileset set must not be null"); var result = ScanResult.NoMatch; foreach (var tok in from) { result = FromTokenWhile( tok, whileset, multiline, inner, notemptywhile, out token, increment ); if (result != ScanResult.NoMatch) { return(result); } } token = new SourceToken(); return(result); }
/// <summary> /// Matches token given by starting character sequence and allowed character set /// </summary> /// <param name="from">Character sequence with which token starts</param> /// <param name="whileset">CharSet which holds allowed characters to be included in token after starting one</param> /// <param name="multiline">Indicates whether token is allowed to span for multiple lines</param> /// <param name="inner">Optional function to check for inner sequences which will be treated as compound character token</param> /// <param name="notemptywhile">Indicates that match should be returned only if there is at leas one match from while set</param> /// <param name="token">Resulting token in case of match</param> /// <param name="increment">Indicates if current source position needs to be advanced in case of match</param> /// <returns>Returns match result</returns> /// <remarks> /// <paramref name="from"/> must not be <c>null</c> or empty string. /// <paramref name="whileset"/> must not be <c>null</c>. /// This function does not return partial matches (it's not possible) in this case. /// </remarks> protected ScanResult FromTokenWhile(string from, CharSet whileset, bool multiline, InnerScan inner, bool notemptywhile, out SourceToken token, bool increment = true) { Debug.Assert(!string.IsNullOrEmpty(from), "from string must not be null or empty"); Debug.Assert(whileset != null, "whileset set must not be null"); token = new SourceToken(_source.Position); // check "from" sequence match if (!Check(from)) { return(ScanResult.NoMatch); } token.Length += from.Length; // continue while characters match "whileset" SourceToken cs; while (CheckCharToken(whileset, multiline, inner, out cs)) { token.Length += cs.Length; } // if notemptywhile requested total length should be more than from length if (notemptywhile && token.Length <= from.Length) { _source.Advance(-token.Length); return(ScanResult.NoMatch); } // if increment wasn't requeseted - advance back (to position which was before this call) if (!increment) { _source.Advance(-token.Length); } return(ScanResult.Match); }
/// <summary> /// Matches token given by starting character set and allowed character set /// </summary> /// <param name="from">CharSet which holds allowed starting token characters</param> /// <param name="whileset">CharSet which holds allowed characters to be included in token after starting one</param> /// <param name="multiline">Indicates whether token is allowed to span for multiple lines</param> /// <param name="inner">Optional function to check for inner sequences which will be treated as compound character token</param> /// <param name="token">Resulting token in case of match</param> /// <param name="increment">Indicates if current source position needs to be advanced in case of match</param> /// <returns>Returns match result</returns> /// <remarks> /// <paramref name="from"/> and <paramref name="whileset"/> must not be <c>null</c>. /// This function does not return partial matches (it's not possible) in this case. /// </remarks> protected ScanResult FromSetWhile(CharSet from, CharSet whileset, bool multiline, InnerScan inner, out SourceToken token, bool increment = true) { Debug.Assert(from != null, "from set must not be null"); Debug.Assert(whileset != null, "whileset set must not be null"); // check match for first allowed character if (!CheckCharToken(from, multiline, inner, out token)) { return(ScanResult.NoMatch); } // continue while characters match "whileset" SourceToken cs; while (CheckCharToken(whileset, multiline, inner, out cs)) { token.Length += cs.Length; } // if increment wasn't requeseted - advance back (to position which was before this call) if (!increment) { _source.Advance(-token.Length); } return(ScanResult.Match); }
// try to scan string literal (usual or interpolated) // usual string: "<chars and escapes>" // interp. string: $"<chars and escapes>" private ScanResult ScanString(InnerScan inner, out SourceToken token) { return(FromTo("\"", "\"", false, inner, false, out token)); }
/// <summary> /// HealthPlanetから取得したデータの整形 /// </summary> /// <param name="healthData"></param> /// <returns></returns> private (bool isSuccess, string height, List <HealthData> healthDataList) ShapeHealthData(InnerScan healthData) { var healthPlanetDataList = new List <HealthData>(); //取得データから日付を抜き出す var healthDateList = healthData.Data.Select(x => x.Date).Distinct().ToList(); //取得データをリスト変換 foreach (var date in healthDateList) { var healthList = healthData.Data .Where(r => date.Equals(r.Date)) .ToDictionary(x => x.Tag, x => x.Keydata); healthPlanetDataList.Add(new HealthData(date, healthList)); } return(true, healthData.Height, healthPlanetDataList); }