blob: ccac4b86becb549acf5971ac84b067dfe4078f82 [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento88a0d812017-08-19 21:31:42 -04002/*
3 * Copyright (c) 2013-2017 Regents of the University of California.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07004 *
5 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07006 *
Alexander Afanasyevc169a812014-05-20 20:37:29 -04007 * ndn-cxx library is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later version.
10 *
11 * ndn-cxx library is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
14 *
15 * You should have received copies of the GNU General Public License and GNU Lesser
16 * General Public License along with ndn-cxx, e.g., in COPYING.md file. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070020 *
21 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080022 */
23
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080024#ifndef NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
25#define NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080026
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080027#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080028
29#include "regex-matcher.hpp"
30
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080031namespace ndn {
32
33class RegexBackrefManager;
Yingdi Yu5e974202014-01-29 16:59:06 -080034
35class RegexPatternListMatcher : public RegexMatcher
36{
37public:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070038 RegexPatternListMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070039
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070040protected:
Davide Pesavento88a0d812017-08-19 21:31:42 -040041 void
42 compile() override;
Yingdi Yu5e974202014-01-29 16:59:06 -080043
44private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070045 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070046 extractPattern(size_t index, size_t* next);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070047
48 int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070049 extractSubPattern(const char left, const char right, size_t index);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070050
51 int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070052 extractRepetition(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080053};
Yingdi Yu5e974202014-01-29 16:59:06 -080054
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080055} // namespace ndn
56
57#include "regex-repeat-matcher.hpp"
58#include "regex-backref-matcher.hpp"
59
60namespace ndn {
61
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070062inline
63RegexPatternListMatcher::RegexPatternListMatcher(const std::string& expr,
64 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070065 : RegexMatcher(expr, EXPR_PATTERN_LIST, backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080066{
67 compile();
68}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070069
70inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080071RegexPatternListMatcher::compile()
72{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070073 size_t len = m_expr.size();
74 size_t index = 0;
75 size_t subHead = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070076
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070077 while (index < len) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080078 subHead = index;
79
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070080 if (!extractPattern(subHead, &index))
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -070081 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Compile error"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080082 }
83}
84
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070085inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070086RegexPatternListMatcher::extractPattern(size_t index, size_t* next)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080087{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070088 size_t start = index;
89 size_t end = index;
90 size_t indicator = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070091
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070092 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080093 case '(':
94 index++;
95 index = extractSubPattern('(', ')', index);
96 indicator = index;
97 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070098 if (indicator == end) {
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070099 shared_ptr<RegexMatcher> matcher =
100 make_shared<RegexBackrefMatcher>(m_expr.substr(start, end - start), m_backrefManager);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 m_backrefManager->pushRef(matcher);
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700102 dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800103
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700104 m_matchers.push_back(matcher);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800105 }
106 else
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700107 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
108 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 break;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700110
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800111 case '<':
112 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700113 index = extractSubPattern('<', '>', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800114 indicator = index;
115 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700116 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
117 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800118 break;
119
120 case '[':
121 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700122 index = extractSubPattern('[', ']', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800123 indicator = index;
124 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700125 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
126 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800127 break;
128
129 default:
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700130 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Unexpected syntax"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131 }
132
133 *next = end;
134
135 return true;
136}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700137
138inline int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700139RegexPatternListMatcher::extractSubPattern(const char left, const char right, size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800140{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700141 size_t lcount = 1;
142 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800143
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700144 while (lcount > rcount) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800145
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700146 if (index >= m_expr.size())
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700147 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Parenthesis mismatch"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800148
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700149 if (left == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800150 lcount++;
151
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700152 if (right == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800153 rcount++;
154
155 index++;
156 }
157 return index;
158}
159
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700160inline int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700161RegexPatternListMatcher::extractRepetition(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800162{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700163 size_t exprSize = m_expr.size();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800164
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700165 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800166 return index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700167
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700168 if (('+' == m_expr[index] || '?' == m_expr[index] || '*' == m_expr[index])) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800169 return ++index;
170 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700171
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700172 if ('{' == m_expr[index]) {
173 while ('}' != m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800174 index++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700175 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800176 break;
177 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700178 if (index == exprSize)
Spyridon Mastorakis0d2ed2e2015-07-27 19:09:12 -0700179 BOOST_THROW_EXCEPTION(RegexMatcher::Error("Missing right brace bracket"));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800180 else
181 return ++index;
182 }
183 else {
184 return index;
185 }
186}
187
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800188} // namespace ndn
189
190#endif // NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP