編集:解決済み、以下の「FIX」を参照
数値の複雑さに応じて浮動小数点数または整数を解析するようにスカラ パーサー コンビネーターをセットアップしようとしています。これが私が現在持っているものです:
import scala.util.parsing.combinator.JavaTokenParsers
trait NumberLiteral
case class IntegerLiteral(i:Int) extends NumberLiteral
case class FloatLiteral(f:Float) extends NumberLiteral
class Parser extends JavaTokenParsers {
def integer:Parser[IntegerLiteral] = wholeNumber ^^ {i => new IntegerLiteral(i.toInt)}
def float:Parser[FloatLiteral] = floatingPointNumber ^^ {f => new FloatLiteral(f.toFloat)}
//FIX: def float:Parser[FloatLiteral] = """[+-]?[0-9]*((\.[0-9]+([eE][+-]?[0-9]+)?[fF]?)|([fF])|([eE][+-]?[0-9]+))\b""".r ^^ {f => new FloatLiteral(f.toFloat)}
def number:Parser[NumberLiteral] = integer | float;
//FIX: def number:Parser[NumberLiteral] = float | integer;
}
整数パーサーと浮動小数点パーサーの両方をテストするように scalatest をセットアップしましたが、どちらも機能します。私のテストクラスは次のようになります。
import org.scalatest._
class ParserSpec extends FlatSpec with Matchers {
val parser = new Parser()
"Parser" should "parse IntegerLiteral" in {
parser.parseAll(parser.integer, "0").get should equal (new IntegerLiteral(0))
parser.parseAll(parser.integer, "4").get should equal (new IntegerLiteral(4))
parser.parseAll(parser.integer, "4448338").get should equal (new IntegerLiteral(4448338))
parser.parseAll(parser.integer, "-33").get should equal (new IntegerLiteral(-33))
parser.parseAll(parser.integer, "-10101010").get should equal (new IntegerLiteral(-10101010))
parser.parseAll(parser.integer, "004").get should equal (new IntegerLiteral(4))
}
it should "parse FloatLiteral" in {
parser.parseAll(parser.float, "1.0").get should equal (new FloatLiteral(1.0f))
parser.parseAll(parser.float, "0").get should equal (new FloatLiteral(0))
parser.parseAll(parser.float, "32.3").get should equal (new FloatLiteral(32.3f))
parser.parseAll(parser.float, "3.4e3").get should equal (new FloatLiteral(3400))
parser.parseAll(parser.float, "-10").get should equal (new FloatLiteral(-10))
parser.parseAll(parser.float, "-4e-4").get should equal (new FloatLiteral(-0.0004f))
parser.parseAll(parser.float, "003.4").get should equal (new FloatLiteral(3.4f))
parser.parseAll(parser.float, "4f").get should equal (new FloatLiteral(4))
}
it should "parse NumberLiteral" in {
parser.parseAll(parser.number, "32").get should equal (new IntegerLiteral(32))
parser.parseAll(parser.number, "32.3").get should equal (new FloatLiteral(32.3f))
parser.parseAll(parser.number, "32f").get should equal (new FloatLiteral(32))
parser.parseAll(parser.number, "0.33").get should equal (new FloatLiteral(0.33f))
parser.parseAll(parser.number, "32e2").get should equal (new IntegerLiteral(3200))
parser.parseAll(parser.number, "0").get should equal (new IntegerLiteral(32))
parser.parseAll(parser.number, "32.3e1").get should equal (new IntegerLiteral(323))
}
}
IntegerLiteralとFloatLiteralテストの両方が完全に機能します。IntegerLiteralご覧のとおり、数値をint または float として解析できるかどうかに応じて、数値を an または FloatLiteral として解析したいと考えています。テストの最初の行はNumberLiteral機能しますが、2 行目に次のエラーが表示されますjava.lang.RuntimeException: no result when parsing failed。float パーサーは parse できるため、パーサーがこのエラーをスローする理由がわかりません32.3。を使用して数値パーサーで何か間違ったことをしていinteger | floatますか?