Comments

53 views
Skip to first unread message

Konstantin Nosov

unread,
Dec 1, 2011, 8:17:19 AM12/1/11
to sprache...@googlegroups.com
I need to have comments in parsed text. I.e. after any char there may be /* .... */ or  //
The only solution I've invented is implementing custom Input:

 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());
        }
    }

and extension method 

 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());
        }
    } 


Solution looks dirty since it required change in Input.cs code (virtual Advance and ctor visibility)  

Is there any better approach?

Nicholas Blumhardt

unread,
Dec 1, 2011, 11:01:48 PM12/1/11
to sprache...@googlegroups.com
Hi Konstantin,

I'm not sure with respect to your grammar how well this may work, however it is normal for comments to be valid at any location that whitespace is valid.

Sprache offers the Token() combinator to eat up and thus ignore whitespace - you can check out its implementation in the source.

My suggestion would be to create a custom implementation of Token() ("TokenPlus"? :)) that includes comments in the characters it eats up.

Then you can write:

   var identifier = Parse.LetterOrDigit.Many().TokenPlus()

to create a parser for an identifier that will ignore comments.

Cheers,
Nick

Konstantin Nosov

unread,
Dec 2, 2011, 3:11:42 AM12/2/11
to sprache...@googlegroups.com
Cool thanks. Your solution is better event from user experience perspective -  /* ... */ inside quotes should be treated as part of quoted text, not as comment. And I assume it is faster.

Reply all
Reply to author
Forward
0 new messages