Function to parse .NET composite string formatComposite GetHashCode functionUse of the composite...

What is Cash Advance APR?

copy and scale one figure (wheel)

Has any country ever had 2 former presidents in jail simultaneously?

What is going on with 'gets(stdin)' on the site coderbyte?

How create a shell/bash script for some Linux command?

Does a 'pending' US visa application constitute a denial?

The probability of Bus A arriving before Bus B

Creating nested elements dynamically

Why did the EU agree to delay the Brexit deadline?

Strong empirical falsification of quantum mechanics based on vacuum energy density

Does the Location of Line-Dash-Wedge Notations Matter?

Does Doodling or Improvising on the Piano Have Any Benefits?

Is there any references on the tensor product of presentable (1-)categories?

Count the occurrence of each unique word in the file

What does "Scientists rise up against statistical significance" mean? (Comment in Nature)

Freedom of speech and where it applies

What will be next at the bottom row and why?

How can "mimic phobia" be cured or prevented?

Can I sign legal documents with a smiley face?

Are paving bricks differently sized for sand bedding vs mortar bedding?

Aragorn's "guise" in the Orthanc Stone

Is preaching recommended or mandatory to a temple priest?

Added a new user on Ubuntu, set password not working?

The screen of my macbook suddenly broken down how can I do to recover



Function to parse .NET composite string format


Composite GetHashCode functionUse of the composite patternSprite animation handlerAdding compile-time format validation to your string.Format callsParse a string to get a SectorIdProject Euler #11 Largest product in a gridTDD - Kata - String Calculator“How are you spending your time on the computer?” Part 2Determine Groups and Children In CollectionObject-oriented Bank class













6












$begingroup$


When generating a string representation of expression trees, I would like to render calls to String.Format with a constant string as the first parameter, as interpolated strings (link). In order to do so, I have to parse the compiler-generated composite format string.



I've written the following function for this purpose, based on the .NET Core parsing function. I am looking primarily for review in:




  • correctness, even in edge cases

  • clarity / readability




The function returns an array of tuples. Each tuple contains the following elements:




  1. literal string until the next placeholder

  2. index of placeholder

  3. alignment

  4. item format


If there is literal text after the last placeholder, it will be added as the last tuple of the array (other elements of the tuple will be null).





The function defines 3 local functions:





  • advanceChar -- advances the current position (pos) by one character, and stores the current character (ch)


  • skipWhitespace -- advances the current position as long as the current character is a space


  • getNumber -- gets a multi-digit number starting from the current position; ignores leading/trailing whitespace




public static (string literal, int? index, int? alignment, string itemFormat)[] ParseFormatString(string format) {
const int indexLimit = 1000000;
const int alignmentLimit = 100000;

int pos = -1;
char ch = 'x0';
int lastPos = format.Length - 1;

var parts = new List<(string literal, int? index, int? alignment, string itemFormat)>();

while (true) {

// Parse literal until argument placeholder
string literal = "";
while (pos < lastPos) {
advanceChar();

if (ch == '}') {
advanceChar();
if (ch == '}') {
literal += '}';
} else {
throw new Exception("Mismatched end brace");
}
} else if (ch == '{') {
advanceChar();
if (ch == '{') {
literal += '{';
} else {
break;
}
} else {
literal += ch;
}
}

if (pos == lastPos) {
if (literal != "") {
parts.Add((literal, (int?)null, (int?)null, (string)null));
}
break;
}

// Parse index section; required
int index = getNumber(indexLimit);

// Parse alignment; optional
int? alignment = null;
if (ch == ',') {
advanceChar();
alignment = getNumber(alignmentLimit, true);
}

// Parse item format; optional
string itemFormat = null;
if (ch == ':') {
advanceChar();
if (ch == '{') {
advanceChar();
if (ch == '{') {
itemFormat += '{';
} else {
throw new Exception("Nested placeholders not allowed");
}
} else if (ch == '}') {
advanceChar();
if (ch=='}') {
itemFormat += '}';
} else {
break;
}
} else {
itemFormat += ch;
}
}

parts.Add((literal, index, alignment, itemFormat));
}

return parts.ToArray();

void advanceChar(bool ignoreEnd = false) {
pos += 1;
if (pos <= lastPos) {
ch = format[pos];
} else if (ignoreEnd) {
ch = 'x0';
} else {
throw new Exception("Unexpected end of text");
}
}

void skipWhitespace() {
while (ch == ' ') {
advanceChar(true);
}
}

int getNumber(int limit, bool allowNegative = false) {
skipWhitespace();

bool isNegative = false;
if (allowNegative && ch == '-') {
isNegative = true;
advanceChar();
}
if (ch < '0' || ch > '9') { throw new Exception("Expected digit"); }
int ret = 0;
do {
ret = ret * 10 + ch - '0';
advanceChar();
} while (ch >= '0' && ch <= '9' && ret < limit);

skipWhitespace();

return ret * (isNegative ? -1 : 1);
}
}









