source: icGREP/icgrep-devel/icgrep/re/re_parser.h @ 5789

Last change on this file since 5789 was 5789, checked in by cameron, 15 months ago

Further parser bug fixes and restructuring

File size: 6.7 KB
Line 
1/*
2 *  Copyright (c) 2014-6 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#ifndef RE_PARSER_H
8#define RE_PARSER_H
9
10#include <map>
11#include <re/re_memoizer.hpp>
12#include "re/re_cc.h"
13
14namespace re { class Name; }
15
16namespace re {
17
18enum RE_Syntax {FixedStrings, BRE, ERE, PCRE, PROSITE};
19
20enum ModeFlagType : unsigned {
21    DEFAULT_MODE = 0,
22    CASE_INSENSITIVE_MODE_FLAG = 1,
23    MULTILINE_MODE_FLAG = 2,
24    DOTALL_MODE_FLAG = 4,         // not currently implemented
25    IGNORE_SPACE_MODE_FLAG = 8,
26    UNIX_LINES_MODE_FLAG = 16,
27    GRAPHEME_CLUSTER_MODE = 32
28};
29
30using ModeFlagSet = unsigned;
31
32class RE_Parser {
33public:
34
35    static LLVM_ATTRIBUTE_NORETURN void ParseFailure(std::string errmsg);
36
37    static RE * parse(const std::string &input_string, ModeFlagSet initialFlags, RE_Syntax syntax = RE_Syntax::PCRE, bool ByteMode = false);
38
39protected:
40
41    using NameMap = std::map<std::pair<std::string, std::string>, re::Name *>;
42
43    using cursor_t = std::string::const_iterator;
44
45    using char_t = const std::string::value_type;
46
47    struct Cursor {
48
49        inline Cursor & operator++() {
50            if (LLVM_UNLIKELY(mCursor == mEnd)) {
51                ParseFailure("Incomplete regular expression!");
52            }
53            ++mCursor;
54            return *this;
55        }
56
57        inline Cursor operator++(int) {
58            if (LLVM_UNLIKELY(mCursor == mEnd)) {
59                ParseFailure("Incomplete regular expression!");
60            }
61            Cursor tmp(*this);
62            ++mCursor;
63            return tmp;
64        }
65
66        inline const char_t operator*() const {
67            if (LLVM_UNLIKELY(mCursor == mEnd)) {
68                return 0;
69            }
70            return *mCursor;
71        }
72
73        inline bool noMore() const {
74            return mCursor == mEnd;
75        }
76
77        inline bool more() const {
78            return mCursor != mEnd;
79        }
80
81        inline cursor_t::difference_type remaining() const {
82            return mEnd - mCursor;
83        }
84
85        inline cursor_t pos() const {
86            return mCursor;
87        }
88       
89       
90        Cursor(const std::string & expression) : mCursor(expression.cbegin()), mEnd(expression.cend()) {}
91        Cursor(const Cursor & cursor) : mCursor(cursor.mCursor), mEnd(cursor.mEnd) {}
92        inline Cursor & operator=(const Cursor & cursor) {
93            mCursor = cursor.mCursor;
94            mEnd = cursor.mEnd;
95            return *this;
96        }
97    private:
98        cursor_t    mCursor;
99        cursor_t    mEnd;
100    };
101
102   
103   
104    inline bool at(char c) {
105        return (mCursor.more()) && (*mCursor == c);
106    }
107   
108    inline bool accept(char c) {
109        if (at(c)) {
110            mCursor++;
111            return true;
112        }
113        return false;
114    }
115   
116    inline void require(char c) {
117        if (!accept(c)) {
118            if (mCursor.noMore()) ParseFailure("Expecting " + std::string(1, c) + " but end of input encountered");
119            ParseFailure("Expecting " + std::string(1, c) + " but " + std::string(1, *mCursor) + " encountered");
120        }
121    }
122   
123    inline bool atany(std::string s) {
124        if (mCursor.noMore()) return false;
125        for (unsigned i = 0; i < s.length(); i++) {
126            if (s[i] == *mCursor) return true;
127        }
128        return false;
129    }
130   
131    inline bool at(std::string s) {
132        Cursor tmp = mCursor;
133        for (unsigned i = 0; i < s.length(); i++) {
134            if (tmp.noMore() || (s[i] != *tmp)) return false;
135            tmp++;
136        }
137        return true;
138    }
139   
140    inline bool accept(std::string s) {
141        Cursor tmp = mCursor;
142        for (unsigned i = 0; i < s.length(); i++) {
143            if (tmp.noMore() || (s[i] != *tmp)) return false;
144            tmp++;
145        }
146        mCursor = tmp;
147        return true;
148    }
149   
150    inline void require(std::string s) {
151        if (!accept(s)) {
152            if (mCursor.noMore()) ParseFailure("Expecting " + s + " but end of input encountered");
153            unsigned long rem = mCursor.remaining();
154            ParseFailure("Expecting " + s + " but " + std::string(mCursor.pos(), mCursor.pos() + std::min(rem, s.length())) + " encountered");
155        }
156    }
157   
158    RE_Parser(const std::string & regular_expression);
159
160    RE_Parser(const std::string & regular_expression, ModeFlagSet initialFlags);
161
162    virtual RE * parse_RE();
163
164    virtual RE * parse_alt();
165   
166    virtual RE * parse_seq();
167
168    virtual RE * parse_next_item();
169
170    virtual RE * parse_group();
171   
172    RE * parse_mode_group(bool & closing_paren_parsed);
173
174    RE * parse_capture_body();
175   
176    RE * parse_back_reference();
177   
178    virtual bool isSetEscapeChar(char c);
179
180    virtual RE * extend_item(RE * re);
181
182    RE * parseGraphemeBoundary(RE * re);
183
184    virtual std::pair<int, int> parse_range_bound();
185
186    unsigned parse_int();
187
188    virtual RE * parse_escaped();
189
190    virtual RE * parseEscapedSet();
191
192    codepoint_t parse_literal_codepoint();
193   
194    codepoint_t parse_utf8_codepoint();
195
196    virtual RE * parsePropertyExpression();
197
198    Name * parseNamePatternExpression();
199
200    RE * makeComplement(RE * s);
201    RE * makeWordBoundary();
202    RE * makeWordNonBoundary();
203    RE * makeReBoundary(RE * wordC);
204    RE * makeReNonBoundary(RE * wordC);
205    RE * makeWordBegin();
206    RE * makeWordEnd();
207    Name * makeDigitSet();
208    Name * makeAlphaNumeric();
209    Name * makeWhitespaceSet();
210    Name * makeWordSet();
211   
212    Name * createName(std::string value);
213    Name * createName(std::string prop, std::string value);
214
215    RE * parse_extended_bracket_expression();
216    RE * parse_bracketed_items();
217    RE * range_extend(RE * e1);
218   
219    RE * parse_equivalence_class();
220    RE * parse_collation_element();
221    RE * parse_Posix_class();
222    RE * parse_escaped_char_item();
223   
224    codepoint_t parse_codepoint();
225
226    virtual codepoint_t parse_escaped_codepoint();
227
228    codepoint_t parse_hex_codepoint(int mindigits, int maxdigits);
229
230    codepoint_t parse_octal_codepoint(int mindigits, int maxdigits);
231
232    // CC insertion dependent on case-insensitive flag.
233    Name * createCC(const codepoint_t cp);
234    void insert(CC * cc, const codepoint_t cp);
235    void insert_range(CC * cc, const codepoint_t lo, const codepoint_t hi);
236
237    static std::string canonicalize(const cursor_t begin, const cursor_t end);
238    bool isCharAhead(char c);
239
240protected:
241    bool                        fByteMode;
242    ModeFlagSet                 fModeFlagSet;
243    bool                        fNested;
244    unsigned                    mGroupsOpen;
245    Cursor                      mCursor;
246    unsigned                    mCaptureGroupCount;
247    NameMap                     mNameMap;
248    Memoizer                    mMemoizer;
249    RE_Syntax                   mReSyntax;
250};
251
252}
253
254#endif // RE_PARSER_H
Note: See TracBrowser for help on using the repository browser.