2 /* important: don't move boost.xpressive include
3 instruction to helper.hpp, otherwise compilation
4 speed goes down the drain */
6 #include <boost/xpressive/xpressive.hpp>
9 #define SETUP_REX(vm, selfname) \
10 RexObj* selfname = NULL; \
11 if(VX_FAILED(vm->GetInstanceUp(1, (VXUserPointer *)&selfname,0))) \
13 vm->ThrowError("regex: GetInstanceUp failed!"); \
18 boost::xpressive::sregex rex
;
21 VXInteger
rexhelp_compile(VXState
* v
, RexObj
* self
, const std::string
& pattern
)
25 self
->rex
= boost::xpressive::sregex::compile(pattern
);
27 catch(boost::xpressive::regex_error
& err
)
29 return v
->ThrowError(err
.what());
34 template<typename Type
>
35 VXArrayObj
* rexhelp_array_from_match(VXState
* v
, Type
& what
)
39 VXArrayObj
* arr
= v
->NewArray();
40 for(i
=0; i
<what
.size(); i
++)
42 std::string
submatch(what
[i
].first
, what
[i
].second
);
43 if(submatch
.length() > 0)
45 arr
->Append(v
->NewString(submatch
.c_str(), submatch
.length()));
51 VXArrayObj
* rexhelp_findall(VXState
* v
, RexObj
* self
, const std::string
& subject
)
53 VXArrayObj
* arr
= v
->NewArray();
54 std::string::const_iterator begin
= subject
.begin();
55 std::string::const_iterator end
= subject
.end();
56 boost::xpressive::match_results
<std::string::const_iterator
> what
;
57 while(boost::xpressive::regex_search(begin
, end
, what
, self
->rex
))
62 VXTableObj
* tb
= v
->NewTable();
64 /* the primary matched string */
65 tb
->NewSlot(v
->NewString("string"), v
->NewString(str
.c_str(), str
.length()));
68 /* matched substrings (eg, from groups) */
69 tb
->NewSlot(v
->NewString("submatches"), rexhelp_array_from_match(v
, what
));
72 /* where the matched string starts */
73 tb
->NewSlot(v
->NewString("position"), VXInteger(what
.position()));
75 /* absolute length of the matched string */
76 tb
->NewSlot(v
->NewString("length"), VXInteger(what
.length()));
79 begin
= what
[0].second
;
85 VXInteger
rexfunc_replace(VXState
* v
)
92 RexObj
* self
= new RexObj
;
93 v
->GetString(2, &sub
);
94 v
->GetString(3, &pat
);
95 v
->GetString(4, &rep
);
96 if((status
= rexhelp_compile(v
, self
, pat
)) != VX_OK
)
105 result
= boost::xpressive::regex_replace(
109 boost::xpressive::regex_constants::format_all
);
110 v
->Push(v
->NewString(result
.c_str(), result
.length()));
114 catch(boost::xpressive::regex_error
& err
)
117 return v
->ThrowError(err
.what());
124 VXInteger
rexfunc_match(VXState
* v
)
129 RexObj
* self
= new RexObj
;
130 v
->GetString(2, &sub
);
131 v
->GetString(3, &pat
);
132 if((status
= rexhelp_compile(v
, self
, pat
)) != VX_OK
)
139 boost::xpressive::match_results
<std::string::const_iterator
> what
;
140 if(boost::xpressive::regex_match(sub
, what
, self
->rex
))
142 v
->Push(rexhelp_array_from_match(v
, what
));
151 VXInteger
rexfunc_search(VXState
* v
)
156 RexObj
* self
= new RexObj
;
157 v
->GetString(2, &sub
);
158 v
->GetString(3, &pat
);
159 if((status
= rexhelp_compile(v
, self
, pat
)) != VX_OK
)
166 boost::xpressive::match_results
<std::string::const_iterator
> what
;
167 if(boost::xpressive::regex_search(sub
, what
, self
->rex
))
169 v
->Push(rexhelp_array_from_match(v
, what
));
178 static VXInteger
rexclass_typeof(VXState
* v
)
180 v
->Push(v
->NewString("regexp"));
184 static VXInteger
rexclass_release(VXUserPointer p
, VXInteger size
)
187 RexObj
* rex
= (RexObj
*)p
;
192 VXInteger
rexclass_match(VXState
* v
)
196 boost::xpressive::match_results
<std::string::const_iterator
> what
;
197 v
->GetString(2, &subject
);
198 if(boost::xpressive::regex_match(subject
, what
, self
->rex
))
200 v
->Push(rexhelp_array_from_match(v
, what
));
206 VXInteger
rexclass_group(VXState
* v
)
210 std::string groupname
;
211 v
->GetString(2, &subject
);
212 v
->GetString(3, &groupname
);
213 boost::xpressive::smatch what
;
214 if(regex_search(subject
, what
, self
->rex
))
218 std::string matched
= what
[groupname
];
219 v
->Push(v
->NewString(matched
.c_str(), matched
.length()));
221 catch(boost::xpressive::regex_error
& err
)
223 return v
->ThrowError(err
.what());
230 VXInteger
rexclass_findall(VXState
* v
)
234 v
->GetString(2, &opt
);
235 v
->Push(rexhelp_findall(v
, self
, opt
));
239 static VXInteger
rexclass_constructor(VXState
* v
)
241 RexObj
* self
= new RexObj
;
244 v
->GetString(2, &pat
);
245 if((status
= rexhelp_compile(v
, self
, pat
)) != VX_OK
)
249 v
->SetInstanceUp(1, (VXUserPointer
*)&self
);
250 v
->SetReleaseHook(1, rexclass_release
);
254 VXRegFunction rexclass_funcs
[] =
256 {"constructor", rexclass_constructor
, 2, ".s"},
257 {"findall", rexclass_findall
, 2, ".s"},
258 {"match", rexclass_match
, 2, ".s"},
259 {"group", rexclass_group
, 3, ".ss"},
260 {"__typeof__", rexclass_typeof
, 1, "x"},
265 static VXRegFunction regexlib_funcs
[]=
267 {"match", rexfunc_match
, 3, ".ss"},
268 {"search", rexfunc_search
, 3, ".ss"},
269 {"replace", rexfunc_replace
, 4, ".sss"},
274 VXInteger
voxstd_register_regexlib(VXState
* v
)
276 VXTableObj
* tb
= v
->NewTable();
277 tb
->NewSlot(v
->NewString("compile"), v
->RegClass(rexclass_funcs
));
278 v
->RegisterLib("regexp", regexlib_funcs
, true, tb
);