Parsing 使用Scala解析器组合器的解析方案

Parsing 使用Scala解析器组合器的解析方案,parsing,scala,Parsing,Scala,我正在用Scala编写一个小型的scheme解释器,在分析scheme中的列表时遇到了问题。我的代码解析包含多个数字、标识符和布尔值的列表,但如果我试图解析包含多个字符串或列表的列表,它就会阻塞。我错过了什么 这是我的解析器: class SchemeParsers extends RegexParsers { // Scheme boolean #t and #f translate to Scala's true and false def bool : Parser[Boolean] =

我正在用Scala编写一个小型的scheme解释器,在分析scheme中的列表时遇到了问题。我的代码解析包含多个数字、标识符和布尔值的列表,但如果我试图解析包含多个字符串或列表的列表,它就会阻塞。我错过了什么

这是我的解析器:

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 <~ '"' ^^ {case s => s}

// 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 ^^ {case s => s}
} 
类SchemeParsers扩展RegexParsers{
//方案布尔值#t和#f转换为Scala的true和false
def bool:分析器[布尔]=
(“#t”|“#f”)^{case“#t”=>真;case“#f”=>假}
//方案标识符允许字母数字字符、一些符号和
//不能以数字开头
def id:分析器[字符串]=
“[a-zA-Z=*+/!\?][a-zA-Z0-9=*+/!\?]*”.r^^{案例s=>s}”
//此解释器只接受数字作为整数
def num:Parser[Int]=“”“-?\d+“”.r^^{case s=>s toInt}
//字符串可以有除“.”之外的任何字符,并用“.”包装
def str:Parser[String]=''“~>”“[^”“]*”“”.rs}
//方案列表是用()包装的一系列表达式
定义列表:解析器[列表[任何]]=
“('~>rep(expr)s}
//方案表达式包含任何其他构造
def expr:Parser[Any]=id | str | num | bool | list^^{case s=>s}
} 

正如@Gabe正确指出的,您留下了一些空白未处理:

scala> object SchemeParsers extends RegexParsers {
     |
     | private def space  = regex("[ \\n]*".r)
     |
     | // Scheme boolean #t and #f translate to Scala's true and false
     | private 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
     | private def id : Parser[String] =
     |     """[a-zA-Z=*+/<>!\?][a-zA-Z0-9=*+/<>!\?]*""".r
     |
     | // This interpreter only accepts numbers as integers
     | private def num : Parser[Int] = """-?\d+""".r ^^ {case s => s toInt}
     |
     | // A string can have any character except ", and is wrapped in "
     | private def str : Parser[String] = '"' ~> """[^""]*""".r <~ '"' <~ space ^^ {case s => s}
     |
     | // A Scheme list is a series of expressions wrapped in ()
     | private def list : Parser[List[Any]] =
     |     '(' ~> space  ~> rep(expr) <~ ')' <~ space ^^ {s: List[Any] => s}
     |
     | // A Scheme expression contains any of the other constructions
     | private def expr : Parser[Any] = id | str | num | bool | list ^^ {case s => s}
     |
     | def parseExpr(str: String) = parse(expr, str)
     | }
defined module SchemeParsers   

scala> SchemeParsers.parseExpr("""(("a" "b") ("a" "b"))""")
res12: SchemeParsers.ParseResult[Any] = [1.22] parsed: List(List(a, b), List(a, b))

scala> SchemeParsers.parseExpr("""("a" "b" "c")""")
res13: SchemeParsers.ParseResult[Any] = [1.14] parsed: List(a, b, c)

scala> SchemeParsers.parseExpr("""((1) (1 2) (1 2 3))""")
res14: SchemeParsers.ParseResult[Any] = [1.20] parsed: List(List(1), List(1, 2), List(1, 2, 3))
scala>objectschemeparsers扩展RegexParsers{
|
|private def space=regex(“[\\n]*”.r)
|
|//Scheme boolean#t和#f转换为Scala的true和false
|私有def bool:解析器[布尔]=
|(“#t”|“#f”)^{case“#t”=>真;case“#f”=>假}
|
|//方案标识符允许字母数字字符、某些符号和
|//不能以数字开头
|私有定义id:解析器[字符串]=
|“[a-zA-Z=*+/!\?][a-zA-Z0-9=*+/!\?]*”。r
|
|//此解释器只接受数字作为整数
|private def num:Parser[Int]=“”“-?\d+“”.r^^{case s=>s toInt}
|
|//字符串可以有除“.”以外的任何字符,并用“.”包装
|private def str:Parser[String]=''“~>”“[^”“]*”“”.r space~>rep(expr)s}
|
|def parsexpr(str:String)=parse(expr,str)
| }
已定义模块SchemeParsers
scala>SchemeParsers.parseExpr(“”(“”(“”“a”b)(“a”b”)“”)
res12:SchemeParsers.ParseResult[Any]=[1.22]已解析:列表(列表(a,b),列表(a,b))
scala>SchemeParsers.parseExpr(“”(“a”“b”“c”)“”)
res13:SchemeParsers.ParseResult[Any]=[1.14]已解析:列表(a、b、c)
scala>SchemeParsers.parseExpr(“”(1)(12)(13))“”)
res14:SchemeParsers.ParseResult[Any]=[1.20]已解析:列表(列表(1),列表(1,2),列表(1,2,3))

代码的唯一问题是使用字符而不是字符串。下面,我删除了冗余的
^^{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
}
类SchemeParsers扩展RegexParsers{
//方案布尔值#t和#f转换为Scala的true和false
def bool:分析器[布尔]=
(“#t”|“#f”)^{case“#t”=>真;case“#f”=>假}
//方案标识符允许字母数字字符、一些符号和
//不能以数字开头
def id:分析器[字符串]=
“[a-zA-Z=*+/!\?][a-zA-Z0-9=*+/!\?]*”.r^^{案例s=>s}”
//此解释器只接受数字作为整数
def num:Parser[Int]=“”“-?\d+“”.r^^{case s=>s toInt}
//字符串可以有除“.”之外的任何字符,并用“.”包装

def str:Parser[String]=“\”“~>”“[^”“]*”.r如何处理空白?为什么需要
^{case s=>s}
?@MJP+1,
^{case s=>s}
可以是removed@Gabe有人会假定,
RegexParsers
默认的空格处理是有效的。失败的测试用例会很有用。太好了!谢谢!我以为Regex解析器为我处理了空格,但我发现我错了。
RegexParsers
在任何文本字符串或字符串的开头自动跳过空格正则表达式。我想知道问题是否与正在使用的
Char
有关…@stomcavage
RegexParsers
为您处理空间,而不是
Char