简体   繁体   English

Scala组合器解析器到地图问题

[英]Scala Combinator Parser to Map problem

I have been beating my head against a wall, trying to figure out how to get this to work. 我一直在撞墙,试图弄清楚如何使其工作。 The initial parser worked great, but when I try to get a Map out of it, it is only giving the initial number value, but not he value blocks. 初始解析器工作得很好,但是当我尝试从中获取Map时,它只是给出初始数字值,而不是他对值块的赋值。

The format is "float: [label float: [optinallabel float:] ...]" like: 格式为“ float:[float标签:[optinallabel float:] ...]”,例如:

     412285.556: [Label 0.0:[Label1 1.0:][Label2 2.0:]

The parser to list is: 列出的解析器是:

object ParseList extends JavaTokenParsers {
    def sep : Parser[String] = ":"
    def string : Parser[Any] = """[\.a-zA-Z0-9]+""".r
    def num: Parser[Any] =  floatingPointNumber <~ sep
    def valueBlock: Parser[Any] =  "["~>rep(valueBlock)<~"]" | string ~ floatingPointNumber <~ sep
    def expr: Parser[Any] = num ~ rep(valueBlock )
    def apply(in: String) = parseAll(expr,in)
}

Testing gives: 测试给出:

scala> ParseList("""412285.556: """)
res150: ParseList.ParseResult[Any] = [1.13] parsed: (412285.556~List())

scala> ParseList("""412285.556: [Label 1.0:]""")
res151: ParseList.ParseResult[Any] = [1.25] parsed: (412285.556~List(List((Label~1.0))))

scala> ParseList("""412285.556: [Label 0.0:[Label1 1.0:][Label2 2.0:]]""")
res152: ParseList.ParseResult[Any] = [1.51] parsed: (412285.556~List(List((Label~0.0), List((Label1~1.0)), List((Label2~2.0)))))

When I try to make it a Map, if only returns the number, but calls the member routine. 当我尝试使其成为Map时,如果仅返回数字,但会调用成员例程。 See the debug output. 请参阅调试输出。

The Map parser: 地图解析器:

object ParseMap extends JavaTokenParsers {
  // Seperator
  def sep : Parser[String] = ":"
  // string
  def string : Parser[String] = """[a-zA-Z][a-zA-Z0-9]+""".r
  // Block within [] with label value: and option additional blocks
  def valueBlock: Parser[(String,Any)] =
      member <~ rep(obj)
  // Member - value pair within a block
  def member: Parser[(String, Any)] =
    string ~ floatingPointNumber <~ sep ^^
        { case s ~ n => (s, n); println("In Member s=" +s+" n="+n); (s, n)} 
  def obj: Parser[Map[String,Any]] =
    "["~> rep(valueBlock) <~"]"  ^^ {Map() ++ _}
  // Initial number value of the data
  def num: Parser[(String, Any)] =
          floatingPointNumber <~ sep ~ rep(obj) ^^
          {  case floatingPointNumber => ("Num", floatingPointNumber) }
  // order of operations
  def value: Parser[Any] = (
      num
      | obj
      | member
      | floatingPointNumber
      | string
      )
  def apply(in: String) = parseAll(value,in)
}

The testing gives: 测试给出:

scala> ParseMap("""412285.556: """)
res154: ParseMap.ParseResult[Any] = [1.13] parsed: (Num,412285.556)

scala> ParseMap("""412285.556: [Label 1.0:]""")
In Member s=Label n=1.0
res155: ParseMap.ParseResult[Any] = [1.25] parsed: (Num,412285.556)

scala> ParseMap("""412285.556: [Label 0.0:[Label1 1.0:][Label2 2.0:]]""")
In Member s=Label n=0.0
In Member s=Label1 n=1.0
In Member s=Label2 n=2.0
res156: ParseMap.ParseResult[Any] = [1.51] parsed: (Num,412285.556)

All my attempts to get a single Map out of it, has failed. 我尝试从中获取单个地图的所有尝试均以失败告终。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Scala's parser combinators are not the easiest thing to use, and they're extraordinarily slow. Scala的解析器组合器不是最容易使用的东西,并且它们的运行速度非常慢。 Try fastparse instead. 请尝试使用fastparse

I can't quite figure out what you want from that data (it's a very strange format!), but there's a nice guide to getting started . 我无法从这些数据中弄清楚您想要什么(这是一种非常奇怪的格式!),但是有一个很好的入门指南

Your core label-interpreter will probably look something like 您的核心标签解释器可能看起来像

val Pair = P(Label ~ " " ~ Num ~ ":")
val MapLine = P("[" Pair ~ ("[" ~ Pair ~ "]").rep ~ "]").
  map{ case (pair, pairs) => pair :: pairs.toList }

The main problem is your use of the <~ combinator in the num method - this throws away all parsed data that follows it (including the rep(obj) parse result that you want for your map). 主要问题是您在num方法中使用了<~组合器-丢弃了紧随其后的所有已解析数据(包括您要用于地图的rep(obj)解析结果)。 Modify that line to something like: 将该行修改为:

def num: Parser[(String, Any)] =
      floatingPointNumber ~ sep ~ rep(obj) ^^
      {  case floatingPointNumber ~ sep ~ objs => ("Num", (floatingPointNumber, objs)) }

and you start getting results like: 然后您开始得到如下结果:

scala> ParseMap("""412285.556: [Label 0.0:[Label1 1.0:][Label2 2.0:]]""")
In Member s=Label n=0.0
In Member s=Label1 n=1.0
In Member s=Label2 n=2.0
res3: ParseMap2.ParseResult[Any] = [1.51] parsed: (Num,(412285.556,List(Map(Label -> 0.0))))

which, while it probably doesn't look quite like what you might be wanting, should give you a starting point to progress further. 尽管看上去可能与您想要的不一样,但它应该为您提供进一步发展的起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM