source: icGREP/icgrep-devel/icgrep/re/re_parser_prosite.cpp @ 5218

Last change on this file since 5218 was 5218, checked in by xuedongx, 3 years ago

Add parser for PROSITE protein patterns

File size: 4.3 KB
Line 
1/*
2 *  Copyright (c) 2016 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 <re/re_parser_prosite.h>
8#include <re/re_parser_helper.h>
9#include <re/re_alt.h>
10#include <re/re_seq.h>
11#include <re/re_start.h>
12#include <re/re_end.h>
13#include <re/re_diff.h>
14#include <re/re_rep.h>
15
16namespace re{
17
18    RE * RE_Parser_PROSITE::parse_RE() {
19        return parse_seq();
20    }
21
22    RE * RE_Parser_PROSITE::parse_seq() {
23        std::vector<RE *> seq;
24        for (;;) {
25            RE * re = parse_next_item();
26            if (re == nullptr) {
27                break;
28            }
29            re = extend_item(re);
30            seq.push_back(re);
31        }
32        return makeSeq(seq.begin(), seq.end());
33    }
34
35    RE * RE_Parser_PROSITE::parse_next_item() {
36        RE * re = nullptr;
37        if (mCursor.more()) {       
38            if (*mCursor == '-') {
39                mCursor++;
40            }
41            switch (*mCursor) {
42                case ']': case '}':
43                    ParseFailure("Illegal Input");
44                case '<': { // the N-terminal of the sequence ('<')
45                    mCursor++;
46                    return makeStart();
47                }
48                case '>': { // the C-terminal of the sequence ('>')
49                    mCursor++;
50                    return makeEnd();
51                }
52                case '[': { // Ambiguities are indicated by listing between '[ ]' the acceptable amino acids for a given position.
53                    mCursor++;
54                    return parse_prosite_alt();
55                }
56                case '{': { // Ambiguities are also indicated by listing between '{ }' the amino acids that are not accepted at a given position.
57                    mCursor++;
58                    RE * re_temp = parse_prosite_not();
59                    return makeDiff(makeAny(), re_temp);
60                }
61                case 'x': // the 'any' metacharacter
62                    mCursor++;
63                    return makeAny();
64                case '.': // ends the pattern
65                    break;
66                default:
67                    re = createCC(parse_utf8_codepoint());
68                    return re;
69            }
70        }
71        return nullptr;
72    }
73
74    RE * RE_Parser_PROSITE::parse_prosite_alt() {
75        std::vector<RE *> alt;
76        while (*mCursor != ']') {
77            RE * re = nullptr;
78            if (*mCursor == '>') {
79                re = makeEnd();
80                mCursor++;
81            } else {
82                re = createCC(parse_utf8_codepoint());
83            }
84            alt.push_back(re);
85        }
86        mCursor++;
87        return makeAlt(alt.begin(), alt.end());
88    }
89
90    RE * RE_Parser_PROSITE::parse_prosite_not() {
91        std::vector<RE *> alt;
92        while (*mCursor != '}') {
93            RE * re = createCC(parse_utf8_codepoint());
94            alt.push_back(re);
95        }
96        mCursor++;
97        return makeAlt(alt.begin(), alt.end());
98    }
99   
100    RE * RE_Parser_PROSITE::extend_item(RE * re) {
101         if (LLVM_LIKELY(mCursor.more())) {
102             int lb = 0, ub = 0;
103             if (*mCursor == '(') {
104                std::tie(lb, ub) = parse_range_bound();
105                if (lb > MAX_REPETITION_LOWER_BOUND || ub > MAX_REPETITION_UPPER_BOUND) {
106                    ParseFailure("Bounded repetition exceeds icgrep implementation limit");
107                }
108                if ((ub != Rep::UNBOUNDED_REP) && (lb > ub)) {
109                    ParseFailure("Lower bound cannot exceed upper bound in bounded repetition");
110                }
111                ++mCursor;
112                re = makeRep(re, lb, ub);
113            }
114
115         }
116         return re;
117    }
118
119    std::pair<int, int> RE_Parser_PROSITE::parse_range_bound() {
120        int lower_bound = 0, upper_bound = 0;
121        mCursor++;
122        lower_bound = RE_Parser::parse_int();
123        if (*mCursor == ')') {
124            upper_bound = lower_bound;
125        } else if (*mCursor != ',') {
126            ParseFailure("Bad lower bound!");
127        } else {
128            mCursor++;
129            upper_bound = parse_int();
130            if (*mCursor != ')') {
131                ParseFailure("Bad upper bound!");
132            }
133        }
134        return std::make_pair(lower_bound, upper_bound);
135    }
136
137}
Note: See TracBrowser for help on using the repository browser.