public class CommentsAwareInput : Input{public CommentsAwareInput(string source): this(skipComments(new Input(source))){}private CommentsAwareInput(Input skipped): base(skipped.Source, skipped.Position, skipped.Line, skipped.Column){}public override Input Advance(){Input tmp = base.Advance();return new CommentsAwareInput(skipComments(tmp));}private static readonly Parser<char> Slash = Parse.Char('/');private static readonly Parser<char> Star = Parse.Char('*');private static readonly Parser<string> MultiLineComment = Star.Then(x =>Parse.AnyChar.Except(Star).XOr(Star.Then(s => Parse.AnyChar.Except(Slash))).Until(Parse.String("*/"))).Select(_ => "");private static readonly Parser<string> SingleLineComment = Slash.Then(x => Parse.AnyChar.Except(ParseEx.EndLine).Many()).Text();internal static readonly Parser<string> Comment = Slash.Then(s => MultiLineComment.XOr(SingleLineComment));private static Input skipComments(Input input){var result = Comment.Many().Select(_ => "")(input);var success = result as ISuccess<string>;if (success != null){return success.Remainder;}throw new ParseException(result.ToString());}}
public static class ParseEx{public static T ParseWithComments<T>(this Parser<T> parser, string input){if (parser == null) throw new ArgumentNullException("parser");if (input == null) throw new ArgumentNullException("input");var result = parser(new CommentsAwareInput(input));var success = result as ISuccess<T>;if (success != null)return success.Result;throw new ParseException(result.ToString());}}