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

Last change on this file since 5792 was 5792, checked in by cameron, 18 months ago

\N{...} expressions now anchored; name expresions in ranges functional

File size: 6.8 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            size_t rem = mCursor.remaining();
154            ParseFailure("Expecting " + s + " but " + std::string(mCursor.pos(), mCursor.pos() + std::min(rem, s.length())) + " encountered");
155        }
156    }
157   
158    inline char get1() { return *mCursor++;}
159
160   
161    RE_Parser(const std::string & regular_expression);
162
163    RE_Parser(const std::string & regular_expression, ModeFlagSet initialFlags);
164
165    virtual RE * parse_RE();
166
167    virtual RE * parse_alt();
168   
169    virtual RE * parse_seq();
170
171    virtual RE * parse_next_item();
172
173    virtual RE * parse_group();
174   
175    RE * parse_mode_group(bool & closing_paren_parsed);
176
177    RE * parse_capture_body();
178   
179    RE * parse_back_reference();
180   
181    virtual bool isSetEscapeChar(char c);
182
183    virtual RE * extend_item(RE * re);
184
185    RE * parseGraphemeBoundary(RE * re);
186
187    virtual std::pair<int, int> parse_range_bound();
188
189    unsigned parse_int();
190
191    virtual RE * parse_escaped();
192
193    virtual RE * parseEscapedSet();
194
195    codepoint_t parse_literal_codepoint();
196   
197    codepoint_t parse_utf8_codepoint();
198
199    virtual RE * parsePropertyExpression();
200
201    Name * parseNamePatternExpression();
202
203    RE * makeComplement(RE * s);
204    RE * makeWordBoundary();
205    RE * makeWordNonBoundary();
206    RE * makeReBoundary(RE * wordC);
207    RE * makeReNonBoundary(RE * wordC);
208    RE * makeWordBegin();
209    RE * makeWordEnd();
210    Name * makeDigitSet();
211    Name * makeAlphaNumeric();
212    Name * makeWhitespaceSet();
213    Name * makeWordSet();
214   
215    Name * createName(std::string value);
216    Name * createName(std::string prop, std::string value);
217
218    RE * parse_extended_bracket_expression();
219    RE * parse_bracketed_items();
220    RE * range_extend(RE * e1);
221   
222    RE * parse_equivalence_class();
223    RE * parse_collation_element();
224    RE * parse_Posix_class();
225    RE * parse_escaped_char_item();
226   
227    codepoint_t parse_codepoint();
228
229    virtual codepoint_t parse_escaped_codepoint();
230
231    codepoint_t parse_hex_codepoint(int mindigits, int maxdigits);
232
233    codepoint_t parse_octal_codepoint(int mindigits, int maxdigits);
234
235    // CC insertion dependent on case-insensitive flag.
236    Name * createCC(const codepoint_t cp);
237    void insert(CC * cc, const codepoint_t cp);
238    void insert_range(CC * cc, const codepoint_t lo, const codepoint_t hi);
239
240    static std::string canonicalize(const cursor_t begin, const cursor_t end);
241    bool isCharAhead(char c);
242
243protected:
244    bool                        fByteMode;
245    ModeFlagSet                 fModeFlagSet;
246    bool                        fNested;
247    unsigned                    mGroupsOpen;
248    Cursor                      mCursor;
249    unsigned                    mCaptureGroupCount;
250    NameMap                     mNameMap;
251    Memoizer                    mMemoizer;
252    RE_Syntax                   mReSyntax;
253};
254
255}
256
257#endif // RE_PARSER_H
Note: See TracBrowser for help on using the repository browser.