source: icGREP/icgrep-devel/icgrep/re/parsers/parser.h @ 6169

Last change on this file since 6169 was 6169, checked in by cameron, 8 months ago

-K flag for compatibility mode

File size: 7.1 KB
Line 
1/*
2 *  Copyright (c) 2014-8 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, FileGLOB, 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    COMPATIBLE_EQUIVALENCE_MODE = 64
29};
30
31using ModeFlagSet = unsigned;
32
33class RE_Parser {
34public:
35
36    static RE * parse(const std::string &input_string, ModeFlagSet initialFlags, RE_Syntax syntax = RE_Syntax::PCRE, bool ByteMode = false);
37
38protected:
39
40    using NameMap = std::map<std::pair<std::string, std::string>, re::Name *>;
41
42    using cursor_t = std::string::const_iterator;
43
44    using char_t = const std::string::value_type;
45
46    struct Cursor {
47        friend class RE_Parser;
48
49        inline Cursor & operator++() {
50            if (LLVM_UNLIKELY(mCursor == mEnd)) {
51                IncompleteRegularExpression();
52            }
53            ++mCursor;
54            return *this;
55        }
56
57        inline Cursor operator++(int) {
58            if (LLVM_UNLIKELY(mCursor == mEnd)) {
59                IncompleteRegularExpression();
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        Cursor(const std::string & expression) : mCursor(expression.cbegin()), mEnd(expression.cend()), mStart(expression.cbegin()) {}
90        Cursor(const Cursor & cursor) : mCursor(cursor.mCursor), mEnd(cursor.mEnd), mStart(cursor.mStart) {}
91        inline Cursor & operator=(const Cursor & cursor) {
92            mCursor = cursor.mCursor;
93            mEnd = cursor.mEnd;
94            return *this;
95        }
96    private:       
97        LLVM_ATTRIBUTE_NORETURN void IncompleteRegularExpression();
98        LLVM_ATTRIBUTE_NORETURN void ParseFailure(const std::string & errmsg);
99    private:
100        cursor_t    mCursor;
101        cursor_t    mEnd;
102        cursor_t    mStart;
103    };
104
105   
106   
107    inline bool at(char c) {
108        return (mCursor.more()) && (*mCursor == c);
109    }
110   
111    inline bool accept(char c) {
112        if (at(c)) {
113            mCursor++;
114            return true;
115        }
116        return false;
117    }
118   
119    inline void require(char c) {
120        if (!accept(c)) {
121            if (mCursor.noMore()) ParseFailure("Expecting " + std::string(1, c) + " but end of input encountered");
122            ParseFailure("Expecting " + std::string(1, c) + " but " + std::string(1, *mCursor) + " encountered");
123        }
124    }
125   
126    inline bool atany(std::string s) {
127        if (mCursor.noMore()) return false;
128        for (unsigned i = 0; i < s.length(); i++) {
129            if (s[i] == *mCursor) return true;
130        }
131        return false;
132    }
133   
134    inline bool at(std::string s) {
135        Cursor tmp = mCursor;
136        for (unsigned i = 0; i < s.length(); i++) {
137            if (tmp.noMore() || (s[i] != *tmp)) return false;
138            tmp++;
139        }
140        return true;
141    }
142   
143    inline bool accept(std::string s) {
144        Cursor tmp = mCursor;
145        for (unsigned i = 0; i < s.length(); i++) {
146            if (tmp.noMore() || (s[i] != *tmp)) return false;
147            tmp++;
148        }
149        mCursor = tmp;
150        return true;
151    }
152   
153    inline void require(std::string s) {
154        if (!accept(s)) {
155            if (mCursor.noMore()) ParseFailure("Expecting " + s + " but end of input encountered");
156            size_t rem = mCursor.remaining();
157            ParseFailure("Expecting " + s + " but " + std::string(mCursor.pos(), mCursor.pos() + std::min(rem, s.length())) + " encountered");
158        }
159    }
160   
161    inline char get1() { return *mCursor++;}
162
163   
164    RE_Parser(const std::string & regular_expression);
165
166    RE_Parser(const std::string & regular_expression, ModeFlagSet initialFlags);
167
168    virtual RE * parse_RE();
169
170    virtual RE * parse_alt();
171   
172    virtual RE * parse_seq();
173
174    virtual RE * parse_next_item();
175
176    virtual RE * parse_group();
177   
178    RE * parse_mode_group(bool & closing_paren_parsed);
179
180    RE * parse_capture_body();
181   
182    RE * parse_back_reference();
183   
184    virtual bool isSetEscapeChar(char c);
185
186    virtual RE * extend_item(RE * re);
187
188    RE * parseGraphemeBoundary(RE * re);
189
190    virtual std::pair<int, int> parse_range_bound();
191
192    unsigned parse_int();
193
194    virtual RE * parse_escaped();
195
196    virtual RE * parseEscapedSet();
197
198    codepoint_t parse_literal_codepoint();
199   
200    codepoint_t parse_utf8_codepoint();
201
202    virtual RE * parsePropertyExpression();
203
204    Name * parseNamePatternExpression();
205
206    RE * makeComplement(RE * s);
207    RE * makeZerowidthComplement(RE * s);
208
209    RE * makeWordBoundary();
210    RE * makeWordNonBoundary();
211    RE * makeReBoundary(RE * wordC);
212    RE * makeReNonBoundary(RE * wordC);
213    RE * makeWordBegin();
214    RE * makeWordEnd();
215    Name * makeDigitSet();
216    Name * makeAlphaNumeric();
217    Name * makeWhitespaceSet();
218    Name * makeWordSet();
219   
220    Name * createName(std::string value);
221    Name * createName(std::string prop, std::string value);
222
223    RE * parse_extended_bracket_expression();
224    RE * parse_bracketed_items();
225    RE * range_extend(RE * e1);
226   
227    RE * parse_equivalence_class();
228    RE * parse_collation_element();
229    RE * parse_Posix_class();
230    RE * parse_escaped_char_item();
231   
232    RE * makeAtomicGroup(RE * r);
233    RE * makeBranchResetGroup(RE * r);
234
235    codepoint_t parse_codepoint();
236
237    virtual codepoint_t parse_escaped_codepoint();
238
239    codepoint_t parse_hex_codepoint(int mindigits, int maxdigits);
240
241    codepoint_t parse_octal_codepoint(int mindigits, int maxdigits);
242
243    CC * createCC(const codepoint_t cp);
244
245    static std::string canonicalize(const cursor_t begin, const cursor_t end);
246
247    LLVM_ATTRIBUTE_NORETURN void InvalidUTF8Encoding();
248
249    LLVM_ATTRIBUTE_NORETURN void ParseFailure(const std::string & errmsg) {
250        mCursor.ParseFailure(errmsg);
251    }
252public:
253    virtual ~RE_Parser() {}
254
255protected:
256    bool                        fByteMode;
257    ModeFlagSet                 fModeFlagSet;
258    bool                        fNested;
259    unsigned                    mGroupsOpen;
260    Cursor                      mCursor;
261    unsigned                    mCaptureGroupCount;
262    RE_Syntax                   mReSyntax;
263    NameMap                     mNameMap;
264    Memoizer                    mMemoizer;
265};
266
267}
268
269#endif // RE_PARSER_H
Note: See TracBrowser for help on using the repository browser.