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