我有一个使用Scala的编写的解析器RegexParsers- 链接
在解析具有深层嵌套表达式的语法时,它有一些严重的性能问题.因此我创建了一个版本,我将其混合在Scala的PackratParsers- 链接中
Packrat版本没有出现相同的性能问题并正确解析语法.但是,当我提供无效的语法进行测试时,例如这个
用于通过此处的失败解析器组合器正确报告"无效规则"失败的旧(非包装)解析器| failure("Invalid rule")- 链接
当使用packrat-parser版本时,如果我启用跟踪,我可以从跟踪中看到故障是在非packrat版本中创建的,但PackratParser似乎忽略了这一点并且总是返回failure: Base Failure.
在使用我需要理解的PackratParsers时,是否存在与故障处理有所不同的内容?
我正在尝试使用Scala解析器组合器编写CSV解析器.语法基于RFC4180.我想出了以下代码.它几乎可以工作,但我不能让它正确地分隔不同的记录.我错过了什么?
object CSV extends RegexParsers {
def COMMA = ","
def DQUOTE = "\""
def DQUOTE2 = "\"\"" ^^ { case _ => "\"" }
def CR = "\r"
def LF = "\n"
def CRLF = "\r\n"
def TXT = "[^\",\r\n]".r
def file: Parser[List[List[String]]] = ((record~((CRLF~>record)*))<~(CRLF?)) ^^ {
case r~rs => r::rs
}
def record: Parser[List[String]] = (field~((COMMA~>field)*)) ^^ {
case f~fs => f::fs
}
def field: Parser[String] = escaped|nonescaped
def escaped: Parser[String] = (DQUOTE~>((TXT|COMMA|CR|LF|DQUOTE2)*)<~DQUOTE) ^^ { case …Run Code Online (Sandbox Code Playgroud) 大约6年前,我在OCaml中对自己的解析器组合器进行了基准测试,结果发现它们比当时提供的解析器生成器慢〜5倍.我最近重新审视了这个主题,并对Haskell的Parsec和一个用F#编写的简单的手动优先攀爬解析器进行了基准测试,并惊讶地发现F#比Haskell快25倍.
这是我用来从文件中读取大型数学表达式的Haskell代码,解析并评估它:
import Control.Applicative
import Text.Parsec hiding ((<|>))
expr = chainl1 term ((+) <$ char '+' <|> (-) <$ char '-')
term = chainl1 fact ((*) <$ char '*' <|> div <$ char '/')
fact = read <$> many1 digit <|> char '(' *> expr <* char ')'
eval :: String -> Int
eval = either (error . show) id . parse expr "" . filter (/= ' ')
main :: IO ()
main = do
file <- …Run Code Online (Sandbox Code Playgroud) 我的问题是关于Scala解析器:
我发现至少这些:
我正在为一个主要用Scala编写的应用程序编写表达式解析器.我在Scala中构建了AST对象,现在需要编写解析器.我听说过Scala的内置解析器组合器,以及ANTLR3,我想知道:哪个可以提供更好的性能和编写代码的简易性?至今:
ANTLR专业人士
ANTLR缺点
Parser combinator专业人士
解析器组合器缺点
有什么想法吗?
编辑:此表达式解析器解析代数/微积分表达式.它将在最终确定的Android应用程序Magnificalc中使用.
我已经读过Haskell解析器组合器(在Parsec中)可以解析上下文敏感语法.Scala解析器组合器也是如此吗?如果是这样,这就是"进入"(又名">>")功能的用途吗?
与Haskell相比,Scala实现解析器组合器有哪些优点/缺点?他们接受同一类语法吗?是否更容易生成错误消息或使用其中一个进行其他各种有用的事情?
packrat解析(在Scala 2.8中引入)如何适应这张图片?
是否有网页或其他资源显示一种语言的实现中不同的运算符/函数/ DSL-sugar如何映射到另一种语言?
我正在使用解析器 - 组合器库在Scala中编写一个简单的函数式编程语言.
语法在此处指定:https://github.com/hejfelix/Frase/blob/master/src/main/scala/it/vigtig/lambda/ParserLike.scala
有一件事我无法通过实现来解决:如何将语法定义与转换为AST节点分开?
直接在解析器源中使用接近人类可读的语法真的很酷,特别是考虑到我是项目ATM上唯一的程序员,它可以作为文档.
如何分离语法和AST特定代码?
我是相当新的Scala和一边念叨解析器组合(魔术解析器组合的背后,在斯卡拉领域特定语言),我遇到的方法定义来是这样的:
def classPrefix = "class" ~ ID ~ "(" ~ formals ~ ")"
Run Code Online (Sandbox Code Playgroud)
我一直在阅读scala.util.parsing.Parsers的API文档,它定义了一个名为(代字号)的方法,但我仍然不能理解它在上面例子中的用法.在该示例中(代字号)是在java.lang.String上调用的方法,该方法没有该方法并导致编译器失败.我知道(代字号)被定义为
case class ~ [+a, +b] (_1: a, _2: b)
Run Code Online (Sandbox Code Playgroud)
但是这对上面的例子有什么帮助呢?
如果有人能给我一些提示来了解这里发生了什么,我会很高兴.非常感谢你提前!
一月
我正在创建一个DSL,并使用Scala的解析器组合库来解析DSL.DSL遵循简单的类似Ruby的语法.源文件可以包含一系列看起来像这样的块:
create_model do
at 0,0,0
end
Run Code Online (Sandbox Code Playgroud)
线路结尾在DSL中很重要,因为它们被有效地用作语句终止符.
我写了一个Scala解析器,看起来像这样:
class ML3D extends JavaTokenParsers {
override val whiteSpace = """[ \t]+""".r
def model: Parser[Any] = commandList
def commandList: Parser[Any] = rep(commandBlock)
def commandBlock: Parser[Any] = command~"do"~eol~statementList~"end"
def eol: Parser[Any] = """(\r?\n)+""".r
def command: Parser[Any] = commandName~opt(commandLabel)
def commandName: Parser[Any] = ident
def commandLabel: Parser[Any] = stringLiteral
def statementList: Parser[Any] = rep(statement)
def statement: Parser[Any] = functionName~argumentList~eol
def functionName: Parser[Any] = ident
def argumentList: Parser[Any] = repsep(argument, ",")
def argument: Parser[Any] = stringLiteral …Run Code Online (Sandbox Code Playgroud) 给定一系列实现解析器组合器的对象,如何组合解析器?由于Parsers.Parser是一个内部类,并且在Scala 内部类中绑定到外部对象,故事变得有点复杂.
这是一个尝试组合来自不同对象的两个解析器的示例.
import scala.util.parsing.combinator._
class BinaryParser extends JavaTokenParsers {
def anyrep: Parser[Any] = rep(any)
def any: Parser[Any] = zero | one
def zero: Parser[Any] = "0"
def one: Parser[Any] = "1"
}
object LongChainParser extends BinaryParser {
def parser1: Parser[Any] = zero~zero~one~one
}
object ShortChainParser extends BinaryParser {
def parser2: Parser[Any] = zero~zero
}
object ExampleParser extends BinaryParser {
def parser: Parser[Any] = (LongChainParser.parser1
||| ShortChainParser.parser2) ~ anyrep
def main(args: Array[String]) {
println(parseAll(parser, args(0) )) …Run Code Online (Sandbox Code Playgroud)