Единственная проблема с кодом - использование символов вместо строк.Ниже я удалил лишний ^^ { case s => s }
и заменил все символы на строки.Я буду дополнительно обсуждать эту проблему ниже.
class SchemeParsers extends RegexParsers {
// Scheme boolean #t and #f translate to Scala's true and false
def bool : Parser[Boolean] =
("#t" | "#f") ^^ {case "#t" => true; case "#f" => false}
// A Scheme identifier allows alphanumeric chars, some symbols, and
// can't start with a digit
def id : Parser[String] =
"""[a-zA-Z=*+/<>!\?][a-zA-Z0-9=*+/<>!\?]*""".r ^^ {case s => s}
// This interpreter only accepts numbers as integers
def num : Parser[Int] = """-?\d+""".r ^^ {case s => s toInt}
// A string can have any character except ", and is wrapped in "
def str : Parser[String] = "\"" ~> """[^""]*""".r <~ "\""
// A Scheme list is a series of expressions wrapped in ()
def list : Parser[List[Any]] =
"(" ~> rep(expr) <~ ")" ^^ {s: List[Any] => s}
// A Scheme expression contains any of the other constructions
def expr : Parser[Any] = id | str | num | bool | list
}
Все Parsers
имеют неявное accept
для их Elem
типов.Итак, если базовый элемент - это Char
, например, в RegexParsers
, то для них существует неявное действие принятия, которое происходит здесь для символов (
, )
и "
, которыесимволов в вашем коде.
Что автоматически делает RegexParsers
, так это автоматически пропускает пробелы (определенные как protected val whiteSpace = """\s+""".r
, так что вы можете переопределить это) автоматически в начале любого String
или Regex
.Он также заботится о перемещении позиционирующего курсора за пробелом в случае сообщений об ошибках.
Одним из следствий этого, которое, как вы, похоже, не поняли, является то, что у префикса префикса " a string beginning with a space"
будет удалено из проанализированноговывод, который вряд ли будет чем-то, что вы хотите.: -)
Кроме того, поскольку \s
включает новые строки, новая строка будет приемлемой перед любым идентификатором, который может быть или не быть тем, что вы хотите.
Вы можете отключить пропуск пробеловв вашем регулярном выражении в целом, переопределив skipWhiteSpace
.С другой стороны, по умолчанию skipWhiteSpace
проверяет длину whiteSpace
, поэтому вы можете потенциально включать и выключать ее, просто манипулируя значением whiteSpace
в течение всего процесса синтаксического анализа.