标签: parser-combinators

在scala中对递归解析器的高级控制

val uninterestingthings = ".".r
val parser = "(?ui)(regexvalue)".r | (uninterestingthings~>parser)
Run Code Online (Sandbox Code Playgroud)

这个递归解析器将尝试解析"(?ui)(regexvalue)".r直到输入结束.scala是一种在"不感兴趣"消耗某些定义数量的字符时禁止解析的方法吗?

UPD:我有一个糟糕的解决方案:

object NonRecursiveParser extends RegexParsers with PackratParsers{
  var max = -1
  val maxInput2Consume = 25
  def uninteresting:Regex ={
    if(max<maxInput2Consume){
    max+=1
    ("."+"{0,"+max.toString+"}").r
    }else{
      throw new Exception("I am tired")
    }
  }
  lazy val value = "itt".r
  def parser:Parser[Any] = (uninteresting~>value)|parser
  def parseQuery(input:String) = {
      try{
      parse(parser, input)
      }catch{
          case e:Exception => 
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

缺点:
- 并非所有成员都是懒惰的,所以PackratParser会有一些时间惩罚
- 在每个"无趣的"方法调用上构建正则表达式- 时间惩罚
- 使用异常来控制程序 - 代码风格和时间惩罚

parsing scala parser-combinators

5
推荐指数
1
解决办法
523
查看次数

如何从文本中解析占位符而不丢弃你的剑,这样你就可以用灯罩击退掠夺者

我需要用文本解析占位符abc $$FOO$$ cba.我和Scala的解析器组合器一起攻击了一些东西,但我对解决方案并不满意.

特别是,我在正则表达式中使用零宽度匹配器(?=(\$\$|\z))来停止解析文本并开始解析占位符.这听起来非常接近于scala邮件列表中讨论过的那些恶作剧,并且被多彩地解散了(这激发了这个问题的标题.)

所以,挑战:修复我的解析器没有这个黑客的工作.我希望看到从问题到解决方案的明确进展,因此我可以替换我的随机组装组合器的策略,直到测试通过.

import scala.util.parsing.combinator.RegexParsers

object PlaceholderParser extends RegexParsers {
  sealed abstract class Element
  case class Text(text: String) extends Element
  case class Placeholder(key: String) extends Element

  override def skipWhitespace = false

  def parseElements(text: String): List[Element] = parseAll(elements, text) match {
    case Success(es, _) => es
    case NoSuccess(msg, _) => error("Could not parse: [%s]. Error: %s".format(text, msg))
  }

  def parseElementsOpt(text: String): ParseResult[List[Element]] = parseAll(elements, text)

  lazy val elements: Parser[List[Element]] = rep(element)
  lazy val …
Run Code Online (Sandbox Code Playgroud)

parsing scala parser-combinators

5
推荐指数
1
解决办法
497
查看次数

如何使用scala.util.parsing.ast.Binders?

我目前正在Scala中实现一个小编译器,当我在进行上下文分析的组件时,我发现了Binders包中的特征scala.util.parsing.ast(我正在使用Scala 2.9 RC),它是Documented以在解析时启用名称绑定.这听起来很有趣,我一直在谷歌搜索,但我仍然不知道如何使用它.虽然我当然能够让我的抽象语法脱离,但Binders我不知道如何从那里开始.网上有什么用法的例子吗?

compiler-construction binding functional-programming scala parser-combinators

5
推荐指数
1
解决办法
243
查看次数

解析器组合器:repsep是否允许反向跟踪?

考虑这样的解析器示例:

object TestParser extends RegexParsers {
    override protected val whiteSpace = """[ \t]*""".r  

    def eol = """(\r?\n)+""".r
    def item = "[a-zA-Z][a-zA-Z0-9-]*".r
    def list = "items:" ~> rep1sep(item,",") 
    def constraints = "exclude:" ~> item

    def itemsDefinition = (rep1sep(list, eol) ~ repsep(constraints,eol))
}
Run Code Online (Sandbox Code Playgroud)

如果我尝试解析此输入(没有两行包含排除工作正常):

items: item1, item2, item3, item3, item4
items: item2, item3, item3, item5, item4    
items: item4, item5, item6, item10      
items: item1, item2, item3
exclude: item1
exclude: item2
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

[5.5] failure: `items:' expected but `e' found

       exclude: item1

       ^
Run Code Online (Sandbox Code Playgroud)

问题很明显这一行:

def …
Run Code Online (Sandbox Code Playgroud)

scala parser-combinators

5
推荐指数
1
解决办法
1224
查看次数

Scala解析器组合器:如何反转匹配?

是否可以使用Scala解析器组合器反转匹配?我试图将行与以一组关键字开头的解析器匹配.我可以用一个恼人的零宽度负先行的正则表达式(例如,做到这一点"(?!h1|h2).*"),但我宁愿用Scala的解析器做到这一点.我能想出的最好的是:

def keyword = "h1." | "h2."
def alwaysfails = "(?=a)b".r
def linenotstartingwithkeyword = keyword ~! alwaysfails | ".*".r
Run Code Online (Sandbox Code Playgroud)

这个想法在这里我用〜!禁止回溯到所有匹配的正则表达式,然后用正则表达式继续"(?= A)B" .R匹配什么.(顺便说一下,有一个预定义的解析器,总是失败?)这样,如果一个关键字被发现,但如果关键字不匹配将匹配行不会匹配.

我想知道是否有更好的方法来做到这一点.在那儿?

scala parser-combinators

5
推荐指数
1
解决办法
1250
查看次数

无法计算解析器的最小长度 - 在Haskell中使用uu-parsinglib

让我们看看代码片段:

pSegmentBegin p i   = pIndentExact i *> ((:) <$> p i <*> ((pEOL *> pSegment p i) <|> pure []))
Run Code Online (Sandbox Code Playgroud)

如果我在我的解析器中将此代码更改为:

pSegmentBegin p i   = do
    pIndentExact i
    ((:) <$> p i <*> ((pEOL *> pSegment p i) <|> pure []))
Run Code Online (Sandbox Code Playgroud)

我有一个错误:

canot compute minmal length of a parser due to occurrence of a moadic bind, use addLength to override
Run Code Online (Sandbox Code Playgroud)

我认为上面的解析器应该以相同的方式运行.为什么会出现此错误?

编辑

上面的例子很简单(为了简化问题),如下所述,这里没有必要使用do notation,但我希望它使用的实际情况如下:

pSegmentBegin p i   = do
    j <- pIndentAtLast i
    (:) <$> p j <*> ((pEOL …
Run Code Online (Sandbox Code Playgroud)

parsing haskell parsec parser-combinators uu-parsinglib

5
推荐指数
2
解决办法
344
查看次数

如何忽略解析器组合器中的单行注释

我有一个工作的解析器,但我刚刚意识到我不满足于评论.在我解析的DSL中,注释以;字符开头.如果;遇到a,则忽略该行的其余部分(但不是全部,除非第一个字符是;).

我正在扩展RegexParsers我的解析器并忽略空格(默认方式),所以我无论如何都会丢失新的行字符.我不希望修改我必须满足注释可能性的每个解析器,因为语句可以跨越多行(因此每个语句的每个部分可能以注释结束).是否有任何干净的方法来实现这一目标?

scala parser-combinators

5
推荐指数
1
解决办法
1845
查看次数

通过函数应用程序解析器组合器发出信号失败

我需要对解析器匹配进行比标准符号允许的更复杂的语法检查,并且我目前正在函数应用程序中执行它^^.示例简化方案是检查重复的关键字:

def keywords: Parser[List[String]] = "[" ~ repsep(keyword, ",") ~ "]" ^^ {
  case _ ~ ks ~ _ =>
    ks.groupBy(x => x).filter(_._2.length > 1).keys.toList match {
      case Nil => ks
      case x => throw new DuplicateKeywordsException(x)
    }
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为在我的解析器中会抛出异常,但我希望将失败捕获为ParseResult.Failure捕获它发生的位置的输入.我无法弄清楚如何从一个^^块内发出信号或使用其他一些构造来达到同样的目的.

scala parser-combinators

5
推荐指数
1
解决办法
70
查看次数

快速解析允许转义字符的字符串?

我正在尝试解析一个可以包含转义字符的字符串,这是一个例子:

import qualified Data.Text as T

exampleParser :: Parser T.Text
exampleParser = T.pack <$> many (char '\\' *> escaped <|> anyChar)
  where escaped = satisfy (\c -> c `elem` ['\\', '"', '[', ']'])
Run Code Online (Sandbox Code Playgroud)

上面的解析器创建一个String然后将其打包Text.是否有任何方法使用attoparsec提供的高效字符串处理函数解析带有类似上述转义的字符串?像string,scan,runScanner,takeWhile,...

解析类似的东西"one \"two\" \[three\]"会产生one "two" [three].

更新:

感谢@epsilonhalbe,我能够提出一个完美满足我需求的通用解决方案; 注意,以下功能不查找匹配转义字符像[..],"..",(..),等; 而且,如果它找到一个无效的转义字符,则将其视为\文字字符.

takeEscapedWhile :: (Char -> Bool) -> (Char -> Bool) -> Parser …
Run Code Online (Sandbox Code Playgroud)

parsing haskell parser-combinators attoparsec

5
推荐指数
1
解决办法
433
查看次数

FParsec:回溯`sepBy`

考虑以下玩具语法和解析器:

(* in EBNF:
  ap = "a", { "ba" }
  bp = ap, "bc"
*)
let ap = sepBy1 (pstring "a") (pstring "b")
let bp = ap .>> (pstring "bc")
let test = run bp "abababc"
Run Code Online (Sandbox Code Playgroud)

我得到以下输出:

Error in Ln: 1 Col: 7
abababc
      ^
Expecting: 'a'
Run Code Online (Sandbox Code Playgroud)

清楚地sepBy1看到最后一个b并期望它导致另一个a,当它找不到时失败.是否有一个变sepBy1体会回溯b并使这个解析成功?我不应该使用它吗?

f# parser-combinators fparsec

5
推荐指数
1
解决办法
212
查看次数