mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-18 10:53:40 +00:00
samples/Mmakefile:
Add the beer program to list of targets.
samples/*.m:
Convert (C->T;E) to (if C then T else E).
Delete trailing whitespace.
Use predmode syntax instead of separate pred and mode
declarations.
samples/interpreter.m:
Fix up one predicate that had some clauses that used
DCGs and others that used state variables.
Don't use the name 'IO' for something that isn't the I/O state.
samples/diff/*.m:
samples/c_interface/c_calls_mercury/mercury_main.m:
samples/c_interface/short_example.m:
Delete trailing whitespace.
179 lines
5.3 KiB
Mathematica
179 lines
5.3 KiB
Mathematica
%-----------------------------------------------------------------------------%
|
|
% vim: ft=mercury ts=4 sw=4 et
|
|
%-----------------------------------------------------------------------------%
|
|
%
|
|
% file: ultra_sub.m
|
|
% author: conway.
|
|
%
|
|
% This source file is hereby placed in the public domain. -conway (the author).
|
|
%
|
|
% 'ultra_sub' is an extended version of zs' 'sub' command. The idea is that
|
|
% it takes a pattern, a template and some strings, and matches the strings
|
|
% against the pattern, binding some variables in the process. Then it
|
|
% substitutes the variables in the template for the bindings from the pattern.
|
|
%
|
|
% usage: ultra_sub <pattern> <template> [strings...]
|
|
%
|
|
% Variables in the pattern and template are represented by capital letters
|
|
% (unfortunately limiting the number of variables to 26 ). Real capital letters
|
|
% should be preceded by a \.
|
|
% Variables in the template that do not occur in the pattern are treated as
|
|
% real capital letters.
|
|
%
|
|
% eg
|
|
% $ ultra_sub 1X2Y3Z 7Z8Y9X 1a2b3c 1foo2bar3baz
|
|
% 7c8b9a
|
|
% 7baz8bar9foo
|
|
%
|
|
% Strings that do not match the pattern are ignored.
|
|
%
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- module ultra_sub.
|
|
:- interface.
|
|
|
|
:- import_module io.
|
|
|
|
:- pred main(io::di, io::uo) is det.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- implementation.
|
|
|
|
|
|
:- import_module char.
|
|
:- import_module list.
|
|
:- import_module map.
|
|
:- import_module string.
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
main(!IO) :-
|
|
% I really should add some options for switching whether
|
|
% capitals or backslashed things are variables.
|
|
io.command_line_arguments(Args, !IO),
|
|
( if
|
|
Args = [Pattern0, Template0 | Rest]
|
|
then
|
|
string.to_char_list(Pattern0, Pattern),
|
|
string.to_char_list(Template0, Template),
|
|
process_args(Rest, Pattern, Template, !IO)
|
|
else
|
|
io.write_string(
|
|
"usage: ultra_sub template pattern [strings]\n", !IO)
|
|
).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred process_args(list(string)::in, list(char)::in, list(char)::in,
|
|
io::di, io::uo) is det.
|
|
|
|
process_args([], _Pattern, _Template, !IO).
|
|
process_args([Str | Strs], Pattern, Template, !IO) :-
|
|
( if
|
|
string.to_char_list(Str, Chars),
|
|
map.init(Match0),
|
|
match(Pattern, Chars, Match0, Match)
|
|
then
|
|
% If the string matches, then apply the substitution.
|
|
sub(Template, Match, ResultChars),
|
|
string.from_char_list(ResultChars, Result),
|
|
io.write_string(Result, !IO),
|
|
io.write_string("\n", !IO)
|
|
else
|
|
true
|
|
),
|
|
process_args(Strs, Pattern, Template, !IO).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred match(list(char)::in, list(char)::in, map(char, list(char))::in,
|
|
map(char, list(char))::out) is semidet.
|
|
|
|
match([], [], Match, Match).
|
|
match([T | Ts], Chars, !Match) :-
|
|
( if
|
|
char.is_upper(T)
|
|
then
|
|
% Match against a variable.
|
|
match_2(T, Chars, [], Ts, !Match)
|
|
else if
|
|
T = ('\\') % don't you love ISO compliant syntax :-(
|
|
then
|
|
Ts = [T1 | Ts1],
|
|
Chars = [T1 | Chars1],
|
|
match(Ts1, Chars1, !Match)
|
|
else
|
|
Chars = [T | Chars1],
|
|
match(Ts, Chars1, !Match)
|
|
).
|
|
|
|
:- pred match_2(char::in, list(char)::in, list(char)::in, list(char)::in,
|
|
map(char, list(char))::in, map(char, list(char))::out) is semidet.
|
|
|
|
match_2(X, Chars, Tail, Ts, !Match) :-
|
|
( if
|
|
% Have we bound X? Does it match an earlier binding?
|
|
map.search(!.Match, X, Chars)
|
|
then
|
|
true
|
|
else
|
|
map.set(X, Chars, !Match)
|
|
),
|
|
( if
|
|
% Try and match the remainder of the pattern.
|
|
match(Ts, Tail, !Match)
|
|
then
|
|
true
|
|
else
|
|
% If the match failed, then try binding less of the string to X.
|
|
remove_last(Chars, Chars1, C),
|
|
match_2(X, Chars1, [C | Tail], Ts, !Match)
|
|
).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred remove_last(list(char)::in, list(char)::out, char::out) is semidet.
|
|
|
|
remove_last([X | Xs], Ys, Z) :-
|
|
remove_last_2(X, Xs, Ys, Z).
|
|
|
|
:- pred remove_last_2(char::in, list(char)::in, list(char)::out, char::out)
|
|
is det.
|
|
|
|
remove_last_2(X, [], [], X).
|
|
remove_last_2(X, [Y | Ys], [X | Zs], W) :-
|
|
remove_last_2(Y, Ys, Zs, W).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
|
|
:- pred sub(list(char)::in, map(char, list(char))::in, list(char)::out) is det.
|
|
|
|
sub([], _Match, []).
|
|
sub([C | Cs], Match, Result) :-
|
|
( if
|
|
char.is_upper(C),
|
|
map.search(Match, C, Chars)
|
|
then
|
|
sub(Cs, Match, Result0),
|
|
list.append(Chars, Result0, Result)
|
|
else if
|
|
C = ('\\')
|
|
then
|
|
( if Cs = [C1 | Cs1] then
|
|
sub(Cs1, Match, Result0),
|
|
Result = [C1 | Result0]
|
|
else
|
|
sub(Cs, Match, Result0),
|
|
Result = Result0
|
|
)
|
|
else
|
|
sub(Cs, Match, Result0),
|
|
Result = [C | Result0]
|
|
).
|
|
|
|
%------------------------------------------------------------------------------%
|
|
:- end_module ultra_sub.
|
|
%------------------------------------------------------------------------------%
|