blob: aa244a4674a62fccdb726f7bf62eaa9037a29356 [file] [log] [blame]
Yingdi Yu5e974202014-01-29 16:59:06 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
2/**
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -07003 * Copyright (c) 2013-2014, Regents of the University of California.
4 * All rights reserved.
5 *
6 * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
7 * See AUTHORS.md for complete list of ndn-cxx authors and contributors.
8 *
9 * This file licensed under New BSD License. See COPYING for detailed information about
10 * ndn-cxx library copyright, permissions, and redistribution restrictions.
11 *
12 * @author Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
Yingdi Yu5e974202014-01-29 16:59:06 -080013 */
14
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080015#ifndef NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
16#define NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP
Yingdi Yu5e974202014-01-29 16:59:06 -080017
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080018#include "../../common.hpp"
Yingdi Yu5e974202014-01-29 16:59:06 -080019
20#include "regex-matcher.hpp"
21
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080022namespace ndn {
23
24class RegexBackrefManager;
Yingdi Yu5e974202014-01-29 16:59:06 -080025
26class RegexPatternListMatcher : public RegexMatcher
27{
28public:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070029 RegexPatternListMatcher(const std::string& expr, shared_ptr<RegexBackrefManager> backrefManager);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070030
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070031 virtual
32 ~RegexPatternListMatcher()
33 {
34 };
Yingdi Yu5e974202014-01-29 16:59:06 -080035
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070036protected:
37 virtual void
Yingdi Yu5e974202014-01-29 16:59:06 -080038 compile();
39
40private:
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070041 bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070042 extractPattern(size_t index, size_t* next);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070043
44 int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070045 extractSubPattern(const char left, const char right, size_t index);
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070046
47 int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -070048 extractRepetition(size_t index);
Yingdi Yu5e974202014-01-29 16:59:06 -080049
50private:
51
52};
Yingdi Yu5e974202014-01-29 16:59:06 -080053
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080054} // namespace ndn
55
56#include "regex-repeat-matcher.hpp"
57#include "regex-backref-matcher.hpp"
58
59namespace ndn {
60
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070061inline
62RegexPatternListMatcher::RegexPatternListMatcher(const std::string& expr,
63 shared_ptr<RegexBackrefManager> backrefManager)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070064 : RegexMatcher(expr, EXPR_PATTERN_LIST, backrefManager)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080065{
66 compile();
67}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070068
69inline void
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080070RegexPatternListMatcher::compile()
71{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070072 size_t len = m_expr.size();
73 size_t index = 0;
74 size_t subHead = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070075
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070076 while (index < len) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080077 subHead = index;
78
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070079 if (!extractPattern(subHead, &index))
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070080 throw RegexMatcher::Error("Compile error");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080081 }
82}
83
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070084inline bool
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070085RegexPatternListMatcher::extractPattern(size_t index, size_t* next)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080086{
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070087 size_t start = index;
88 size_t end = index;
89 size_t indicator = index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -070090
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070091 switch (m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -080092 case '(':
93 index++;
94 index = extractSubPattern('(', ')', index);
95 indicator = index;
96 end = extractRepetition(index);
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -070097 if (indicator == end) {
Alexander Afanasyevdfa52c42014-04-24 21:10:11 -070098 shared_ptr<RegexMatcher> matcher =
99 make_shared<RegexBackrefMatcher>(m_expr.substr(start, end - start), m_backrefManager);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800100 m_backrefManager->pushRef(matcher);
Alexander Afanasyevb67090a2014-04-29 22:31:01 -0700101 dynamic_pointer_cast<RegexBackrefMatcher>(matcher)->lateCompile();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800102
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700103 m_matchers.push_back(matcher);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800104 }
105 else
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700106 m_matchers.push_back(make_shared<RegexRepeatMatcher>(m_expr.substr(start, end - start),
107 m_backrefManager, indicator - start));
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800108 break;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700109
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800110 case '<':
111 index++;
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700112 index = extractSubPattern('<', '>', index);
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800113 indicator = index;
114 end = extractRepetition(index);
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;
118
119 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 default:
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700129 throw RegexMatcher::Error("Unexpected syntax");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800130 }
131
132 *next = end;
133
134 return true;
135}
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700136
137inline int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700138RegexPatternListMatcher::extractSubPattern(const char left, const char right, size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800139{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700140 size_t lcount = 1;
141 size_t rcount = 0;
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800142
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700143 while (lcount > rcount) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800144
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700145 if (index >= m_expr.size())
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700146 throw RegexMatcher::Error("Parenthesis mismatch");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800147
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700148 if (left == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800149 lcount++;
150
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700151 if (right == m_expr[index])
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800152 rcount++;
153
154 index++;
155 }
156 return index;
157}
158
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700159inline int
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700160RegexPatternListMatcher::extractRepetition(size_t index)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800161{
Alexander Afanasyev1dd95c52014-03-22 19:11:36 -0700162 size_t exprSize = m_expr.size();
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800163
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700164 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800165 return index;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700166
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700167 if (('+' == m_expr[index] || '?' == m_expr[index] || '*' == m_expr[index])) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800168 return ++index;
169 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700170
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700171 if ('{' == m_expr[index]) {
172 while ('}' != m_expr[index]) {
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800173 index++;
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700174 if (index == exprSize)
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800175 break;
176 }
Alexander Afanasyevfdbfc6d2014-04-14 15:12:11 -0700177 if (index == exprSize)
Alexander Afanasyevb6b21b32014-04-28 22:38:03 -0700178 throw RegexMatcher::Error("Missing right brace bracket");
Alexander Afanasyev36b84cf2014-02-17 19:34:18 -0800179 else
180 return ++index;
181 }
182 else {
183 return index;
184 }
185}
186
187
188} // namespace ndn
189
190#endif // NDN_UTIL_REGEX_REGEX_PATTERN_LIST_MATCHER_HPP