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

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

Restructuring - not quite ready

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