blob: acca0f99c73072b38f92ff640f37950d0d7444ff [file] [log] [blame]
Alexander Afanasyevc169a812014-05-20 20:37:29 -04001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Yingdi Yu5e974202014-01-29 16:59:06 -08002/**
Alexander Afanasyevc169a812014-05-20 20:37:29 -04003 * Copyright (c) 2013-2014 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 Afanasyevb6b21b32014-04-28 22:38:03 -070040 virtual
41 ~RegexPatternListMatcher()
42 {
43 };
Yingdi Yu5e974202014-01-29 16:59:06 -080044
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070045protected:
46 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080047 compile();
48
49private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070050 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070051 extractPattern(size_t index, size_t* next);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070052
53 int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070054 extractSubPattern(const char left, const char right, size_t index);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070055
56 int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070057 extractRepetition(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080058
59private:
60
61};
Yingdi Yu5e974202014-01-29 16:59:06 -080062
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080063} // namespace ndn
64
65#include "regex-repeat-matcher.hpp"
66#include "regex-backref-matcher.hpp"
67
68namespace ndn {
69
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070070inline
71RegexPatternListMatcher::RegexPatternListMatcher(const std::string& expr,
72 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070073 : RegexMatcher(expr, EXPR_PATTERN_LIST, backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080074{
75 compile();
76}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070077
78inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080079RegexPatternListMatcher::compile()
80{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070081 size_t len = m_expr.size();
82 size_t index = 0;
83 size_t subHead = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070084
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070085 while (index < len) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080086 subHead = index;
87
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070088 if (!extractPattern(subHead, &index))
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070089 throw RegexMatcher::Error("Compile error");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080090 }
91}
92
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070093inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070094RegexPatternListMatcher::extractPattern(size_t index, size_t* next)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080095{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070096 size_t start = index;
97 size_t end = index;
98 size_t indicator = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070099
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700100 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800101 case '(':
102 index++;
103 index = extractSubPattern('(', ')', index);
104 indicator = index;
105 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700106 if (indicator == end) {
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -0700107 shared_ptr<RegexMatcher> matcher =
108 make_shared<RegexBackrefMatcher>(m_expr.substr(start, end - start), m_backrefManager);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800109 m_backrefManager->pushRef(matcher);
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700110 dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800111
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700112 m_matchers.push_back(matcher);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800113 }
114 else
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700115 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
116 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800117 break;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700118
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800119 case '<':
120 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700121 index = extractSubPattern('<', '>', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800122 indicator = index;
123 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700124 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
125 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800126 break;
127
128 case '[':
129 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700130 index = extractSubPattern('[', ']', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800131 indicator = index;
132 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700133 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
134 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800135 break;
136
137 default:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700138 throw RegexMatcher::Error("Unexpected syntax");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800139 }
140
141 *next = end;
142
143 return true;
144}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700145
146inline int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700147RegexPatternListMatcher::extractSubPattern(const char left, const char right, size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800148{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700149 size_t lcount = 1;
150 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800151
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700152 while (lcount > rcount) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800153
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700154 if (index >= m_expr.size())
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700155 throw RegexMatcher::Error("Parenthesis mismatch");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800156
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700157 if (left == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800158 lcount++;
159
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700160 if (right == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800161 rcount++;
162
163 index++;
164 }
165 return index;
166}
167
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700168inline int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700169RegexPatternListMatcher::extractRepetition(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800170{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700171 size_t exprSize = m_expr.size();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800172
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700173 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800174 return index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700175
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700176 if (('+' == m_expr[index] || '?' == m_expr[index] || '*' == m_expr[index])) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800177 return ++index;
178 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700179
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700180 if ('{' == m_expr[index]) {
181 while ('}' != m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800182 index++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700183 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800184 break;
185 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700186 if (index == exprSize)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700187 throw RegexMatcher::Error("Missing right brace bracket");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800188 else
189 return ++index;
190 }
191 else {
192 return index;
193 }
194}
195
196
197} // namespace ndn
198
199#endif // NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP