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.