helpers.pl (3757B)
1 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 2 % File: helpers.pl 3 % Description: Misc. utility predicates. 4 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 5 6 % read_file(+Stream, -Codes). 7 % Read a file to a list of character codes. 8 read_file(Stream, Codes):- 9 get_code(Stream, Code), 10 read_file_next(Code, Stream, Codes). 11 12 read_file_next(-1, _, []). 13 14 read_file_next(Code, Stream, [Code|Rest]):- 15 read_file(Stream, Rest). 16 17 18 % replace(+FindCodes, +ReplaceCodes, +Haystack, -Result). 19 % Find instances of FindCodes in Haystack and replace with ReplaceCodes. 20 % All four arguments are lists of character codes. 21 replace(FindCodes, ReplaceCodes, Haystack, Result):- 22 substrings(FindCodes, Substrings, Haystack, []), 23 substrings(ReplaceCodes, Substrings, Result, []). 24 25 substrings(Delimiter, [Substring|Substrings]) --> 26 anything(Substring), 27 Delimiter, 28 substrings(Delimiter, Substrings). 29 30 substrings(_, [Substring]) --> anything(Substring). 31 32 33 % write_codes(+CodesList). 34 % Loop through a list of character codes, convert each one to a 35 % character, and write them to the current output stream one at 36 % a time. This is better than converting the whole list to an atom 37 % with atom_codes/2, which can trigger a segfault if the atom is too long. 38 write_codes(_, []). 39 40 write_codes(Stream, [X|Rest]):- 41 char_code(Char, X), 42 write(Stream, Char), 43 write_codes(Stream, Rest). 44 45 46 % join(?List, +Separator, ?Atom). 47 % Join elements of a list into an atom separated by a separator. 48 % Written specifically as a join predicate, but should work as a split. 49 join([], _, ''). 50 51 join([A], _, A). 52 53 join([First|Rest], Separator, Result):- 54 join(Rest, Separator, End), 55 atom_concat(First, Separator, FirstPlusSeparator), 56 atom_concat(FirstPlusSeparator, End, Result). 57 58 59 % format_date(-RFCDate, +Date). 60 % Parse and format a date according to RFC 822. 61 format_date(RFCDate, Date):- 62 date_stamp(YearCodes, MonthCodes, DayCodes, Date, []), 63 number_codes(Year, YearCodes), 64 number_codes(Month, MonthCodes), 65 number_codes(Day, DayCodes), 66 day_of_week(date(Year, Month, Day), DayOfWeek), 67 day(DayOfWeek, DayOfWeekNameCodes), 68 month(Month, MonthNameCodes, _), 69 rfc_822(YearCodes, MonthNameCodes, DayCodes, DayOfWeekNameCodes, RFCDate, []). 70 71 % TODO: Implement support for other date formats. 72 % Currently we support YYYY-MM-DD. 73 date_stamp(YearCodes, MonthCodes, DayCodes) --> 74 anything(YearCodes), 75 "-", 76 anything(MonthCodes), 77 "-", 78 anything(DayCodes). 79 80 rfc_822(YearCodes, MonthNameCodes, DayCodes, DayOfWeekNameCodes) --> 81 anything(DayOfWeekNameCodes), 82 ", ", 83 anything(DayCodes), 84 " ", 85 anything(MonthNameCodes), 86 " ", 87 anything(YearCodes), 88 " 00:00:00 GMT". 89 90 day_of_week(date(Year, Month, Day), DayOfWeek):- 91 magic_year(Year, Month, MagicYear), 92 month(Month, _, MagicMonth), 93 DayOfWeek is (MagicYear + MagicYear // 4 - MagicYear // 100 + MagicYear // 400 + MagicMonth + Day) mod 7. 94 95 magic_year(Year, Month, MagicYear):- 96 Month < 3, 97 MagicYear is Year - 1. 98 99 magic_year(Year, _, Year). 100 101 % month(?MonthNumber, ?ShortName, -MagicNumber). 102 % Magic numbers, used for calculating the day of the week, 103 % are as defined in Sakamoto's methods: 104 % https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week#Sakamoto's_methods 105 month(1, "Jan", 0). 106 month(2, "Feb", 3). 107 month(3, "Mar", 2). 108 month(4, "Apr", 5). 109 month(5, "May", 0). 110 month(6, "Jun", 3). 111 month(7, "Jul", 5). 112 month(8, "Aug", 1). 113 month(9, "Sep", 4). 114 month(10, "Oct", 6). 115 month(11, "Nov", 2). 116 month(12, "Dec", 4). 117 118 day(0, "Sun"). 119 day(1, "Mon"). 120 day(2, "Tue"). 121 day(3, "Wed"). 122 day(4, "Thu"). 123 day(5, "Fri"). 124 day(6, "Sat"). 125 126 127 anything([]) --> []. 128 129 anything([X|Rest]) --> [X], anything(Rest). 130 131 132 whitespace --> []. 133 134 whitespace --> newline, whitespace. 135 136 whitespace --> tab, whitespace. 137 138 whitespace --> " ", whitespace. 139 140 newline --> "\n". 141 142 tab --> "\t".