Parsing indentation with FastParse

326 Views Asked by At

I'm trying to parse an indented language using FastParse and I'm struggling finding any resources or information on it.
There is only one example I can find here that shows how to parse and calculate the sum of the integers in the tree structure. I've tried copying this code but I get the same error where it fails parsing \n.

I would like to parse this.

example
  1
  2
  3

Code

import fastparse.all._

class ExampleParser(indent: Int) {

  val word: P[String] = P("example".!)

  val number: P[String] = P( CharIn('0'to'9').rep(1).! )

  val blockBody: P[Seq[String]] = "\n" ~ deeper.flatMap(i => new ExampleParser(indent = i).number.rep(1, sep = ("\n" + " " * i).~/))

  val deeper: P[Int] = P(" ".rep(indent + 1).!.map(_.length))

  val section: P[(String, Seq[String])] = P(word ~ blockBody)

  val expr: P[(String, Seq[String])] = P(section)

}

object Main
{
  def main(args: Array[String]) =
  {
    check(
      """example
        |  1
        |  2
        |  3
      """.stripMargin.trim

    )
    println()
  }

  def check(str: String) = {
    new ExampleParser(0).expr.parse(str) match {
      case Parsed.Success(value, _) => println(value)
      case Parsed.Failure(a, b, c) => println("Failure:" + a + ":" + b + ":" + c)
    }
  }
}

Output

Failure:"\n":7:Extra(...ample
1
2
3, [traced - not evaluated])

How can I parse this correctly?

1

There are 1 best solutions below

4
On

If I change "expression" to "example":

check (
  """example
    |  1
    |  2
    |  3
  """.stripMargin.trim
)

I get the result:

[info] Running Main 
(example,ArrayBuffer(1, 2, 3))

Of course you might like to change it the other way round.