一个简单的自定义配置格式的Scala实现


本来想执行我Object As Configuration的理念, 不过google group上有人推荐我看看configgy, 看过之后, 觉得还是自己写一个简单些, So 马上动手…

配置格式先简单定义为:

            ident = value
            groupId = {
             ident1 = value1
             ident2 = value2
             ...
            }
            

即可以配置为key-value的形式(以=或者:分割),或者group的形式(group暂时不考虑嵌套group的形式)。

定义一个Scala的Parser combinator如下:

class BlockOrItemConfigurationParser extends JavaTokenParsers {
            
              def entry = ((item | block) +) ^^ {
                _.foldLeft(Map[String, Any]()) {
                  (accum, i) =>
                    i._2 match {
                      case lst: List[(String, Any)] => accum ++ lst.foldLeft(Map[String, Any]()) {
                        (ac, it) =>
                          ac + ((i._1 + "." + it._1) -> it._2)
                      }
                      case x => accum + (i._1 -> x)
                    }
                }
              }
            
              def block = ident ~ "=" ~ "{" ~ rep(item) ~ "}" ^^ {
                case k ~ "=" ~ "{" ~ v ~ "}" => (k -> v)
              }
            
              def item = ident ~ ("=" | ":") ~ value <~ opt(";") ^^ {
                case k ~ _ ~ v => (k -> v)
              }
            
              def value = stringLit | decimalNumber | floatingPointNumber | booleanLiteral | nullLiteral
            
              def stringLit = "\"" ~> string <~ "\"" ^^ {
                case s => s
              }
            
              def string = ("""([^"\p{Cntrl}\\]|\\[\\/bfnrt]|\\u[a-fA-F0-9]{4})*""").r
            
              def booleanLiteral = "true" ^^^ true | "false" ^^^ false
            
              def nullLiteral = "null" ^^^ null
            }

代码写的有点儿矬, 将就看吧,呵呵, 本来用的JavaTokenParsers.stringLiteral, 但后来发现他没有去掉引号”, 所以,只能自己重新定义一个, 当然,代码直接拷贝它的。

有了parser之后, 就可以定义一个Configurator,比如:

class SimpleConfigurator(configFile:File) {
               val p = new BlockOrItemConfigurationParser
               p.parseAll(p.entry, new CharSeqReader(FileUtils.readFileToString(configFile))) match{
                    case p.Success(r, in)=> // use r to get parsed result and feed your program, hehe 
                    case x=> throw new Exception("parse error:"+x)
               }
            }

OK, That’s it!Have Fun!


>>>>>> 更多阅读 <<<<<<

「为AI疯狂」星球上,扶墙老师正在和朋友们讨论有趣的AI话题,你要不要⼀起来呀?^-^
这里

  1. 不但有及时新鲜的AI资讯和深度探讨
  2. 还分享AI工具、产品方法和商业机会
  3. 更有体系化精品付费内容等着你,加入星球(https://t.zsxq.com/0dI3ZA0sL) 即可免费领取。(加入之后一定记得看置顶消息呀!)

知识星球二维码

存量的时代,省钱就是赚钱。
在增量的时代,省钱其实是亏钱。
避坑儿是省钱的一种形式,更是真正聪明人的选择!
弯路虽然也是路,但还是能少走就少走,背后都是高昂的试错成本。
订阅「福报」,少踩坑,少走弯路,多走一步,就是不一样的胜率!

订阅「福报Premium订阅」