share|improve this question









$endgroup$

















    6












    $begingroup$


    When generating a string representation of expression trees, I would like to render calls to String.Format with a constant string as the first parameter, as interpolated strings (link). In order to do so, I have to parse the compiler-generated composite format string.



    I've written the following function for this purpose, based on the .NET Core parsing function. I am looking primarily for review in:




    • correctness, even in edge cases

    • clarity / readability




    The function returns an array of tuples. Each tuple contains the following elements:




    1. literal string until the next placeholder

    2. index of placeholder

    3. alignment

    4. item format


    If there is literal text after the last placeholder, it will be added as the last tuple of the array (other elements of the tuple will be null).





    The function defines 3 local functions:





    • advanceChar -- advances the current position (pos) by one character, and stores the current character (ch)


    • skipWhitespace -- advances the current position as long as the current character is a space


    • getNumber -- gets a multi-digit number starting from the current position; ignores leading/trailing whitespace




    public static (string literal, int? index, int? alignment, string itemFormat)[] ParseFormatString(string format) {
    const int indexLimit = 1000000;
    const int alignmentLimit = 100000;

    int pos = -1;
    char ch = 'x0';
    int lastPos = format.Length - 1;

    var parts = new List<(string literal, int? index, int? alignment, string itemFormat)>();

    while (true) {

    // Parse literal until argument placeholder
    string literal = "";
    while (pos < lastPos) {
    advanceChar();

    if (ch == '}') {
    advanceChar();
    if (ch == '}') {
    literal += '}';
    } else {
    throw new Exception("Mismatched end brace");
    }
    } else if (ch == '{') {
    advanceChar();
    if (ch == '{') {
    literal += '{';
    } else {
    break;
    }
    } else {
    literal += ch;
    }
    }

    if (pos == lastPos) {
    if (literal != "") {
    parts.Add((literal, (int?)null, (int?)null, (string)null));
    }
    break;
    }

    // Parse index section; required
    int index = getNumber(indexLimit);

    // Parse alignment; optional
    int? alignment = null;
    if (ch == ',') {
    advanceChar();
    alignment = getNumber(alignmentLimit, true);
    }

    // Parse item format; optional
    string itemFormat = null;
    if (ch == ':') {
    advanceChar();
    if (ch == '{') {
    advanceChar();
    if (ch == '{') {
    itemFormat += '{';
    } else {
    throw new Exception("Nested placeholders not allowed");
    }
    } else if (ch == '}') {
    advanceChar();
    if (ch=='}') {
    itemFormat += '}';
    } else {
    break;
    }
    } else {
    itemFormat += ch;
    }
    }

    parts.Add((literal, index, alignment, itemFormat));
    }

    return parts.ToArray();

    void advanceChar(bool ignoreEnd = false) {
    pos += 1;
    if (pos <= lastPos) {
    ch = format[pos];
    } else if (ignoreEnd) {
    ch = 'x0';
    } else {
    throw new Exception("Unexpected end of text");
    }
    }

    void skipWhitespace() {
    while (ch == ' ') {
    advanceChar(true);
    }
    }

    int getNumber(int limit, bool allowNegative = false) {
    skipWhitespace();

    bool isNegative = false;
    if (allowNegative && ch == '-') {
    isNegative = true;
    advanceChar();
    }
    if (ch < '0' || ch > '9') { throw new Exception("Expected digit"); }
    int ret = 0;
    do {
    ret = ret * 10 + ch - '0';
    advanceChar();
    } while (ch >= '0' && ch <= '9' && ret < limit);

    skipWhitespace();

    return ret * (isNegative ? -1 : 1);
    }
    }









    share|improve this question









    $endgroup$















      6












      6








      6





      $begingroup$


      When generating a string representation of expression trees, I would like to render calls to String.Format with a constant string as the first parameter, as interpolated strings (link). In order to do so, I have to parse the compiler-generated composite format string.



      I've written the following function for this purpose, based on the .NET Core parsing function. I am looking primarily for review in:




      • correctness, even in edge cases

      • clarity / readability




      The function returns an array of tuples. Each tuple contains the following elements:




      1. literal string until the next placeholder

      2. index of placeholder

      3. alignment

      4. item format


      If there is literal text after the last placeholder, it will be added as the last tuple of the array (other elements of the tuple will be null).





      The function defines 3 local functions:





      • advanceChar -- advances the current position (pos) by one character, and stores the current character (ch)


      • skipWhitespace -- advances the current position as long as the current character is a space


      • getNumber -- gets a multi-digit number starting from the current position; ignores leading/trailing whitespace




      public static (string literal, int? index, int? alignment, string itemFormat)[] ParseFormatString(string format) {
      const int indexLimit = 1000000;
      const int alignmentLimit = 100000;

      int pos = -1;
      char ch = 'x0';
      int lastPos = format.Length - 1;

      var parts = new List<(string literal, int? index, int? alignment, string itemFormat)>();

      while (true) {

      // Parse literal until argument placeholder
      string literal = "";
      while (pos < lastPos) {
      advanceChar();

      if (ch == '}') {
      advanceChar();
      if (ch == '}') {
      literal += '}';
      } else {
      throw new Exception("Mismatched end brace");
      }
      } else if (ch == '{') {
      advanceChar();
      if (ch == '{') {
      literal += '{';
      } else {
      break;
      }
      } else {
      literal += ch;
      }
      }

      if (pos == lastPos) {
      if (literal != "") {
      parts.Add((literal, (int?)null, (int?)null, (string)null));
      }
      break;
      }

      // Parse index section; required
      int index = getNumber(indexLimit);

      // Parse alignment; optional
      int? alignment = null;
      if (ch == ',') {
      advanceChar();
      alignment = getNumber(alignmentLimit, true);
      }

      // Parse item format; optional
      string itemFormat = null;
      if (ch == ':') {
      advanceChar();
      if (ch == '{') {
      advanceChar();
      if (ch == '{') {
      itemFormat += '{';
      } else {
      throw new Exception("Nested placeholders not allowed");
      }
      } else if (ch == '}') {
      advanceChar();
      if (ch=='}') {
      itemFormat += '}';
      } else {
      break;
      }
      } else {
      itemFormat += ch;
      }
      }

      parts.Add((literal, index, alignment, itemFormat));
      }

      return parts.ToArray();

      void advanceChar(bool ignoreEnd = false) {
      pos += 1;
      if (pos <= lastPos) {
      ch = format[pos];
      } else if (ignoreEnd) {
      ch = 'x0';
      } else {
      throw new Exception("Unexpected end of text");
      }
      }

      void skipWhitespace() {
      while (ch == ' ') {
      advanceChar(true);
      }
      }

      int getNumber(int limit, bool allowNegative = false) {
      skipWhitespace();

      bool isNegative = false;
      if (allowNegative && ch == '-') {
      isNegative = true;
      advanceChar();
      }
      if (ch < '0' || ch > '9') { throw new Exception("Expected digit"); }
      int ret = 0;
      do {
      ret = ret * 10 + ch - '0';
      advanceChar();
      } while (ch >= '0' && ch <= '9' && ret < limit);

      skipWhitespace();

      return ret * (isNegative ? -1 : 1);
      }
      }









      share|improve this question









      $endgroup$




      When generating a string representation of expression trees, I would like to render calls to String.Format with a constant string as the first parameter, as interpolated strings (link). In order to do so, I have to parse the compiler-generated composite format string.



      I've written the following function for this purpose, based on the .NET Core parsing function. I am looking primarily for review in:




      • correctness, even in edge cases

      • clarity / readability




      The function returns an array of tuples. Each tuple contains the following elements:




      1. literal string until the next placeholder

      2. index of placeholder

      3. alignment

      4. item format


      If there is literal text after the last placeholder, it will be added as the last tuple of the array (other elements of the tuple will be null).





      The function defines 3 local functions:





      • advanceChar -- advances the current position (pos) by one character, and stores the current character (ch)


      • skipWhitespace -- advances the current position as long as the current character is a space


      • getNumber -- gets a multi-digit number starting from the current position; ignores leading/trailing whitespace




      public static (string literal, int? index, int? alignment, string itemFormat)[] ParseFormatString(string format) {
      const int indexLimit = 1000000;
      const int alignmentLimit = 100000;

      int pos = -1;
      char ch = 'x0';
      int lastPos = format.Length - 1;

      var parts = new List<(string literal, int? index, int? alignment, string itemFormat)>();

      while (true) {

      // Parse literal until argument placeholder
      string literal = "";
      while (pos < lastPos) {
      advanceChar();

      if (ch == '}') {
      advanceChar();
      if (ch == '}') {
      literal += '}';
      } else {
      throw new Exception("Mismatched end brace");
      }
      } else if (ch == '{') {
      advanceChar();
      if (ch == '{') {
      literal += '{';
      } else {
      break;
      }
      } else {
      literal += ch;
      }
      }

      if (pos == lastPos) {
      if (literal != "") {
      parts.Add((literal, (int?)null, (int?)null, (string)null));
      }
      break;
      }

      // Parse index section; required
      int index = getNumber(indexLimit);

      // Parse alignment; optional
      int? alignment = null;
      if (ch == ',') {
      advanceChar();
      alignment = getNumber(alignmentLimit, true);
      }

      // Parse item format; optional
      string itemFormat = null;
      if (ch == ':') {
      advanceChar();
      if (ch == '{') {
      advanceChar();
      if (ch == '{') {
      itemFormat += '{';
      } else {
      throw new Exception("Nested placeholders not allowed");
      }
      } else if (ch == '}') {
      advanceChar();
      if (ch=='}') {
      itemFormat += '}';
      } else {
      break;
      }
      } else {
      itemFormat += ch;
      }
      }

      parts.Add((literal, index, alignment, itemFormat));
      }

      return parts.ToArray();

      void advanceChar(bool ignoreEnd = false) {
      pos += 1;
      if (pos <= lastPos) {
      ch = format[pos];
      } else if (ignoreEnd) {
      ch = 'x0';
      } else {
      throw new Exception("Unexpected end of text");
      }
      }

      void skipWhitespace() {
      while (ch == ' ') {
      advanceChar(true);
      }
      }

      int getNumber(int limit, bool allowNegative = false) {
      skipWhitespace();

      bool isNegative = false;
      if (allowNegative && ch == '-') {
      isNegative = true;
      advanceChar();
      }
      if (ch < '0' || ch > '9') { throw new Exception("Expected digit"); }
      int ret = 0;
      do {
      ret = ret * 10 + ch - '0';
      advanceChar();
      } while (ch >= '0' && ch <= '9' && ret < limit);

      skipWhitespace();

      return ret * (isNegative ? -1 : 1);
      }
      }






      c#






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 14 at 12:08









      Zev SpitzZev Spitz

      1789




      1789






















          1 Answer
          1






          active

          oldest

          votes


















          8












          $begingroup$

          Problems:



          Item format parsing is broken:





          • "{0:X2}" fails with an 'Unexpected end of text' exception, while "{0:X2}a" fails with a 'Mismatched end brace' exception. Both are valid formats.


          • "{0:}" also fails with an 'Unexpected end of text' exception, but "{0:}a" returns an empty array instead. Both are valid formats.


          • "{0:{{" and "{0:}}" are parsed successfully. Both should be rejected as invalid.


          Improvements:




          • The index and alignment limits seem fairly arbitrary. If they're based on an actual limit it would be a good idea to document that. Also, exceeding those limits results in a misleading 'Mismatched end brace' error.

          • I'd recommend using a more specific exception exception type. The existing FormatException seems appropriate here.

          • For repeated string concatenation, a StringBuilder is (significantly) more efficient.

          • The exceptions don't provide much detail. It would be useful to know at what index the problem was detected, or what the parser was expecting when it hit the end of the input.

          • The main while loop body is fairly drawn out. If you're using local functions anyway, why not split things up further into a ParseLiteralPart and ParseFormatPart function?






          share|improve this answer









          $endgroup$









          • 2




            $begingroup$
            mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
            $endgroup$
            – t3chb0t
            Mar 14 at 15:08












          • $begingroup$
            @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
            $endgroup$
            – Zev Spitz
            Mar 14 at 22:46










          • $begingroup$
            @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
            $endgroup$
            – t3chb0t
            Mar 15 at 9:17











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215417%2ffunction-to-parse-net-composite-string-format%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          1 Answer
          1






          active

          oldest

          votes








          1 Answer
          1






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          8












          $begingroup$

          Problems:



          Item format parsing is broken:





          • "{0:X2}" fails with an 'Unexpected end of text' exception, while "{0:X2}a" fails with a 'Mismatched end brace' exception. Both are valid formats.


          • "{0:}" also fails with an 'Unexpected end of text' exception, but "{0:}a" returns an empty array instead. Both are valid formats.


          • "{0:{{" and "{0:}}" are parsed successfully. Both should be rejected as invalid.


          Improvements:




          • The index and alignment limits seem fairly arbitrary. If they're based on an actual limit it would be a good idea to document that. Also, exceeding those limits results in a misleading 'Mismatched end brace' error.

          • I'd recommend using a more specific exception exception type. The existing FormatException seems appropriate here.

          • For repeated string concatenation, a StringBuilder is (significantly) more efficient.

          • The exceptions don't provide much detail. It would be useful to know at what index the problem was detected, or what the parser was expecting when it hit the end of the input.

          • The main while loop body is fairly drawn out. If you're using local functions anyway, why not split things up further into a ParseLiteralPart and ParseFormatPart function?






          share|improve this answer









          $endgroup$









          • 2




            $begingroup$
            mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
            $endgroup$
            – t3chb0t
            Mar 14 at 15:08












          • $begingroup$
            @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
            $endgroup$
            – Zev Spitz
            Mar 14 at 22:46










          • $begingroup$
            @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
            $endgroup$
            – t3chb0t
            Mar 15 at 9:17
















          8












          $begingroup$

          Problems:



          Item format parsing is broken:





          • "{0:X2}" fails with an 'Unexpected end of text' exception, while "{0:X2}a" fails with a 'Mismatched end brace' exception. Both are valid formats.


          • "{0:}" also fails with an 'Unexpected end of text' exception, but "{0:}a" returns an empty array instead. Both are valid formats.


          • "{0:{{" and "{0:}}" are parsed successfully. Both should be rejected as invalid.


          Improvements:




          • The index and alignment limits seem fairly arbitrary. If they're based on an actual limit it would be a good idea to document that. Also, exceeding those limits results in a misleading 'Mismatched end brace' error.

          • I'd recommend using a more specific exception exception type. The existing FormatException seems appropriate here.

          • For repeated string concatenation, a StringBuilder is (significantly) more efficient.

          • The exceptions don't provide much detail. It would be useful to know at what index the problem was detected, or what the parser was expecting when it hit the end of the input.

          • The main while loop body is fairly drawn out. If you're using local functions anyway, why not split things up further into a ParseLiteralPart and ParseFormatPart function?






          share|improve this answer









          $endgroup$









          • 2




            $begingroup$
            mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
            $endgroup$
            – t3chb0t
            Mar 14 at 15:08












          • $begingroup$
            @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
            $endgroup$
            – Zev Spitz
            Mar 14 at 22:46










          • $begingroup$
            @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
            $endgroup$
            – t3chb0t
            Mar 15 at 9:17














          8












          8








          8





          $begingroup$

          Problems:



          Item format parsing is broken:





          • "{0:X2}" fails with an 'Unexpected end of text' exception, while "{0:X2}a" fails with a 'Mismatched end brace' exception. Both are valid formats.


          • "{0:}" also fails with an 'Unexpected end of text' exception, but "{0:}a" returns an empty array instead. Both are valid formats.


          • "{0:{{" and "{0:}}" are parsed successfully. Both should be rejected as invalid.


          Improvements:




          • The index and alignment limits seem fairly arbitrary. If they're based on an actual limit it would be a good idea to document that. Also, exceeding those limits results in a misleading 'Mismatched end brace' error.

          • I'd recommend using a more specific exception exception type. The existing FormatException seems appropriate here.

          • For repeated string concatenation, a StringBuilder is (significantly) more efficient.

          • The exceptions don't provide much detail. It would be useful to know at what index the problem was detected, or what the parser was expecting when it hit the end of the input.

          • The main while loop body is fairly drawn out. If you're using local functions anyway, why not split things up further into a ParseLiteralPart and ParseFormatPart function?






          share|improve this answer









          $endgroup$



          Problems:



          Item format parsing is broken:





          • "{0:X2}" fails with an 'Unexpected end of text' exception, while "{0:X2}a" fails with a 'Mismatched end brace' exception. Both are valid formats.


          • "{0:}" also fails with an 'Unexpected end of text' exception, but "{0:}a" returns an empty array instead. Both are valid formats.


          • "{0:{{" and "{0:}}" are parsed successfully. Both should be rejected as invalid.


          Improvements:




          • The index and alignment limits seem fairly arbitrary. If they're based on an actual limit it would be a good idea to document that. Also, exceeding those limits results in a misleading 'Mismatched end brace' error.

          • I'd recommend using a more specific exception exception type. The existing FormatException seems appropriate here.

          • For repeated string concatenation, a StringBuilder is (significantly) more efficient.

          • The exceptions don't provide much detail. It would be useful to know at what index the problem was detected, or what the parser was expecting when it hit the end of the input.

          • The main while loop body is fairly drawn out. If you're using local functions anyway, why not split things up further into a ParseLiteralPart and ParseFormatPart function?







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Mar 14 at 13:33









          Pieter WitvoetPieter Witvoet

          6,444826




          6,444826








          • 2




            $begingroup$
            mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
            $endgroup$
            – t3chb0t
            Mar 14 at 15:08












          • $begingroup$
            @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
            $endgroup$
            – Zev Spitz
            Mar 14 at 22:46










          • $begingroup$
            @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
            $endgroup$
            – t3chb0t
            Mar 15 at 9:17














          • 2




            $begingroup$
            mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
            $endgroup$
            – t3chb0t
            Mar 14 at 15:08












          • $begingroup$
            @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
            $endgroup$
            – Zev Spitz
            Mar 14 at 22:46










          • $begingroup$
            @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
            $endgroup$
            – t3chb0t
            Mar 15 at 9:17








          2




          2




          $begingroup$
          mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
          $endgroup$
          – t3chb0t
          Mar 14 at 15:08






          $begingroup$
          mhmm... based on your findings I'm thinking of flagging the question as not-working-code...
          $endgroup$
          – t3chb0t
          Mar 14 at 15:08














          $begingroup$
          @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
          $endgroup$
          – Zev Spitz
          Mar 14 at 22:46




          $begingroup$
          @t3chb0t I've identified and fixed the problems (still working on the improvements); should I edit the code in the question? Should I close this and reopen another question?
          $endgroup$
          – Zev Spitz
          Mar 14 at 22:46












          $begingroup$
          @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
          $endgroup$
          – t3chb0t
          Mar 15 at 9:17




          $begingroup$
          @ZevSpitz nope, editing the code is not allowed when there are already answers. What you can do is to either add a self-answer or ask a follow-up question if you'd like to have another review.
          $endgroup$
          – t3chb0t
          Mar 15 at 9:17


















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f215417%2ffunction-to-parse-net-composite-string-format%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Fairchild Swearingen Metro Inhaltsverzeichnis Geschichte | Innenausstattung | Nutzung | Zwischenfälle...

          Pilgersdorf Inhaltsverzeichnis Geografie | Geschichte | Bevölkerungsentwicklung | Politik | Kultur...

          Marineschifffahrtleitung Inhaltsverzeichnis Geschichte | Heutige Organisation der NATO | Nationale und...