I did another brief update to Cornerstone last night. When parsing floating point numbers, I *was* doing a parse of an integer, then the dot, then a series of digits, and gluing it all together afterwards. Fred Medlin at the Java Hack Night pointed out that was silly, and I should should parse the value directly as a regex. I went one step further, and jacked the BigDecimal String constructor’s BNF, but encoded as a regex.

So the number parsing now looks like this:

def float_number : Parser[BigDecimal] = (rawFloat <~ ("F"|"f")) def integer_number : Parser[BigInteger] = (rawInteger <~ ("Z"|"z")) def rational_number : Parser[CSRational] = ( (rawFloat ^^ { new CSRational(_) }) | fraction | (rawInteger ^^ { new CSRational(_) }) ) def fraction : Parser[CSRational] = ( ((rawInteger <~ "/") ~ rawNonzeroNatural) ^^ { case x ~ y => new CSRational(x,y) } ) def rawInteger: Parser[BigInteger] = ( ((opt("+") ~> """[01-9]+""".r) | """[-]?[01-9]+""".r) ^^ { new BigInteger(_) } ) def rawNonzeroNatural : Parser[BigInteger] = ( (opt("+") ~> """[1-9][01-9]*""".r) ^^ { new BigInteger(_) } ) def rawFloat : Parser[BigDecimal] = ( """[-+]?\d*\.\d+([eE][+-]?\d+)?""".r ^^ { new BigDecimal(_) } ) |

As you can see, Cornerstone has only 3 kinds of numbers: integers, floats, and rationals. Rationals are the default, with integers and floats being signaled by suffixes on the numbers (“Z”/”z” and “F”/”f”, respectively). I’m still trying to decide, but I may go with 5 numeric types at the end of the day: long integers (“z”), BigIntegers (“Z”), double-precision floats (“f”), BigDecimals (“F”), and arbitrary-precision rationals (un-suffixed).