Propagating parse errors to JLine, can I do better?

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

Propagating parse errors to JLine, can I do better?

binarytemple

Hi there, for fun I'm writing a small command line spreadsheet program, in Scala.

(Yeah, for fun).

The real reason is because I want to Grok JLine and Parboiled a bit better.

Anyhow I'm trying to propagate parsing errors to the JLine, so that I can

a) Suggest completions

and

b) Correct errors

With that in mind, I create a:

val runner = RecoveringParseRunner(qtp.FormulaExtractor, 1000l)

Then, upon failure, catch the Exception, and extract the ParseErrors fom the runner, like so:

val collect: List[FormulaParseFail] = runner.inner.getParseErrors.toList.collect {
          case i: InvalidInputError =>
            FormulaParseFail(i.getStartIndex, i.getEndIndex, i.getInputBuffer, i.getIndexDelta,
              i.getFailedMatchers.toList.map(_.element.matcher.getLabel).map {
                case QuoteStripper(x) => x
              })
        }
        Left(collect.head)

Those errors contain lots of useful information, like where it failed, and what Rules it actually expected to match.

So I've implemented this, and it works OK, but the fact that element.matcher.getLabel - for something like:

SUM , will return 'SUM' - concerns me somewhat because it feels like I'm accessing the API incorrectly.

I mean, I can strip the quotes off, using something like:

val QuoteStripper = """^'([^']*)'$""".r

But it feels like I'm doing it wrong, is this the correct way to propagate parse errors for correction?

Thanks,

Bryan Hunt
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: Propagating parse errors to JLine, can I do better?

binarytemple
Hmm. I was doing it wrong, presumably this is closer to correctness.

   catch {
      case t: Throwable =>
        import scala.collection.JavaConversions._

          //On invalid input we try to resolve the logest posible sucessive token
          val collect = runner.inner.getParseErrors.toList.collectFirst {

          case i: InvalidInputError =>
            val fails = i.getFailedMatchers.toList.map{
              mp:MatcherPath =>
                mp.element.matcher match {
                  case cm:CharMatcher => mp.parent.element.matcher match {
                    case fsm:FirstOfStringsMatcher => fsm.strings.toList.map(new String(_))
                    case sm:StringMatcher => List (new String(sm.characters))
                    case _ => List(cm.character.toString)
                  }
                }
            }.flatten
            FormulaParseFail(i.getStartIndex, i.getEndIndex, i.getInputBuffer, i.getIndexDelta,fails)
          }
        Left(collect.get)
    }
Loading...