1 // Copyright (C) 2000-2007, Luca Padovani <padovani@sti.uniurb.it>. 2 // 3 // This file is part of GtkMathView, a flexible, high-quality rendering 4 // engine for MathML documents. 5 // 6 // GtkMathView is free software; you can redistribute it and/or modify it 7 // under the terms of the GNU Lesser General Public License as published 8 // by the Free Software Foundation; either version 3 of the License, or 9 // (at your option) any later version. 10 // 11 // GtkMathView is distributed in the hope that it will be useful, but 12 // WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 // Lesser General Public License for more details. 15 // 16 // You should have received a copy of the GNU Lesser General Public License 17 // along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19 #ifndef __TemplateStringParsers_hh__ 20 #define __TemplateStringParsers_hh__ 21 22 #include "TokenSet.hh" 23 #include "TemplateStringScanners.hh" 24 #include "Variant.hh" 25 #include "Length.hh" 26 #include "ValueConversion.hh" 27 28 typedef Set<T_FALSE,T_TRUE> TokenSet_Boolean; 29 typedef Set<T_EM,T_EX,T_PX,T_IN,T_CM,T_MM,T_PT,T_PC,T__PERCENTAGE> TokenSet_Unit; 30 31 class ParseBin 32 { 33 public: sequence(void)34 static inline bool sequence(void) { return false; } 35 36 static bool parseInSequence(const UCS4String::const_iterator &,const UCS4String::const_iterator &,UCS4String::const_iterator &,std::vector<SmartPtr<Value>> &)37 parseInSequence(const UCS4String::const_iterator&, 38 const UCS4String::const_iterator&, 39 UCS4String::const_iterator&, 40 std::vector< SmartPtr<Value> >&) 41 { 42 assert(false); 43 } 44 }; 45 46 template <typename Scanner, typename NativeType> 47 class Parse : public ParseBin 48 { 49 public: 50 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)51 parse(const UCS4String::const_iterator& begin, 52 const UCS4String::const_iterator& end, 53 UCS4String::const_iterator& next) 54 { 55 UCS4String::const_iterator p; 56 ScanSpaces::scan(begin, end, p); 57 if (Scanner::scan(p, end, next)) 58 { 59 NativeType v = Scanner::parse(p, next); 60 return Variant<NativeType>::create(v); 61 } 62 return 0; 63 } 64 }; 65 66 template <> 67 class Parse<ScanToken, bool> 68 { 69 public: 70 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)71 parse(const UCS4String::const_iterator& begin, 72 const UCS4String::const_iterator& end, 73 UCS4String::const_iterator& next) 74 { 75 UCS4String::const_iterator p; 76 ScanSpaces::scan(begin, end, p); 77 if (ScanToken::scan(p, end, next)) 78 { 79 TokenId id = ScanToken::parse(p, next); 80 if (TokenSet_Boolean::has(id)) 81 return Variant<bool>::create(id == T_TRUE); 82 } 83 return 0; 84 } 85 }; 86 87 class ParseLength : public ParseBin 88 { 89 public: 90 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)91 parse(const UCS4String::const_iterator& begin, 92 const UCS4String::const_iterator& end, 93 UCS4String::const_iterator& next) 94 { 95 UCS4String::const_iterator p; 96 ScanSpaces::scan(begin, end, p); 97 if (ScanNumber::scan(p, end, next)) 98 { 99 float v = ScanNumber::parse(p, next); 100 p = next; 101 ScanSpaces::scan(p, end, next); 102 p = next; 103 if (ScanToken::scan(p, end, next)) 104 { 105 TokenId id = ScanToken::parse(p, next); 106 if (TokenSet_Unit::has(id)) 107 return Variant<Length>::create(Length(v, toUnitId(id))); 108 } 109 } 110 return 0; 111 } 112 }; 113 114 class ParseString : public ParseBin 115 { 116 public: 117 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)118 parse(const UCS4String::const_iterator& begin, 119 const UCS4String::const_iterator& end, 120 UCS4String::const_iterator& next) 121 { 122 next = end; 123 return Variant<String>::create(Scan::toString(begin, end)); 124 } 125 }; 126 127 class ParseKeyword : public ParseBin 128 { 129 public: 130 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)131 parse(const UCS4String::const_iterator& begin, 132 const UCS4String::const_iterator& end, 133 UCS4String::const_iterator& next) 134 { 135 UCS4String::const_iterator p; 136 ScanSpaces::scan(begin, end, p); 137 if (ScanKeywordToken::scan(p, end, next)) 138 return Variant<String>::create(Scan::toString(p, next)); 139 else 140 return 0; 141 } 142 }; 143 144 template <typename TokenSet> 145 class ParseTokenSet : public ParseBin 146 { 147 public: 148 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)149 parse(const UCS4String::const_iterator& begin, 150 const UCS4String::const_iterator& end, 151 UCS4String::const_iterator& next) 152 { 153 UCS4String::const_iterator p; 154 ScanSpaces::scan(begin, end, p); 155 if (ScanToken::scan(p, end, next)) 156 { 157 TokenId id = ScanToken::parse(p, next); 158 if (TokenSet::has(id)) return Variant<TokenId>::create(id); 159 } 160 return 0; 161 } 162 }; 163 164 template <TokenId id> 165 class ParseToken : public ParseTokenSet< Singleton<id> > 166 { }; 167 168 template <typename P1, typename P2> 169 class ParseChoice : public ParseBin 170 { 171 public: 172 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)173 parse(const UCS4String::const_iterator& begin, 174 const UCS4String::const_iterator& end, 175 UCS4String::const_iterator& next) 176 { 177 if (SmartPtr<Value> v = P1::parse(begin, end, next)) 178 return v; 179 else 180 return P2::parse(begin, end, next); 181 } 182 }; 183 184 template <typename P1, typename P2> 185 class ParseSeq 186 { 187 public: sequence(void)188 static inline bool sequence(void) { return true; } 189 190 static bool parseInSequence(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next,std::vector<SmartPtr<Value>> & content)191 parseInSequence(const UCS4String::const_iterator& begin, 192 const UCS4String::const_iterator& end, 193 UCS4String::const_iterator& next, 194 std::vector< SmartPtr<Value> >& content) 195 { 196 UCS4String::const_iterator p; 197 if (P1::sequence()) 198 { 199 if (!P1::parseInSequence(begin, end, p, content)) 200 return false; 201 } 202 else if (SmartPtr<Value> v = P1::parse(begin, end, p)) 203 content.push_back(v); 204 else 205 return false; 206 207 if (P2::sequence()) 208 { 209 if (!P2::parseInSequence(p, end, next, content)) 210 return false; 211 } 212 else if (SmartPtr<Value> v = P2::parse(p, end, next)) 213 content.push_back(v); 214 else 215 return false; 216 217 return true; 218 } 219 220 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)221 parse(const UCS4String::const_iterator& begin, 222 const UCS4String::const_iterator& end, 223 UCS4String::const_iterator& next) 224 { 225 std::vector< SmartPtr<Value> > content; 226 if (parseInSequence(begin, end, next, content)) 227 return Variant<std::vector< SmartPtr<Value> > >::create(content); 228 else 229 return 0; 230 } 231 }; 232 233 template <typename P> 234 class ParseZeroOrOne : public ParseBin 235 { 236 public: 237 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)238 parse(const UCS4String::const_iterator& begin, 239 const UCS4String::const_iterator& end, 240 UCS4String::const_iterator& next) 241 { 242 if (SmartPtr<Value> v = P::parse(begin, end, next)) 243 return v; 244 else 245 { 246 next = begin; 247 return Variant<void>::create(); 248 } 249 } 250 }; 251 252 template <typename P> 253 class ParseOneOrMore : public ParseBin 254 { 255 public: 256 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)257 parse(const UCS4String::const_iterator& begin, 258 const UCS4String::const_iterator& end, 259 UCS4String::const_iterator& next) 260 { 261 UCS4String::const_iterator p = begin; 262 std::vector< SmartPtr<Value> > content; 263 while (SmartPtr<Value> v = P::parse(p, end, next)) 264 { 265 content.push_back(v); 266 p = next; 267 } 268 269 if (!content.empty()) 270 { 271 next = p; 272 return Variant< std::vector< SmartPtr<Value> > >::create(content); 273 } 274 else 275 return 0; 276 } 277 }; 278 279 template <typename P> 280 class ParseZeroOrMore : public ParseZeroOrOne< ParseOneOrMore<P> > 281 { }; 282 283 class ParseRGBColor 284 { 285 public: 286 static SmartPtr<Value> parse(const UCS4String::const_iterator & begin,const UCS4String::const_iterator & end,UCS4String::const_iterator & next)287 parse(const UCS4String::const_iterator& begin, 288 const UCS4String::const_iterator& end, 289 UCS4String::const_iterator& next) 290 { 291 UCS4String::const_iterator p; 292 ScanSpaces::scan(begin, end, p); 293 if (ScanRGBColor::scan(p, end, next)) 294 return Variant<RGBColor>::create(ScanRGBColor::parse(p, next)); 295 else 296 return 0; 297 } 298 }; 299 300 #endif // __TemplateStringParsers_hh__ 301 302