Parsing language with continuation and comment

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Parsing language with continuation and comment

vincenth
Hi,

I have to parse a programming language with a continuation character, and am wondering whether there is a simple way to do it using parboiled version 1.1.7.
Any advice on my rules pasted below is also welcome - I am a beginner in terms of parsing :)


In the considered language:
- Each line can start by a numerical label, or an alphabetical label followed by ":".
- A line continuation is indicated by "_" (as long as "_" is not part of a comment). This continuation can occur in the middle of a "quoted" text. Any character on the same line after "_" is treated as comment and ignored.
- The start of a comment on a line is indicated by "!" (as long as this "!" is not part of a quoted text), and the comment goes up to the end of the line.
- Quoted text is text between two similar quote characters, either " or '.

For example:
WRITSRC: FORMAT "QPASS$ = ";QPASS$;(CR);_!COMMENT"                              
                "!MESSAGE$ =";MESSAGE$;(CR);"HELLO_                            
               MY FRIEND";(CR)
becomes:
WRITSRC: FORMAT "QPASS$ = ";QPASS$;(CR);"!MESSAGE$ =";MESSAGE$;(CR);"HELLO       MY FRIEND";(CR)

Currently, I managed this with the following rules, but they appear a bit heavy for use:
@Override
        public Rule InputContent() {
                return Sequence(Code(), EOI);
        }
   
        public Rule Code() {
                return ZeroOrMore(CodeLine());
        }
       
        // -------------------------------------------------------------------------------------
        // --   MAJOR RULE TO PARSE CODE LINE
        // -------------------------------------------------------------------------------------
        public Rule CodeLine() {
                return Sequence(
                                Optional(SpaceOrContinuation()).skipNode(),
                                FirstOf(
                                        FormatStatement(),
                                        Sequence(
                                                Optional(Sequence(Label(),SpaceOrContinuation())).skipNode(),
                                                Optional(Statement()).skipNode()
                                                        )
                                                ).skipNode(),
                                ZeroOrMore(
                                                Sequence(
                                                                StatementSeparatorOnLine(),
                                                                Statement()
                                                                )
                                                ).skipNode(),
                                        Optional(Comment()).skipNode(),
                                        EndOfLine()
                                        );
        }

// -------------------------------------------------------------------------------------
// --   RULES TO PARSE STANDARD STATEMENTS
// -------------------------------------------------------------------------------------
       
        public Rule Statement() {
                return ZeroOrMore(
                                Sequence(
                                                FirstOf(
                                                                Quote(),
                                                                Text()
                                                                ).skipNode(),
                                                OneOrMore(
                                                                FirstOf(
                                                                                Separator(),
                                                                                SpaceOrContinuation()
                                                                                ).skipNode()
                                                                )
                                                ).skipNode()
                                );
        }
...

// -------------------------------------------------------------------------------------
// --   RULES TO PARSE NON-FORMAT STATEMENTS
// -------------------------------------------------------------------------------------
       
        @SuppressSubnodes
        public Rule Text() {
                return OneOrMore(NoneOf(nonWordCharacters));
        }

// -------------------------------------------------------------------------------------
        // --   BASIC PARSING RULES
        // -------------------------------------------------------------------------------------
        @SuppressSubnodes
        public Rule EndOfLine() {
                return Sequence(Optional("\r"),
                                "\n"
                                );
        }
       
        public Rule Quote() {
                return FirstOf(
                                Sequence("\"",
                                                QuoteContent(),
                                                "\""),
                                Sequence("\'",
                                                QuoteContent(),
                                                "\'").skipNode()
                                );
        }
       
        @SuppressSubnodes
        public Rule QuoteContent() {
                return ZeroOrMore(FirstOf(NoneOf(nonQuoteCharacters),Continuation()));
        }
       
        @SuppressSubnodes
        public Rule Comment() {
                return Sequence("!",
                                ZeroOrMore(NoneOf("\n"))
                                );
        }
       
        @SuppressSubnodes
        public Rule Label() {
                return FirstOf(
                                Digits(),
                                Sequence(OneOrMore(CharRange('A', 'Z')),":" )
                                );
        }
       
        public Rule LabelValue() {
                return FirstOf(
                                Digits(),
                                OneOrMore(CharRange('A', 'Z'))
                                );
        }
       
        public Rule Continuation() {
                return Sequence(
                                "_",
                                ZeroOrMore(NoneOf("\n")),
                                "\n");
        }
       
        public Rule ExtendedContinuation() {
                return Sequence(Continuation(),
                                ZeroOrMore(SpaceOrContinuation()));
        }
       
        public Rule NumericValue() {
                return Sequence(
                                Digits(),
                                Optional(
                                                Sequence(
                                                                ".",
                                                                Digits()
                                                                )
                                                )
                                );
        }
       
        @SuppressSubnodes
        public Rule Digits() {
                return OneOrMore(Digit());
        }
       
        public Rule Digit() {
                return CharRange('0', '9');
        }
       
        public Rule Separator() {
                return AnyOf(separators);
        }
       
        @SuppressSubnodes
        public Rule StatementSeparatorOnLine() {
                return Sequence(ZeroOrMore(SpaceOrContinuation()),
                                '&',
                                ZeroOrMore(SpaceOrContinuation()));
        }
       
        @SuppressSubnodes
        public Rule SpaceOrContinuation() {
                return FirstOf(ExtendedContinuation(),OneOrMore(AnyOf(whiteSpacesOrContinuation)));
        }
       
Loading...