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

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

Fix unicode match with Scanthru; negated unicode class fix

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