1 /*
2 Copyright (c) 2015 Timur Gafarov 
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 
6 Permission is hereby granted, free of charge, to any person or organization
7 obtaining a copy of the software and accompanying documentation covered by
8 this license (the "Software") to use, reproduce, display, distribute,
9 execute, and transmit the Software, and to prepare derivative works of the
10 Software, and to permit third-parties to whom the Software is furnished to
11 do so, all subject to the following:
12 
13 The copyright notices in the Software and this entire statement, including
14 the above license grant, this restriction and the following disclaimer,
15 must be included in all copies of the Software, in whole or in part, and
16 all derivative works of the Software, unless such copies or derivative
17 works are solely in the form of machine-executable object code generated by
18 a source language processor.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 DEALINGS IN THE SOFTWARE.
27 */
28 
29 module dgl.dml.dml;
30 
31 import std.stdio;
32 import std.conv;
33 import dlib.core.memory;
34 import dlib.container.dict;
35 import dlib.coding.hash;
36 import dlib.math.vector;
37 import dlib.image.color;
38 import dgl.dml.lexer;
39 import dgl.dml.stringconv;
40 
41 struct DMLValue
42 {
43     string data;
44 
45     string toString()
46     {
47         return data;
48     }
49 
50     double toDouble()
51     {
52         return to!double(data);
53     }
54 
55     float toFloat()
56     {
57         return to!float(data);
58     }
59 
60     int toInt()
61     {
62         return to!int(data);
63     }
64 
65     bool toBool()
66     {
67         return cast(bool)to!int(data);
68     }
69 
70     Vector3f toVector3f()
71     {
72         return Vector3f(data);
73     }
74 
75     Vector4f toVector4f()
76     {
77         return Vector4f(data);
78     }
79 
80     Color4f toColor4f()
81     {
82         return Color4f(Vector4f(data));
83     }
84 }
85 
86 //TODO: rewrite without GC
87 struct DMLStruct
88 {
89     //DMLValue[string] data;
90     Dict!(DMLValue, string) data;
91     alias data this;
92     
93     static DMLStruct opCall()
94     {
95         DMLStruct s;
96         s.data = dict!(DMLValue, string);
97         return s;
98     }
99 
100     bool set(Lexeme key, Lexeme val)
101     {
102         string k = convToStr(key.str.data);
103         string v = convToStr(val.str.data[1..$-1]);
104 		return set(k, v);
105     }
106 	
107     bool set(string k, string v)
108     {
109         if (data is null)
110             data = dict!(DMLValue, string);
111         
112         data[k] = DMLValue(v);
113         return true;
114     }
115 
116     void free()
117     {
118         if (data !is null)
119             Delete(data);
120     }
121 }
122 
123 struct DMLData
124 {
125     DMLStruct root;
126     alias root this;
127     
128     static DMLData opCall()
129     {
130         DMLData d;
131         d.root = DMLStruct();
132         return d;
133     }
134 
135     void free()
136     {
137         root.free();
138     }
139 }
140 
141 bool parseDML(string text, DMLData* data)
142 {    
143     Lexer lexer = Lexer(text);
144 
145     Lexeme lexeme;
146     lexeme = lexer.get();
147     if (lexeme.valid)
148     {
149         if (lexeme.str.data == "{")
150         {
151             lexeme.free();
152             return parseStruct(&lexer, &data.root);
153         }
154         else
155         {
156             lexeme.valid = false;
157             writefln("DML error at line %s: expected \"{\", not \"%s\"", lexer.line, lexeme.str.data);
158             return false;
159         }
160     }
161     else
162     {
163         writeln("DML error: empty string");
164         return false;
165     }
166 }
167 
168 bool parseStruct(Lexer* lexer, DMLStruct* stru)
169 {
170     Lexeme lexeme = lexer.current;
171     bool noError = true;
172     while(noError && lexeme.valid && lexeme.str.data != "}")
173     {
174         lexeme = lexer.get();
175         if (lexeme.str.data != "}")
176         {
177             noError = parseStatement(lexer, stru);
178             lexeme = lexer.current;
179         }
180     }
181 
182     if (lexeme.str.data != "}")
183     {
184         lexeme.free();
185         writefln("DML syntax error at line %s: missing \"}\"", lexer.line);
186         return false;
187     }
188 
189     lexeme.free();
190     return noError;
191 }
192 
193 bool parseStatement(Lexer* lexer, DMLStruct* stru)
194 {
195     Lexeme id, value;
196     Lexeme lexeme = lexer.current;
197     // TODO: assert identifier
198 
199     id = lexeme;
200     lexeme = lexer.get();
201     if (lexeme.str.data != "=")
202     {
203         writefln("DML syntax error at line %s: \"=\" expected, got \"%s\"", lexer.line, lexeme.str.data);
204         lexeme.free();
205         return false;
206     }
207     lexeme.free();
208     lexeme = lexer.get();
209     if (!isString(lexeme))
210     {
211         writefln("DML syntax error at line %s: string expected, got \"%s\"", lexer.line, lexeme.str.data);
212         lexeme.free();
213         return false;
214     }
215     value = lexeme;
216     lexeme = lexer.get();
217     if (lexeme.str.data != ";")
218     {
219         writefln("DML syntax error at line %s: \";\" expected, got \"%s\"", lexer.line, lexeme.str.data);
220         lexeme.free();
221         return false;
222     }
223     lexeme.free();
224 
225     stru.set(id, value);
226     id.free();
227     value.free();
228 
229     return true;
230 }
231 
232 bool isString(Lexeme lexeme)
233 {
234     return lexeme.str.data[0] == '\"' &&
235            lexeme.str.data[$-1] == '\"';
236 }
237