Open Source Journaling: Cornerstone

I was a bit fried and looking to escape from work, so I played around with Cornerstone a bit tonight. The key focus right now has been the parser of Cornerstone, which is written in Scala.

In Cornerstone, there are what I’m calling the “mirror operators”[1]. Like OCaml, Haskell, and Scala, the user can define operators. In Cornerstone, one of these operators is “[", or "[" followed by some arbtirary sequence of symbols. So these are potential operators:
[ foo ]
[| foo |]
[|> foo <|]

I was trying to figure out how to get a the parser combinator library to express that "mirrored" concept, and someone pointed me to the (undocumented) into construct: http://paste.pocoo.org/show/102878/. So I went to town on that.

The resulting code looks like this:

  def mirrorCreate(given:CSParser.~[CSExpression,Operator]):Parser[MirrorExpression] = given match {
    case outr ~ Operator(sym) => {
      val mirrored = StringUtils.replaceChars(StringUtils.reverse(sym), """<>{}[]/""", """><}{][/""")
      return (opt(ws) ~> expression <~ opt(ws) <~ (mirrored + "]") ^^ {
        MirrorExpression(Operator("[" + sym), Operator(mirrored + "]"), outr, _)
      })
    }
  }
 
  def mirror_apply : Parser[MirrorExpression] = positioned(
    ((expression ~ (opt(ws) ~> "[" ~> operator)) into mirrorCreate)
  )

I ran into a problem while writing up this code -- I needed to import Commons-Lang, but for reasons that still escape me, Scala was freaking out because there was another package that used the word "lang". So I ended up having to use the (undocumented) _root_ construct:

import _root_.cstone.lang.CSRational
import java.math.BigInteger
import java.math.BigDecimal
import _root_.org.apache.commons.lang._

Thanks to #scala on FreeNode for tipping me off to both these undocumented features.

The only other interesting thing is that I was a bit bummed to discover case statements need explicit match calls on them. In OCaml, I can write something like the following:

let f = function |1 -> ... |2 -> .... |_ ->  ...

But there's no such beast in Scala. I tried leaving off the given match in the code above, and the compiler bombed out on me. Bad times.

Next up for Cornerstone is implementing operator precedence in the parser. There's a kinda half-assed implementation of operators which worked for the moment. I really want to wrap a lot of unit tests around the operator precedence stuff, though, because it's tricky.

[1]Brian actually came up with this idea, which I think is somewhat brilliant.

No related posts.

This entry was posted in Ashlar/Cornerstone, Open Source Journaling. Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.
  • Johannes Rudolph

    _root_ is documented in section 9.3 of the current Scala Language Reference. There is a somewhat lengthy mailing list discussion from last year about the way Scala’s nested packages work and how they may be non-intuitive to Java users.

    Pattern matching without cases is possible for anonymous function with one parameter, so if you rewrite mirrorCreate into a function value it should possibly work.

  • http://www.smokejumperit.com Robert Fischer

    Thanks. You’re +2 over the IRC channel.

    Is the “Scala Language Specification” you’re talking about the one linked to at http://www.scala-lang.org/node/198?

  • Johannes

    Yeah, that’s the spec I meant.

    Actually, about the implicit pattern matching: I found that out, just a few weeks ago, because I wondered how scala parser generators

    ^^ {case bla ~ blub => //…}

    works. And it turned out, that ^^ just accepts a function.

  • http://www.smokejumperit.com Robert Fischer

    Yeah, I pull that same stunt elsewhere in my parser, which is why I assumed it would work for a method, too. But apparently not.

  • Categories