标签: parser-combinators

Scala解析器组合器:使用packratparsers获取stackoverflow

由于这是我的第一篇文章,我想借此机会说:这是一个多么伟大的网站!

无论如何,对于这个问题:

我有点像Scala新手,我正在尝试用Scala中的解析器组合器解决数据提取和解析问题,我得到了java.lang.StackOverflowError异常.

我的真实世界的例子太大了,所以我没有重复使用来自另一个SO问题的代码同样的问题.虽然代码略有修改.我尝试使用PackratParsers解决问题,但没有成功.

import scala.util.parsing.combinator.syntactical.StandardTokenParsers
import scala.util.parsing.combinator.PackratParsers

object ArithmeticParser1 extends StandardTokenParsers with PackratParsers {
  lexical.delimiters ++= List("(", ")", "+", "-", "*", "/")

  lazy val reduceList: Int ~ List[String ~ Int] => Int = {
    case i ~ ps => (i /: ps)(reduce)
  }

  def reduce(x: Int, r: String ~ Int) = (r: @unchecked) match {
    case "+" ~ y => x + y
    case "-" ~ y => x - y
    case "*" ~ y => x …
Run Code Online (Sandbox Code Playgroud)

stack-overflow parsing scala text-parsing parser-combinators

2
推荐指数
1
解决办法
1035
查看次数

使用nom识别输入的浮点数

我正在尝试使用nom来解析基于文本的协议.此协议可以具有以下形式的浮点值:

[-]digit+[.digit+]
Run Code Online (Sandbox Code Playgroud)

其中的例子是:

  • -10.0
  • 10.0
  • 10

我构建的nom解析器是为了识别这个......不漂亮.它也不太明显.到目前为止我得到了什么:

named!(float_prs <&[u8], f64>,
       alt!(
           take_while!(nom::is_digit) => {|x| FromStr::from_str(std::str::from_utf8(x).unwrap()).unwrap()} |
           recognize!(chain!(
               take_while!(nom::is_digit) ~
                   tag!(".") ~
                   take_while!(nom::is_digit),
               || {})
           ) => {|x: &[u8]| FromStr::from_str(std::str::from_utf8(x).unwrap()).unwrap() }
       )
);
Run Code Online (Sandbox Code Playgroud)

第一个替代解析器识别digit+,第二个是尝试识别digit+.digit+但是

<nom macros>:5:38: 5:62 error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
<nom macros>:5 let index = ( $ i ) . offset ( i ) ; $ crate:: IResult:: Done (
Run Code Online (Sandbox Code Playgroud)

-digit …

parser-combinators rust

2
推荐指数
1
解决办法
1015
查看次数

避免在解析器库中的解析器中使用失败

据我所知,不建议使用失败,以后将删除它。

在以下Parsers/Trifecta示例中,应该正确使用什么而不是失败?

parserNaturalNoLeadZero :: Parser Integer
parserNaturalNoLeadZero = do
  digits <- some digit
  if length digits > 1 && head digits == '0'
    then fail "Leading Zeros"
    else return $ read digits
Run Code Online (Sandbox Code Playgroud)

parsing haskell parser-combinators

2
推荐指数
1
解决办法
81
查看次数

为什么我不能使用 case 类的构造函数作为函数在 map() 中使用

编译器不接受将元组直接传递给构造函数,如最小示例所示:

scala> case class A(a:Int, b:Int)
defined class A

scala> List((1, 2)).map(A)
<console>:14: error: type mismatch;
found   : A.type
required: ((Int, Int)) => ?
    List((1, 2)).map(A)
                        ^

scala> List((1, 2)).map(A _)
<console>:14: error: _ must follow method; cannot follow A.type
    List((1, 2)).map(A _)
                        ^
Run Code Online (Sandbox Code Playgroud)

Scala 解析器组合器具有^^用于此的运算符。fastparse 库中有类似的东西吗?

lambda scala parser-combinators case-class fastparse

2
推荐指数
1
解决办法
78
查看次数

Scala解析器组合器:如何解析"if(x)",如果x可以包含")"

我试图让这个工作:

def emptyCond: Parser[Cond] = ("if" ~ "(") ~> regularStr <~ ")" ^^ { case s => Cond("",Nil,Nil) }
Run Code Online (Sandbox Code Playgroud)

其中regularStr被定义为接受许多东西,包括")".当然,我希望这是一个可接受的输入:if(foo()).但对于任何if(x),它将")"作为regularStr的一部分,因此这个解析器永远不会成功.

我错过了什么?

编辑:

regularStr不是正则表达式.它定义如下:

  def regularStr = rep(ident | numericLit | decimalLit | stringLit | stmtSymbol) ^^ { case s => s.mkString(" ") }
Run Code Online (Sandbox Code Playgroud)

符号是:

  val stmtSymbol = "*" | "&" | "." | "::" | "(" | ")" | "*" | ">=" | "<=" | "=" | 
               "<" | ">" | …
Run Code Online (Sandbox Code Playgroud)

scala parser-combinators

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

强制正则表达式匹配可选组

我想在文本中搜索字符串"W foo X bar Y baz Z".W,X,Y,Z是不重要的分隔符,我不能搜索它们.foo,bar和baz是我感兴趣的词.订单并不重要.我想知道文本中出现的所需词语"好".

我正在尝试以下方面

(?:\Qfoo\E)?.{0,3}(?:\Qbar\E)?.{0,3}(?:\Qbaz\E)?
Run Code Online (Sandbox Code Playgroud)

我的理由是:

  • 将每个单词打包在一个可选组中,因此不需要发生[(?:是非捕获组,\ Q ...\E只是转义]
  • 用.{0,3}分隔每个单词(任何字符,出现0-3次)

此正则表达式始终匹配,因为它只包含可选组,但结果匹配始终为空,即使它可以完全匹配所有可选组.但是,我想对结果匹配进行后期处理,因此我需要尽可能多地捕获它.

我可以强制正则表达式尝试尽可能匹配所有组吗?

或者您是否知道如何搜索多个单词,由某些单词分隔,然后检查哪些单词出现以计算某些相似性?

非常感谢你

java regex scala parser-combinators

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

我不明白如何使用lexeme函数

来自Text.Parsec.Token:

lexeme p = do { x <- p; whiteSpace; return x }
Run Code Online (Sandbox Code Playgroud)

看来,语义需要一个解析器P和提供具有相同行为为p,但它也跳过所有尾随空格的分析器.正确?

那怎么来以下不起作用:

constant :: Parser Int
constant = do
    digits <- many1 digit
    return (read digits)

lexConst :: Parser Int
lexConst = lexeme constant
Run Code Online (Sandbox Code Playgroud)

最后一行导致以下错误消息:

Couldn't match expected type `ParsecT
                                String () Data.Functor.Identity.Identity Int'
            with actual type `ParsecT s0 u0 m0 a0 -> ParsecT s0 u0 m0 a0'
Expected type: Parser Int
  Actual type: ParsecT s0 u0 m0 a0 -> ParsecT s0 u0 m0 a0 …
Run Code Online (Sandbox Code Playgroud)

whitespace haskell parsec lexer parser-combinators

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

如何将此解析器转换为应用程序的多变量解析器?

我正在尝试解析日期,例如09/10/2015 17:20:52:

{-# LANGUAGE FlexibleContexts #-}

import Text.Parsec
import Text.Parsec.String
import Text.Read
import Control.Applicative hiding (many, (<|>))

data Day = Day
  { mo  :: Int
  , dy  :: Int
  , yr  :: Int
  } deriving (Show)

data Time = Time
  { hr  :: Int
  , min :: Int
  , sec :: Int
  } deriving (Show)

day  = listUncurry Day  <$> (sepCount 3 (char '/') $ read <$> many digit)
time = listUncurry Time <$> (sepCount 3 (char ':') …
Run Code Online (Sandbox Code Playgroud)

haskell parsec parser-combinators applicative polyvariadic

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

如果抛出异常,如何使解析器优雅地失败?

这是我尝试为 Int s 编写一个小解析器:

import scala.util.parsing.combinator.RegexParsers

object PositiveIntParser extends RegexParsers {

  private def positiveInt: Parser[Int] = """0*[1-9]\d*""".r ^^ { _.toInt }

  def apply(input: String): Option[Int] = parseAll(positiveInt, input) match {
    case Success(result, _) => Some(result)
    case _ => None
  }

}
Run Code Online (Sandbox Code Playgroud)

问题是,如果输入字符串太长,则toInt抛出一个NumberFormatException,这会使我的解析器爆炸:

scala> :load PositiveIntParser.scala
Loading PositiveIntParser.scala...
import scala.util.parsing.combinator.RegexParsers
defined object PositiveIntParser

scala> PositiveIntParser("12")
res0: Option[Int] = Some(12)

scala> PositiveIntParser("-12")
res1: Option[Int] = None

scala> PositiveIntParser("123123123123123123")
java.lang.NumberFormatException: For input string: "123123123123123123"
  at ...
Run Code Online (Sandbox Code Playgroud)

相反,我希望我的positiveInt …

parsing scala exception-handling parser-combinators

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

SCALA:如何将Parser Combinator结果转换为Scala List [String]?

我正在尝试为与Milner的CCS非常相似的语言编写解析器.基本上我到目前为止解析的是以下类型的表达式:

  • aba1
  • A.0

表达式必须以字母开头(不包括t),并且可以在第一个字母后面加上任意数量的字母(以"."分隔).Expression必须以数字结尾(为简单起见,我现在选择0到2之间的数字).我想为Scala使用Parser Combinators,但这是我第一次使用它们.这是我到目前为止:

import scala.util.parsing.combinator._

class SimpleParser extends RegexParsers {
  def alpha: Parser[String] = """[^t]{1}""".r ^^ { _.toString }
  def digit: Parser[Int] = """[0-2]{1}""".r ^^ { _.toInt }

  def expr: Parser[Any] = alpha ~ "." ~ digit ^^ {
    case al ~ "." ~ di => List(al, di)
  }

  def simpleExpression: Parser[Any] = alpha ~ "." ~ rep(alpha ~ ".") ~ digit //^^ {  }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,def expr :Parser[Any]我试图将结果作为列表返回,因为Scala中的列表非常容易使用(在我看来).这是如何将Parser [Any]结果转换为List的正确方法吗?任何人都可以给我任何关于如何做到这一点的提示def simpleExpression:Parser[Any].

我想使用Lists的主要原因是因为在解析和Expression之后我希望能够使用它.例如,给定表达式ab1,如果给出 …

parsing scala parser-combinators

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

规范 5:多次使用另一个解析器创建组合器

假设我想创建一个多次使用另一个解析器的组合器,例如,解析由两种引号分隔的字符串:

fn quoted<'a, F: 'a, O, E: ParseError<&'a str>>(f: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where
    F: Fn(&'a str) -> IResult<&'a str, O, E>,
{
    map(
        alt((
            tuple((tag("'"), f, tag("'"))),
            tuple((tag("\""), f, tag("\"")))
        )),
        |(_, res, _)| res,
    )
}
Run Code Online (Sandbox Code Playgroud)

正如预期的那样,该解析器无法编译并出现“使用移动值”错误:

fn quoted<'a, F: 'a, O, E: ParseError<&'a str>>(f: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where
    F: Fn(&'a str) -> IResult<&'a str, O, E>,
{
    map(
        alt((
            tuple((tag("'"), f, tag("'"))),
            tuple((tag("\""), f, …
Run Code Online (Sandbox Code Playgroud)

parsing parser-combinators rust nom

0
推荐指数
1
解决办法
1116
查看次数