Parsing 在不使用太多变量的情况下解析基于行的结构(光线跟踪器)

Parsing 在不使用太多变量的情况下解析基于行的结构(光线跟踪器),parsing,scala,Parsing,Scala,我想在scala中解析一个文件(可能使用JavaTokerParser?)。可能不使用太多变量:-) 该文件是光线跟踪器的输入 它是一种基于行的文件结构 存在三种类型的行:空行、注释行和命令行 注释行以#开头(可能在#之前有一些空格) 命令行以一个标识符开始,后面可选地跟一系列参数(float或filename) 我该怎么办呢。我想这样称呼解析器 val scene=parseAll(场景文件,文件) 示例文件: #Cornell Box size 640 480 camera 0 0 1 0

我想在scala中解析一个文件(可能使用JavaTokerParser?)。可能不使用太多变量:-)

该文件是光线跟踪器的输入

它是一种基于行的文件结构

存在三种类型的行:空行、注释行和命令行

注释行以#开头(可能在#之前有一些空格) 命令行以一个标识符开始,后面可选地跟一系列参数(float或filename)

我该怎么办呢。我想这样称呼解析器

val scene=parseAll(场景文件,文件)

示例文件:

#Cornell Box
size 640 480
camera 0 0 1 0 0 -1 0 1 0 45
output scene6.png

maxdepth 5    
maxverts 12
#planar face
vertex -1 +1 0
vertex -1 -1 0
vertex +1 -1 0
vertex +1 +1 0

#cube
vertex -1 +1 +1
vertex +1 +1 +1
vertex -1 -1 +1
vertex +1 -1 +1

vertex -1 +1 -1
vertex +1 +1 -1
vertex -1 -1 -1
vertex +1 -1 -1


ambient 0 0 0
specular 0 0 0
shininess 1
emission 0 0 0
diffuse 0 0 0

attenuation 1 0.1 0.05

point 0 0.44 -1.5 0.8 0.8 0.8
directional 0 1 -1 0.2 0.2 0.2

diffuse 0 0 1
#sphere 0 0.8 -1.5 0.1


pushTransform

#red
pushTransform
translate 0 0 -3
rotate 0 1 0 60
scale 10 10 1
diffuse 1 0 0
tri 0 1 2
tri 0 2 3
popTransform

#green
pushTransform
translate 0 0 -3
rotate 0 1 0 -60
scale 10 10 1
diffuse 0 1 0
tri 0 1 2
tri 0 2 3
popTransform

#back
pushTransform
scale 10 10 1
translate 0 0 -2
diffuse 1 1 1
tri 0 1 2
tri 0 2 3
popTransform

#sphere
diffuse 0.7 0.5 0.2
specular 0.2 0.2 0.2
pushTransform
translate 0 -0.7 -1.5
scale 0.1 0.1 0.1
sphere 0 0 0 1
popTransform

#cube
diffuse 0.5 0.7 0.2
specular 0.2 0.2 0.2
pushTransform
translate -0.25 -0.4 -1.8
rotate 0 1 0 15
scale 0.25 0.4 0.2
diffuse 1 1 1

tri 4 6 5
tri 6 7 5
tri 4 5 8
tri 5 9 8
tri 7 9 5
tri 7 11 9
tri 4 8 10
tri 4 10 6
tri 6 10 11
tri 6 11 7
tri 10 8 9
tri 10 9 11
popTransform

popTransform

popTransform

也许我对一行的要求太高了,但这是我的观点(尽管习惯用法可能不是最优的):

首先,
CommandParams
以列表格式表示命令及其参数。如果没有参数,则我们有
None
args:

case class CommandParams(command:String, params:Option[List[String]])
下面是一行一行的文件解析和构造以及逐行解释:

val fileToDataStructure = Source.fromFile("file.txt").getLines()    //open file and get lines iterator
  .filter(!_.isEmpty)   //exclude empty lines
  .filter(!_.startsWith("#"))   //exclude comments
  .foldLeft(List[CommandParams]())    //iterate and store in a list of CommandParams
  {(listCmds:List[CommandParams], line:String) =>   //tuple of a list of objs so far and the current line
                    val arr = line.split("\\s")   //split line on any space delim
                    val command = arr.head    //first element of array is the command
                    val args = if(arr.tail.isEmpty) None else Option(arr.tail.toList)   //rest are their params
                    new CommandParams(command, args)::listCmds   //construct the obj and cons it to the list
  }
  .reverse    //due to cons concat we need to reverse to preserve order
迭代的演示输出:

fileToDataStructure.foreach(println)
收益率:

CommandParams(size,Some(List(640, 480)))
CommandParams(camera,Some(List(0, 0, 1, 0, 0, -1, 0, 1, 0, 45)))
CommandParams(output,Some(List(scene6.png)))
CommandParams(maxdepth,Some(List(5)))
CommandParams(maxverts,Some(List(12)))
CommandParams(vertex,Some(List(-1, +1, 0)))
...
CommandParams(pushTransform,None)
CommandParams(pushTransform,None)
CommandParams(translate,Some(List(0, 0, -3)))
...
加载后如何迭代以执行实际工作的演示:

fileToDataStructure.foreach{
  cmdParms => cmdParms match {
    case CommandParams(cmd, None) => println(s"I'm a ${cmd} with no args")
    case CommandParams(cmd, Some(args))=> println(s"I'm a ${cmd} with args: ${args.mkString(",")}")
  }
}
产量:

I'm a size with args: 640,480
I'm a camera with args: 0,0,1,0,0,-1,0,1,0,45
I'm a output with args: scene6.png
I'm a maxdepth with args: 5
I'm a maxverts with args: 12
I'm a vertex with args: -1,+1,0
...
I'm a popTransform with no args
I'm a popTransform with no args
谢谢:-)这比我现在的好。抱歉,响应太晚,我们仍然希望得到JavaTokenParsers解决方案:-)