| 1 | % (c) 2018-2019 Lehrstuhl fuer Softwaretechnik und Programmiersprachen, | |
| 2 | % Heinrich Heine Universitaet Duesseldorf | |
| 3 | % This software is licenced under EPL 1.0 (http://www.eclipse.org/org/documents/epl-v10.html) | |
| 4 | ||
| 5 | :- module(regexp, [regexp_init/0, | |
| 6 | regexp_match/2, | |
| 7 | is_regexp/1, | |
| 8 | regexp_replace/4, | |
| 9 | regexp_search_first/3, | |
| 10 | regexp_search_first_detailed/4, | |
| 11 | regexp_search_all/3]). | |
| 12 | ||
| 13 | ||
| 14 | /* the interface to a heap global variable stored and maintained in C */ | |
| 15 | ||
| 16 | ||
| 17 | foreign(cpp_regex_match,cpp_regex_match(+string,+string,+integer,[-integer])). | |
| 18 | foreign(cpp_regex_replace,cpp_regex_replace(+string,+string,+string,[-atom])). | |
| 19 | foreign(cpp_regex_search_all_str,cpp_regex_search_all_str(+string,+string,[-term])). | |
| 20 | foreign(cpp_regex_search_first_str,cpp_regex_search_first_str(+string,+string,[-atom])). | |
| 21 | foreign(cpp_regex_search_first,cpp_regex_search_first(+string,+integer,+string,[-term])). | |
| 22 | foreign_resource(regexp, | |
| 23 | [ | |
| 24 | cpp_regex_match, | |
| 25 | cpp_regex_replace, | |
| 26 | cpp_regex_search_first_str, | |
| 27 | cpp_regex_search_first, | |
| 28 | cpp_regex_search_all_str | |
| 29 | ]). | |
| 30 | ||
| 31 | :- use_module(probsrc(error_manager)). | |
| 32 | ||
| 33 | % match an atom agains a regular expression in ECMA syntax also represented as an atom | |
| 34 | regexp_match(String,Pattern) :- | |
| 35 | atom(String), atom(Pattern), | |
| 36 | regexp_init, | |
| 37 | !, | |
| 38 | cpp_regex_match(String,Pattern,1,Res), | |
| 39 | %format('String ~w for Pattern ~w: Result=~w~n',[String,Pattern,Res]), | |
| 40 | (Res=1 -> true | |
| 41 | ; Res>1 | |
| 42 | -> add_error(regexp,'Illegal Regular Expression Pattern (use ECMAScript syntax): ',Pattern), | |
| 43 | fail). | |
| 44 | regexp_match(String,Pattern) :- | |
| 45 | format(user_error,'Illegal call: ',regepx_match(String,Pattern)), | |
| 46 | fail. | |
| 47 | ||
| 48 | % check if an atom is a valid regular expression pattern | |
| 49 | is_regexp(Pattern) :- atom(Pattern), | |
| 50 | regexp_init, | |
| 51 | !, | |
| 52 | cpp_regex_match('',Pattern,0,Res), % TO DO: will still print error messages | |
| 53 | Res<2. % 0 or 1 means pattern was ok | |
| 54 | is_regexp(Pattern) :- | |
| 55 | format(user_error,'Illegal call: ',is_regexp(Pattern)), | |
| 56 | fail. | |
| 57 | ||
| 58 | ||
| 59 | % match an atom agains a regular expression in ECMA syntax also represented as an atom | |
| 60 | regexp_replace(String,Pattern,ReplStr,Result) :- | |
| 61 | atom(String), atom(Pattern), atom(ReplStr), regexp_init, | |
| 62 | !, | |
| 63 | cpp_regex_replace(String,Pattern,ReplStr,Result). | |
| 64 | %,format('Replace ~w for Pattern ~w with ~w: Result=~w~n',[String,Pattern,ReplStr,Result]). | |
| 65 | regexp_replace(String,Pattern,ReplStr,Result) :- | |
| 66 | format(user_error,'Illegal call: ',regexp_replace(String,Pattern,ReplStr,Result)), | |
| 67 | fail. | |
| 68 | ||
| 69 | % search for a first match of a pattern; returns empty string if no match found | |
| 70 | regexp_search_first(String,Pattern,Result) :- | |
| 71 | atom(String), atom(Pattern), regexp_init, | |
| 72 | !, | |
| 73 | cpp_regex_search_first_str(String,Pattern,Result). | |
| 74 | %,format('Search ~w for Pattern ~w: Result=~w~n',[String,Pattern,Result]). | |
| 75 | regexp_search_first(String,Pattern,Result) :- | |
| 76 | format(user_error,'Illegal call: ',regexp_search_first(String,Pattern,Result)), | |
| 77 | fail. | |
| 78 | ||
| 79 | % search for a first match of a pattern; | |
| 80 | % returns either match(Pos,Len,[MatchAtom|SubMatches]) or no-match | |
| 81 | regexp_search_first_detailed(String,FromPosition,Pattern,Result) :- | |
| 82 | atom(String), atom(Pattern), FromPosition>0, | |
| 83 | regexp_init, | |
| 84 | !, | |
| 85 | Offset is FromPosition-1, | |
| 86 | cpp_regex_search_first(String,Offset,Pattern,Result). | |
| 87 | %, format('Search ~w for Pattern ~w: Result=~w~n',[String,Pattern,Result]). | |
| 88 | regexp_search_first_detailed(String,From,Pattern,Result) :- | |
| 89 | format(user_error,'Illegal call: ',regexp_search_first_detailed(String,From,Pattern,Result)), | |
| 90 | fail. | |
| 91 | ||
| 92 | :- use_module(library(lists),[reverse/2]). | |
| 93 | % search for a first match of a pattern; returns empty string if no match found | |
| 94 | regexp_search_all(String,Pattern,Result) :- | |
| 95 | atom(String), atom(Pattern), regexp_init, | |
| 96 | !, | |
| 97 | cpp_regex_search_all_str(String,Pattern,CRes), | |
| 98 | reverse(CRes,Result). | |
| 99 | %,format('Search ~w for Pattern ~w: Result=~w~n',[String,Pattern,Result]). | |
| 100 | regexp_search_all(String,Pattern,Result) :- | |
| 101 | format(user_error,'Illegal call: ',regexp_search_first(String,Pattern,Result)), | |
| 102 | fail. | |
| 103 | ||
| 104 | :- dynamic loaded/0. | |
| 105 | ||
| 106 | regexp_init :- | |
| 107 | (loaded -> true | |
| 108 | ; (assert(loaded), | |
| 109 | %assert_dir, | |
| 110 | %assert(user:library_directory(prob_home('.'))), | |
| 111 | %print(loading_foreign_resource(myheap)),nl, | |
| 112 | load_foreign_resource(library(regexp))) | |
| 113 | ). | |
| 114 | ||
| 115 | assert_dir :- (user:library_directory('.') -> true ; assert(user:library_directory('.'))). | |
| 116 |