Parsing nested structure

21 views
Skip to first unread message

sebi...@gmail.com

unread,
Nov 6, 2017, 3:44:43 PM11/6/17
to parboiled2.org User List
Hi,

I have the following input:

[[[
   some statements
   
[[[
      some more statements
   
]]]
   some
final statements
]]]


I would like to write a rule of type Rule1[String] that would consume the whole input and push on the stack the inner part of it (i.e. without the first set of brackets):

some statements
[[[
   some more statements
]]]
some
final statements



My current attempt is to use somethings like this:

def Start = rule { str("[[[") }


def End = rule { str("]]]") }


def Code = rule {
   
Start ~ capture(!End ~ ANY) ~ End
}


however, it fails to consume the entire input and stops when it first encounters "]]]"

Is there a way to do this? Somehow like:
def Code = rule {
   
Start ~ capture(!RULE ~ ANY) ~ End
}



where RULE would depend on how many occurrences of start / end tokens have been counted up to a certain point.

Many thanks in advance for some hints.

Kind regards,
Sebastian

sebi...@gmail.com

unread,
Nov 7, 2017, 1:12:26 AM11/7/17
to parboiled2.org User List
I finally came up with this implementation. Do you see any issues with it?

protected def Code: Rule1[ast.Text] = {
    var countStart = 0
    var countEnd = 0

    def lastTriplet = (charAt(-3) :: charAt(-2) :: charAt(-1) :: Nil).mkString

    def ValidCodeChar = {
        val lt = lastTriplet
        if (lt == BasicToken.CODE_START.entryName) countStart += 1
        if (lt == BasicToken.CODE_END.entryName) countEnd += 1

        if (countStart - countEnd > 1) {
            rule {
                ANY
            }
        }
        else {
            rule {
                !CodeEnd ~ ANY
            }
        }
    }

    rule {
        CodeStart ~
            capture(oneOrMore(ValidCodeChar)) ~
            CodeEnd ~>
            ((s: String) => ast.Text(Seq(ast.PlainText(s))))
    }
}

private def CodeEnd = rule {
    str("]]]")
}

private def CodeStart = rule {
    str("[[[")
}


Mathias Doenitz

unread,
Nov 7, 2017, 4:21:14 AM11/7/17
to parboil...@googlegroups.com
Hi Sebastian,

the key to recursive structures like the one you are trying to parse is to build a recursive grammar.
One solution to your problem might something along these lines:

```
def Code = rule { Start ~ capture(oneOrMore(Block)) ~ End }
def Block = rule { Start ~ oneOrMore(Statement) ~ End }
def Statement = rule { SimpleStatement | Block }
def SimpleStatement = rule { oneOrMore(!Start ~ ANY) }
def Start = rule { str("[[[") }
def End = rule { str("]]]") }
```

Hope that helps!

Cheers,
Mathias

---
mat...@parboiled.org
http://www.parboiled.org
> --
> You received this message because you are subscribed to the Google Groups "parboiled2.org User List" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to parboiled-use...@googlegroups.com.
> Visit this group at https://groups.google.com/group/parboiled-user.
> To view this discussion on the web visit https://groups.google.com/d/msgid/parboiled-user/dd5aef57-8e25-477a-b248-749eb6ecba79%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages