lib/gamnit: intro new services and refine `StringProcessor` to read model files
[nit.git] / lib / gamnit / model_parsers / model_parser_base.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 # Services to parse models from a text description
16 module model_parser_base
17
18 import parser_base
19
20 # Vector of 3 values, either `x, y, z`, `u, v, z` or `r, g, b`
21 class Vec3
22
23 # X value
24 var x = 0.0 is writable
25
26 # Y value
27 var y = 0.0 is writable
28
29 # Z value
30 var z = 0.0 is writable
31
32 # U value (redirection as `x`)
33 fun u: Float do return x
34
35 # Set U value (redirection for `x=`)
36 fun u=(value: Float) do x = value
37
38 # V value (redirection as `y`)
39 fun v: Float do return y
40
41 # Set V value (redirection for `y=`)
42 fun v=(value: Float) do y = value
43
44 # R value
45 fun r: Float do return x
46
47 # Set R value (redirection for `x=`)
48 fun r=(value: Float) do x = value
49
50 # G value
51 fun g: Float do return y
52
53 # Set G value (redirection for `y=`)
54 fun g=(value: Float) do y = value
55
56 # B value
57 fun b: Float do return z
58
59 # Set B value (redirection for `z=`)
60 fun b=(value: Float) do z = value
61
62 # Return all values into a new `Array[Float]`
63 fun to_a: Array[Float] do return [x, y, z]
64
65 redef fun to_s do return "<{class_name} {x} {y} {z}>"
66 end
67
68 # Vector of 4 values, either `x, y, z, w`, `u, v, z, w` or `r, g, b, a`
69 class Vec4
70 super Vec3
71
72 # W value
73 var w = 1.0 is writable
74
75 # A value (redirection to `z`)
76 fun a: Float do return z
77
78 # Set A value (redirection for `z=`)
79 fun a=(value: Float) do z = value
80
81 # Return all values into a new `Array[Float]`
82 redef fun to_a do return [x, y, z, w]
83
84 redef fun to_s do return "<{class_name} {x} {y} {z} {w}>"
85 end
86
87 redef class StringProcessor
88 # Read a single token after skipping preceding whitespaces
89 #
90 # Returns an empty string when at `eof`
91 protected fun read_token: String
92 do
93 while not eof and src[pos].is_whitespace and src[pos] != '\n' do
94 pos += 1
95 end
96
97 var start = pos
98 ignore_until_whitespace_or_comment
99 var ending = pos
100 var str = src.substring(start, ending-start)
101 return str
102 end
103
104 # Read 3 or 4 numbers and return them as a `Vec4`
105 #
106 # If there is no fourth value, `Vec4::w` is set to 1.0.
107 protected fun read_vec4: Vec4
108 do
109 var vec = new Vec4
110 vec.x = read_number
111 vec.y = read_number
112 vec.z = read_number
113
114 var wstr = read_token
115 if wstr.length > 0 then
116 vec.w = if wstr.is_numeric then wstr.to_f else 0.0
117 else
118 vec.w = 1.0
119 end
120
121 return vec
122 end
123
124 # Read 2 or 3 numbers and return them as a `Vec3`
125 #
126 # If there is no third value, `Vec3::z` is set to 0.0.
127 protected fun read_vec3: Vec3
128 do
129 var vec = new Vec3
130 vec.x = read_number
131 vec.y = read_number # Make optional
132
133 var wstr = read_token
134 if wstr.length > 0 then
135 vec.z = if wstr.is_numeric then wstr.to_f else 0.0
136 else
137 vec.z = 0.0
138 end
139
140 return vec
141 end
142
143 # Advance `pos` until a whitespace or `#` is encountered
144 protected fun ignore_until_whitespace_or_comment: Int
145 do
146 while src.length > pos and not src[pos].is_whitespace and src[pos] != '#' do
147 pos += 1
148 end
149 return pos
150 end
151
152 # Read a token and parse it as a `Float`
153 protected fun read_number: Float
154 do
155 var str = read_token
156 return if str.is_numeric then str.to_f else 0.0
157 end
158
159 # Advance `pos` until the next end of line or a `#`
160 protected fun read_until_eol_or_comment: String
161 do
162 ignore_whitespaces
163 var start = pos
164 while not eof and src[pos] != '#' and src[pos] != '\n' do
165 pos += 1
166 end
167 var ending = pos
168 var str = src.substring(start, ending-start)
169 return str.trim
170 end
171
172 # Advance `pos` to skip the next end of line
173 protected fun skip_eol
174 do
175 while not eof do
176 var c = src.chars[pos]
177 pos += 1
178 if c == '\n' then break
179 end
180 end
181 end