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