source: icGREP/icgrep-devel/icgrep/re/re_parser_bre.cpp @ 5787

Last change on this file since 5787 was 5787, checked in by cameron, 11 months ago

RE parser restructuring; parsing symbolic ranges, collation and equivalence exprs

File size: 3.2 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_bre.h>
8#include <re/re_alt.h>
9#include <re/re_any.h>
10#include <re/re_seq.h>
11#include <re/re_start.h>
12#include <re/re_end.h>
13#include <re/re_assertion.h>
14#include <re/re_rep.h>
15
16
17namespace re {
18
19
20RE * RE_Parser_BRE::parse_alt() {
21    std::vector<RE *> alt;
22    do {
23        alt.push_back(parse_seq());
24    }
25    while (accept("\\|"));
26    return makeAlt(alt.begin(), alt.end());
27}
28
29RE * RE_Parser_BRE::parse_seq() {
30    std::vector<RE *> seq;
31    if (!mCursor.more() || at("\\|") || ((mGroupsOpen > 0) && at("\\)"))) return makeSeq();
32    for (;;) {
33        RE * re = parse_next_item();
34        if (re == nullptr) {
35            break;
36        }
37        re = extend_item(re);
38        seq.push_back(re);
39    }
40    return makeSeq(seq.begin(), seq.end());
41}
42
43
44RE * RE_Parser_BRE::parse_next_item() {
45    if (mCursor.noMore() || at('*') || at("\\?") || at("\\{") || at("\\|")) return nullptr;
46    else if ((mGroupsOpen > 0) && at("\\)")) return nullptr;
47    else if (accept('^')) return makeStart();
48    else if (accept('$')) return makeEnd();
49    else if (accept('.')) return makeAny();
50    else if (accept("\\(")) return parse_group();
51    else if (accept('[')) return parse_bracket_expr();
52    else if (accept('\\')) return parse_escaped();
53    else return createCC(parse_literal_codepoint());
54}
55
56// A parenthesized group.  Input precondition: the opening ( has been consumed
57RE * RE_Parser_BRE::parse_group() {
58    // Capturing paren group.
59    mGroupsOpen++;
60    RE * captured = parse_alt();
61    mCaptureGroupCount++;
62    std::string captureName = "\\" + std::to_string(mCaptureGroupCount);
63    Name * const capture  = mMemoizer.memoize(makeCapture(captureName, captured));
64    auto key = std::make_pair("", captureName);
65    mNameMap.insert(std::make_pair(std::move(key), capture));
66    if (!accept("\\)")) ParseFailure("Closing parenthesis required.");
67    mGroupsOpen--;
68    return capture;
69}
70
71// Extend a RE item with one or more quantifiers
72RE * RE_Parser_BRE::extend_item(RE * re) {
73    int lb, ub;
74    if (accept('*')) {lb = 0; ub = Rep::UNBOUNDED_REP;}
75    else if (accept("\\?")) {lb = 0; ub = 1;}
76    else if (accept("\\+")) {lb = 1; ub = Rep::UNBOUNDED_REP;}
77    else if (accept("\\{")) std::tie(lb, ub) = parse_range_bound();
78    else {
79        // No quantifier found.
80        return re;
81    }
82    re = makeRep(re, lb, ub);
83    // The quantified expression may be extended with a further quantifier, e,g., [a-z]\{6,7\}\{2,3\}
84    return extend_item(re);
85}
86
87std::pair<int, int> RE_Parser_BRE::parse_range_bound() {
88    int lb, ub;
89    if (accept(',')) {
90        lb = 0;
91        ub = parse_int();
92    } else {
93        lb = parse_int();
94        if (accept("\\}")) return std::make_pair(lb, lb);
95        if (!accept(',')) ParseFailure("Expecting , or }");
96        if (accept("\\}")) return std::make_pair(lb, Rep::UNBOUNDED_REP);
97        ub = parse_int();
98        if (ub < lb) ParseFailure("Upper bound less than lower bound");
99    }
100    if (accept("\\}")) return std::make_pair(lb, ub);
101    else ParseFailure("Expecting \\}");
102}
103
104}
105
Note: See TracBrowser for help on using the repository browser.