source: icGREP/icgrep-devel/icgrep/pbix_compiler.cpp @ 4086

Last change on this file since 4086 was 4086, checked in by cameron, 5 years ago

Support for Pablo if-statements; use for utf-8 scope streams

File size: 14.6 KB
Line 
1/*
2 *  Copyright (c) 2014 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "pbix_compiler.h"
8#include "printer_pablos.h"
9
10Pbix_Compiler::Pbix_Compiler(std::map<std::string, std::string> name_map)
11{
12    m_name_map = name_map;
13    symgen = SymbolGenerator();
14}
15
16CodeGenState Pbix_Compiler::compile_subexpressions(const std::map<std::string, RE*>& re_map)
17{
18    CodeGenState cg_state;
19
20    for (auto it =  re_map.rbegin(); it != re_map.rend(); ++it)
21    {
22        //This is specifically for the utf8 multibyte character classes.
23        if (Seq* seq = dynamic_cast<Seq*>(it->second))
24        {
25            if (seq->getType() == Seq::Byte)
26            {
27                std::string gs_retVal = symgen.gensym("start_marker");
28                cg_state.stmtsl.push_back(new Assign(gs_retVal, new All(1)));
29                cg_state.newsym = gs_retVal;
30
31                std::list<RE*>::iterator endit;
32                endit = seq->GetREList()->end();
33                --endit;
34                std::list<RE*>::iterator it;
35                for (it = seq->GetREList()->begin(); it != seq->GetREList()->end(); ++it)
36                {
37                    Name* name = dynamic_cast<Name*>(*it);
38                    if (it != endit)
39                    {
40                        gs_retVal = symgen.gensym("marker");
41                        cg_state.stmtsl.push_back(new Assign(gs_retVal, new Advance(new And(new Var(cg_state.newsym), new CharClass(name->getName())))));
42                        cg_state.newsym = gs_retVal;
43                    }
44                    else
45                    {
46                        cg_state.stmtsl.push_back(new Assign(seq->getName(), new And(new Var(cg_state.newsym), new CharClass(name->getName()))));
47                    }
48                }
49            }
50        }
51    }
52
53    return cg_state;
54}
55
56CodeGenState Pbix_Compiler::compile(RE *re)
57{   
58    CodeGenState cg_state;
59
60    std::string gs_m0 = symgen.gensym("start_marker");
61    cg_state.stmtsl.push_back(new Assign(gs_m0, new All(1)));
62
63    if (unicode_re(re))
64    {
65        cg_state.newsym = gs_m0;
66        //Set the 'internal.initial' bit stream for the utf-8 multi-byte encoding.
67        std::string gs_initial = symgen.gensym("internal.initial");
68        m_name_map.insert(make_pair("internal.initial", gs_initial));
69        PabloE * u8single = new Var(m_name_map.find("UTF8-SingleByte")->second);
70        PabloE * u8pfx2 = new Var(m_name_map.find("UTF8-Prefix2")->second);
71        PabloE * u8pfx3 = new Var(m_name_map.find("UTF8-Prefix3")->second);
72        PabloE * u8pfx4 = new Var(m_name_map.find("UTF8-Prefix4")->second);
73        PabloE * u8pfx = new Or(new Or(u8pfx2, u8pfx3), u8pfx4);
74        cg_state.stmtsl.push_back(new Assign(gs_initial, new Or(u8pfx, u8single)));
75
76#if 0
77        cg_state.stmtsl.push_back(new Assign(gs_initial, new Or(new Or( new Or( new And(new Var(m_name_map.find("UTF8-Prefix2")->second),
78            new Var(cg_state.newsym)),  new And(new Var(m_name_map.find("UTF8-SingleByte")->second), new Var(cg_state.newsym))),
79            new And(new Var(m_name_map.find("UTF8-Prefix3")->second), new Var(cg_state.newsym))),
80            new And(new Var(m_name_map.find("UTF8-Prefix4")->second), new Var(cg_state.newsym)))));
81#endif
82        cg_state.newsym = gs_initial;
83
84        //Set the 'internal.nonfinal' bit stream for the utf-8 multi-byte encoding.
85        cg_state.newsym = gs_m0;
86        std::string gs_nonfinal = symgen.gensym("internal.nonfinal");
87        m_name_map.insert(make_pair("internal.nonfinal", gs_nonfinal));
88        cg_state.stmtsl.push_back(new Assign(gs_nonfinal, new All(0)));
89        PabloE * u8scope32 = new Advance(u8pfx3);
90        PabloE * u8scope42 = new Advance(u8pfx4);
91        PabloE * u8scope43 = new Advance(u8scope42);
92        PabloS * assign_non_final = new Assign(gs_nonfinal, new Or(new Or(u8pfx, u8scope32), new Or(u8scope42, u8scope43)));
93        std::list<PabloS *> * if_body = new std::list<PabloS *> ();
94        if_body->push_back(assign_non_final);
95        cg_state.stmtsl.push_back(new If(u8pfx, *if_body));
96#if 0
97        cg_state.stmtsl.push_back(new Assign(gs_nonfinal, new Or(new Or(new Or(new Or(new Or( new And(new Var(m_name_map.find("UTF8-Prefix3")->second),
98            new Var(cg_state.newsym)),  new And(new Var(m_name_map.find("UTF8-Prefix2")->second), new Var(cg_state.newsym))),
99            new Advance( new And(new Var(m_name_map.find("UTF8-Prefix3")->second), new Var(cg_state.newsym)))),
100            new And(new Var(m_name_map.find("UTF8-Prefix4")->second), new Var(cg_state.newsym))), new Advance(
101            new And(new Var(m_name_map.find("UTF8-Prefix4")->second), new Var(cg_state.newsym)))), new Advance(
102            new Advance( new And(new Var(m_name_map.find("UTF8-Prefix4")->second), new Var(cg_state.newsym)))))));
103#endif
104        cg_state.newsym = gs_nonfinal;
105    }
106
107    cg_state.newsym = gs_m0;
108    cg_state = re2pablo_helper(re, cg_state);
109
110    //These three lines are specifically for grep.
111    std::string gs_retVal = symgen.gensym("marker");
112    cg_state.stmtsl.push_back(new Assign(gs_retVal, new And(new MatchStar(new Var(cg_state.newsym),
113        new Not(new Var(m_name_map.find("LineFeed")->second))), new Var(m_name_map.find("LineFeed")->second))));
114    cg_state.newsym = gs_retVal;
115
116    return cg_state;
117}
118
119CodeGenState Pbix_Compiler::re2pablo_helper(RE *re, CodeGenState cg_state)
120{
121    if (Name* name = dynamic_cast<Name*>(re))
122    {
123        std::string gs_retVal = symgen.gensym("marker");
124        PabloE* markerExpr = new Var(cg_state.newsym);
125        if (name->getType() != Name::FixedLength) {
126            // Move the markers forward through any nonfinal UTF-8 bytes to the final position of each character.
127            markerExpr = new And(markerExpr, new CharClass(m_name_map.find("internal.initial")->second));
128            markerExpr = new ScanThru(markerExpr, new CharClass(m_name_map.find("internal.nonfinal")->second));
129        }       
130        PabloE* ccExpr;
131        if (name->getType() == Name::UnicodeCategory)
132        {
133            ccExpr = new Call(name->getName());
134        }
135        else 
136        {
137            ccExpr = new CharClass(name->getName());
138        }
139        if (name->isNegated()) {
140            ccExpr = new Not(new Or(new Or(ccExpr, new CharClass(m_name_map.find("LineFeed")->second)),
141                                    new CharClass(m_name_map.find("internal.nonfinal")->second)));
142        }
143        cg_state.stmtsl.push_back(new Assign(gs_retVal, new Advance(new And(ccExpr, markerExpr))));
144        cg_state.newsym = gs_retVal;
145
146        //std::cout << "\n" << "(" << StatementPrinter::PrintStmts(cg_state) << ")" << "\n" << std::endl;
147    }
148    else if (Start* start = dynamic_cast<Start*>(re))
149    {
150        std::string gs_retVal = symgen.gensym("start_of_line_marker");
151        cg_state.stmtsl.push_back(new Assign(gs_retVal, new And(new Var(cg_state.newsym), new Not(new Advance(new Not(new CharClass(m_name_map.find("LineFeed")->second)))))));
152        cg_state.newsym = gs_retVal;
153    }
154    else if (End* end = dynamic_cast<End*>(re))
155    {
156        std::string gs_retVal = symgen.gensym("end_of_line_marker");
157        cg_state.stmtsl.push_back(new Assign(gs_retVal, new And(new Var(cg_state.newsym), new CharClass(m_name_map.find("LineFeed")->second))));
158        cg_state.newsym = gs_retVal;
159    }
160    else if (Seq* seq = dynamic_cast<Seq*>(re))
161    {
162        std::list<RE*>::iterator it = seq->GetREList()->begin();
163        if (it != seq->GetREList()->end())
164        {
165            cg_state = Seq_helper(seq->GetREList(), it, cg_state);
166        }
167    //cout << "\n" << "Seq => (" << StatementPrinter::PrintStmts(cg_state) << ")" << "\n" << endl;
168    }
169    else if (Alt* alt = dynamic_cast<Alt*>(re))
170    {
171        if (alt->GetREList() == 0)
172        {
173
174            std::string gs_retVal = symgen.gensym("always_fail_marker");
175            cg_state.stmtsl.push_back(new Assign(gs_retVal, new All(0)));
176            cg_state.newsym = gs_retVal;
177        }
178        else
179        {
180            if (alt->GetREList()->size() == 1)
181            {
182                cg_state = re2pablo_helper(alt->GetREList()->front(), cg_state);
183            }
184            else
185            {
186                std::list<RE*>::iterator it = alt->GetREList()->begin();
187                cg_state = Alt_helper(alt->GetREList(), it, cg_state);
188            }
189        }
190    //cout << "\n" << "Alt => (" << StatementPrinter::PrintStmts(cg_state) << ")" << "\n" << endl;
191    }
192    else if (Rep* rep = dynamic_cast<Rep*>(re))
193    {
194        if ((dynamic_cast<Name*>(rep->getRE()) != 0) && (rep->getLB() == 0) && (rep->getUB()== unboundedRep))
195        {
196            Name* rep_name = dynamic_cast<Name*>(rep->getRE());
197            std::string gs_retVal = symgen.gensym("marker");
198
199            PabloE* ccExpr;
200            if (rep_name->getType() == Name::UnicodeCategory)
201            {
202                ccExpr = new Call(rep_name->getName());
203            }
204            else 
205            {
206                ccExpr = new CharClass(rep_name->getName());
207            }
208
209            if (rep_name->isNegated()) {
210                ccExpr = new Not(new Or(new Or(ccExpr, new CharClass(m_name_map.find("LineFeed")->second)),
211                                        new CharClass(m_name_map.find("internal.nonfinal")->second)));
212            }
213            if (rep_name->getType() == Name::FixedLength)
214            {
215                cg_state.stmtsl.push_back(new Assign(gs_retVal, new MatchStar(new Var(cg_state.newsym), ccExpr)));
216            }
217            else //Name::Unicode and Name::UnicodeCategory
218            {
219                cg_state.stmtsl.push_back(new Assign(gs_retVal,
220                    new And(new MatchStar(new Var(cg_state.newsym), new Or(new CharClass(m_name_map.find("internal.nonfinal")->second),
221                    ccExpr)), new CharClass(m_name_map.find("internal.initial")->second))));
222            }
223
224            cg_state.newsym = gs_retVal;
225        }
226        else if (rep->getUB() == unboundedRep)
227        {
228            if (rep->getLB() == 0)
229            {
230                //std::cout << "While, no lb." << std::endl;
231
232                std::string while_test_gs_retVal = symgen.gensym("while_test");
233                std::string while_accum_gs_retVal = symgen.gensym("while_accum");
234                CodeGenState while_test_state;
235                while_test_state.newsym = while_test_gs_retVal;
236                CodeGenState t1_cg_state = re2pablo_helper(rep->getRE(), while_test_state);
237                cg_state.stmtsl.push_back(new Assign(while_test_gs_retVal, new Var(cg_state.newsym)));
238                cg_state.stmtsl.push_back(new Assign(while_accum_gs_retVal, new Var(cg_state.newsym)));
239                std::list<PabloS*> stmtList;
240                stmtList = t1_cg_state.stmtsl;
241                stmtList.push_back(new Assign(while_test_gs_retVal, new And(new Var(t1_cg_state.newsym), new Not(new Var(while_accum_gs_retVal)))));
242                stmtList.push_back(new Assign(while_accum_gs_retVal, new Or(new Var(while_accum_gs_retVal), new Var(t1_cg_state.newsym))));
243                cg_state.stmtsl.push_back( new While(new Var(while_test_gs_retVal), stmtList));
244                cg_state.newsym = while_accum_gs_retVal;
245            }
246            else //if (rep->getLB() > 1)
247            {
248                CodeGenState t1_cg_state = re2pablo_helper(rep->getRE(), cg_state);
249                rep->setLB(rep->getLB() - 1);
250                cg_state = re2pablo_helper(rep, t1_cg_state);
251            }
252        }
253        else if (rep->getUB() != unboundedRep)
254        {
255            if ((rep->getLB() == 0) && (rep->getUB() == 0))
256            {
257                //Just fall through...do nothing.
258            }
259            else if ((rep->getLB() == 0) && (rep->getUB() > 0))
260            {
261                CodeGenState t1_cg_state = re2pablo_helper(rep->getRE(), cg_state);
262                rep->setUB(rep->getUB() - 1);
263                CodeGenState t2_cg_state = re2pablo_helper(re, t1_cg_state);
264                std::string gs_retVal = symgen.gensym("alt_marker");
265                cg_state.stmtsl = t2_cg_state.stmtsl;
266                cg_state.stmtsl.push_back(new Assign(gs_retVal, new Or(new Var(cg_state.newsym), new Var(t2_cg_state.newsym))));
267                cg_state.newsym = gs_retVal;
268            }
269            else //if ((rep->getLB() > 0) && (rep->getUB() > 0))
270            {
271                CodeGenState t1_cg_state = re2pablo_helper(rep->getRE(), cg_state);
272                rep->setLB(rep->getLB() - 1);
273                rep->setUB(rep->getUB() - 1);
274                cg_state = re2pablo_helper(rep, t1_cg_state);
275            }
276        }
277    }
278
279    return cg_state;
280}
281
282CodeGenState Pbix_Compiler::Seq_helper(std::list<RE*>* lst, std::list<RE*>::const_iterator it, CodeGenState cg_state)
283{
284    if (it != lst->end())
285    {
286        cg_state = re2pablo_helper(*it, cg_state);
287        cg_state = Seq_helper(lst, ++it, cg_state);
288    }
289
290    return cg_state;
291}
292
293CodeGenState Pbix_Compiler::Alt_helper(std::list<RE*>* lst, std::list<RE*>::const_iterator it, CodeGenState cg_state)
294{
295    CodeGenState t1_cg_state = re2pablo_helper(*it, cg_state);
296    cg_state.stmtsl = t1_cg_state.stmtsl;
297    ++it;
298    if (it != lst->end())
299    {
300        CodeGenState t2_cg_state = Alt_helper(lst, it, cg_state);
301        cg_state.stmtsl = t2_cg_state.stmtsl;
302        std::string gs_retVal = symgen.gensym("alt_marker");
303        cg_state.stmtsl.push_back(new Assign(gs_retVal, new Or(new Var(t1_cg_state.newsym), new Var(t2_cg_state.newsym))));
304        cg_state.newsym = gs_retVal;
305    }
306    else
307    {
308        cg_state.newsym = t1_cg_state.newsym;
309    }
310
311    return cg_state;
312}
313
314bool Pbix_Compiler::unicode_re(RE *re)
315{
316    bool found = false;
317
318    return unicode_re_helper(re, found);
319}
320
321bool Pbix_Compiler::unicode_re_helper(RE *re, bool found)
322{
323    if (!found)
324    {
325        if (Name* name = dynamic_cast<Name*>(re))
326        {
327            if ((name->getType() == Name::UnicodeCategory) || (name->getType() == Name::Unicode))
328            {
329                found = true;
330            }
331        }
332        else if (Seq* re_seq = dynamic_cast<Seq*>(re))
333        {
334            std::list<RE*>::iterator it;
335            for (it = re_seq->GetREList()->begin(); it != re_seq->GetREList()->end(); ++it)
336            {
337                found = unicode_re_helper(*it, found);
338                if (found) break;
339            }
340        }
341        else if (Alt* re_alt = dynamic_cast<Alt*>(re))
342        {
343            std::list<RE*>::iterator it;
344            for (it = re_alt->GetREList()->begin(); it != re_alt->GetREList()->end(); ++it)
345            {
346                found = unicode_re_helper(*it, found);
347                if (found) break;
348            }
349        }
350        else if (Rep* rep = dynamic_cast<Rep*>(re))
351        {
352            found = unicode_re_helper(rep->getRE(), found);
353        }
354    }
355
356    return found;
357}
Note: See TracBrowser for help on using the repository browser.