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

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

Bug fix for bounded repetition

File size: 13.5 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        cg_state.newsym = gs_initial;
76
77        //Set the 'internal.nonfinal' bit stream for the utf-8 multi-byte encoding.
78        cg_state.newsym = gs_m0;
79        std::string gs_nonfinal = symgen.gensym("internal.nonfinal");
80        m_name_map.insert(make_pair("internal.nonfinal", gs_nonfinal));
81//#define USE_IF_FOR_NONFINAL
82#ifdef USE_IF_FOR_NONFINAL
83        cg_state.stmtsl.push_back(new Assign(gs_nonfinal, new All(0)));
84#endif
85        PabloE * u8scope32 = new Advance(u8pfx3);
86        PabloE * u8scope42 = new Advance(u8pfx4);
87        PabloE * u8scope43 = new Advance(u8scope42);
88        PabloS * assign_non_final = new Assign(gs_nonfinal, new Or(new Or(u8pfx, u8scope32), new Or(u8scope42, u8scope43)));
89#ifdef USE_IF_FOR_NONFINAL
90        std::list<PabloS *> * if_body = new std::list<PabloS *> ();
91        if_body->push_back(assign_non_final);
92        cg_state.stmtsl.push_back(new If(u8pfx, *if_body));
93#endif
94#ifndef USE_IF_FOR_NONFINAL
95        cg_state.stmtsl.push_back(assign_non_final);
96#endif
97        cg_state.newsym = gs_nonfinal;
98    }
99
100    cg_state.newsym = gs_m0;
101    cg_state = re2pablo_helper(re, cg_state);
102
103    //These three lines are specifically for grep.
104    std::string gs_retVal = symgen.gensym("marker");
105    cg_state.stmtsl.push_back(new Assign(gs_retVal, new And(new MatchStar(new Var(cg_state.newsym),
106        new Not(new Var(m_name_map.find("LineFeed")->second))), new Var(m_name_map.find("LineFeed")->second))));
107    cg_state.newsym = gs_retVal;
108
109    return cg_state;
110}
111
112CodeGenState Pbix_Compiler::re2pablo_helper(RE *re, CodeGenState cg_state)
113{
114    if (Name* name = dynamic_cast<Name*>(re))
115    {
116        std::string gs_retVal = symgen.gensym("marker");
117        PabloE* markerExpr = new Var(cg_state.newsym);
118        if (name->getType() != Name::FixedLength) {
119            // Move the markers forward through any nonfinal UTF-8 bytes to the final position of each character.
120            markerExpr = new And(markerExpr, new CharClass(m_name_map.find("internal.initial")->second));
121            markerExpr = new ScanThru(markerExpr, new CharClass(m_name_map.find("internal.nonfinal")->second));
122        }       
123        PabloE* ccExpr;
124        if (name->getType() == Name::UnicodeCategory)
125        {
126            ccExpr = new Call(name->getName());
127        }
128        else 
129        {
130            ccExpr = new CharClass(name->getName());
131        }
132        if (name->isNegated()) {
133            ccExpr = new Not(new Or(new Or(ccExpr, new CharClass(m_name_map.find("LineFeed")->second)),
134                                    new CharClass(m_name_map.find("internal.nonfinal")->second)));
135        }
136        cg_state.stmtsl.push_back(new Assign(gs_retVal, new Advance(new And(ccExpr, markerExpr))));
137        cg_state.newsym = gs_retVal;
138
139        //std::cout << "\n" << "(" << StatementPrinter::PrintStmts(cg_state) << ")" << "\n" << std::endl;
140    }
141    else if (Start* start = dynamic_cast<Start*>(re))
142    {
143        std::string gs_retVal = symgen.gensym("start_of_line_marker");
144        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)))))));
145        cg_state.newsym = gs_retVal;
146    }
147    else if (End* end = dynamic_cast<End*>(re))
148    {
149        std::string gs_retVal = symgen.gensym("end_of_line_marker");
150        cg_state.stmtsl.push_back(new Assign(gs_retVal, new And(new Var(cg_state.newsym), new CharClass(m_name_map.find("LineFeed")->second))));
151        cg_state.newsym = gs_retVal;
152    }
153    else if (Seq* seq = dynamic_cast<Seq*>(re))
154    {
155        std::list<RE*>::iterator it = seq->GetREList()->begin();
156        if (it != seq->GetREList()->end())
157        {
158            cg_state = Seq_helper(seq->GetREList(), it, cg_state);
159        }
160    //cout << "\n" << "Seq => (" << StatementPrinter::PrintStmts(cg_state) << ")" << "\n" << endl;
161    }
162    else if (Alt* alt = dynamic_cast<Alt*>(re))
163    {
164        if (alt->GetREList() == 0)
165        {
166
167            std::string gs_retVal = symgen.gensym("always_fail_marker");
168            cg_state.stmtsl.push_back(new Assign(gs_retVal, new All(0)));
169            cg_state.newsym = gs_retVal;
170        }
171        else
172        {
173            if (alt->GetREList()->size() == 1)
174            {
175                cg_state = re2pablo_helper(alt->GetREList()->front(), cg_state);
176            }
177            else
178            {
179                std::list<RE*>::iterator it = alt->GetREList()->begin();
180                cg_state = Alt_helper(alt->GetREList(), it, cg_state);
181            }
182        }
183    //cout << "\n" << "Alt => (" << StatementPrinter::PrintStmts(cg_state) << ")" << "\n" << endl;
184    }
185    else if (Rep* rep = dynamic_cast<Rep*>(re))
186    {
187        if ((dynamic_cast<Name*>(rep->getRE()) != 0) && (rep->getLB() == 0) && (rep->getUB()== unboundedRep))
188        {
189            Name* rep_name = dynamic_cast<Name*>(rep->getRE());
190            std::string gs_retVal = symgen.gensym("marker");
191
192            PabloE* ccExpr;
193            if (rep_name->getType() == Name::UnicodeCategory)
194            {
195                ccExpr = new Call(rep_name->getName());
196            }
197            else 
198            {
199                ccExpr = new CharClass(rep_name->getName());
200            }
201
202            if (rep_name->isNegated()) {
203                ccExpr = new Not(new Or(new Or(ccExpr, new CharClass(m_name_map.find("LineFeed")->second)),
204                                        new CharClass(m_name_map.find("internal.nonfinal")->second)));
205            }
206            if (rep_name->getType() == Name::FixedLength)
207            {
208                cg_state.stmtsl.push_back(new Assign(gs_retVal, new MatchStar(new Var(cg_state.newsym), ccExpr)));
209            }
210            else //Name::Unicode and Name::UnicodeCategory
211            {
212                cg_state.stmtsl.push_back(new Assign(gs_retVal,
213                    new And(new MatchStar(new Var(cg_state.newsym), new Or(new CharClass(m_name_map.find("internal.nonfinal")->second),
214                    ccExpr)), new CharClass(m_name_map.find("internal.initial")->second))));
215            }
216
217            cg_state.newsym = gs_retVal;
218        }
219        else if (rep->getUB() == unboundedRep)
220        {
221            if (rep->getLB() == 0)
222            {
223                //std::cout << "While, no lb." << std::endl;
224
225                std::string while_test_gs_retVal = symgen.gensym("while_test");
226                std::string while_accum_gs_retVal = symgen.gensym("while_accum");
227                CodeGenState while_test_state;
228                while_test_state.newsym = while_test_gs_retVal;
229                CodeGenState t1_cg_state = re2pablo_helper(rep->getRE(), while_test_state);
230                cg_state.stmtsl.push_back(new Assign(while_test_gs_retVal, new Var(cg_state.newsym)));
231                cg_state.stmtsl.push_back(new Assign(while_accum_gs_retVal, new Var(cg_state.newsym)));
232                std::list<PabloS*> stmtList;
233                stmtList = t1_cg_state.stmtsl;
234                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)))));
235                stmtList.push_back(new Assign(while_accum_gs_retVal, new Or(new Var(while_accum_gs_retVal), new Var(t1_cg_state.newsym))));
236                cg_state.stmtsl.push_back( new While(new Var(while_test_gs_retVal), stmtList));
237                cg_state.newsym = while_accum_gs_retVal;
238            }
239            else //if (rep->getLB() > 1)
240            {
241                CodeGenState t1_cg_state = re2pablo_helper(rep->getRE(), cg_state);
242                rep->setLB(rep->getLB() - 1);
243                cg_state = re2pablo_helper(rep, t1_cg_state);
244            }
245        }
246        else if (rep->getUB() != unboundedRep)
247        {
248            cg_state = BoundedRep_helper(rep->getRE(), rep->getLB(), rep->getUB(), cg_state);
249        }
250    }
251
252    return cg_state;
253}
254
255
256CodeGenState Pbix_Compiler::Seq_helper(std::list<RE*>* lst, std::list<RE*>::const_iterator it, CodeGenState cg_state)
257{
258    if (it != lst->end())
259    {
260        cg_state = re2pablo_helper(*it, cg_state);
261        cg_state = Seq_helper(lst, ++it, cg_state);
262    }
263
264    return cg_state;
265}
266
267CodeGenState Pbix_Compiler::Alt_helper(std::list<RE*>* lst, std::list<RE*>::const_iterator it, CodeGenState cg_state)
268{
269    CodeGenState t1_cg_state = re2pablo_helper(*it, cg_state);
270    cg_state.stmtsl = t1_cg_state.stmtsl;
271    ++it;
272    if (it != lst->end())
273    {
274        CodeGenState t2_cg_state = Alt_helper(lst, it, cg_state);
275        cg_state.stmtsl = t2_cg_state.stmtsl;
276        std::string gs_retVal = symgen.gensym("alt_marker");
277        cg_state.stmtsl.push_back(new Assign(gs_retVal, new Or(new Var(t1_cg_state.newsym), new Var(t2_cg_state.newsym))));
278        cg_state.newsym = gs_retVal;
279    }
280    else
281    {
282        cg_state.newsym = t1_cg_state.newsym;
283    }
284
285    return cg_state;
286}
287
288CodeGenState Pbix_Compiler::BoundedRep_helper(RE* repeated, int lb, int ub, CodeGenState cg_state) {
289    if ((lb == 0) && (ub == 0))
290    {
291    //Just fall through...do nothing.
292    }
293    else if ((lb == 0) && (ub > 0))
294    {
295         CodeGenState t1_cg_state = re2pablo_helper(repeated, cg_state);
296         CodeGenState t2_cg_state = BoundedRep_helper(repeated, 0, ub-1, t1_cg_state);
297         std::string gs_retVal = symgen.gensym("alt_marker");
298         cg_state.stmtsl = t2_cg_state.stmtsl;
299         cg_state.stmtsl.push_back(new Assign(gs_retVal, new Or(new Var(cg_state.newsym), new Var(t2_cg_state.newsym))));
300         cg_state.newsym = gs_retVal;
301    }
302    else //if ((lb > 0) && (ub > 0))
303    {
304         CodeGenState t1_cg_state = re2pablo_helper(repeated, cg_state);
305         cg_state = BoundedRep_helper(repeated, lb-1, ub-1, t1_cg_state);
306    }
307    return cg_state;
308
309}
310
311
312bool Pbix_Compiler::unicode_re(RE *re)
313{
314    bool found = false;
315
316    return unicode_re_helper(re, found);
317}
318
319bool Pbix_Compiler::unicode_re_helper(RE *re, bool found)
320{
321    if (!found)
322    {
323        if (Name* name = dynamic_cast<Name*>(re))
324        {
325            if ((name->getType() == Name::UnicodeCategory) || (name->getType() == Name::Unicode))
326            {
327                found = true;
328            }
329        }
330        else if (Seq* re_seq = dynamic_cast<Seq*>(re))
331        {
332            std::list<RE*>::iterator it;
333            for (it = re_seq->GetREList()->begin(); it != re_seq->GetREList()->end(); ++it)
334            {
335                found = unicode_re_helper(*it, found);
336                if (found) break;
337            }
338        }
339        else if (Alt* re_alt = dynamic_cast<Alt*>(re))
340        {
341            std::list<RE*>::iterator it;
342            for (it = re_alt->GetREList()->begin(); it != re_alt->GetREList()->end(); ++it)
343            {
344                found = unicode_re_helper(*it, found);
345                if (found) break;
346            }
347        }
348        else if (Rep* rep = dynamic_cast<Rep*>(re))
349        {
350            found = unicode_re_helper(rep->getRE(), found);
351        }
352    }
353
354    return found;
355}
Note: See TracBrowser for help on using the repository browser.