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

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

Introduce USE_IF_FOR_NONFINAL for experimental option.

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