Files
mercury/extras/show_ops/show_ops.m
Julien Fischer 53e2c0f154 Fix compilation of extras/show_ops.
extras/show_ops/show_ops.m:
     Import mercury_term_parser; this is now required.
2022-03-06 02:44:30 +11:00

151 lines
4.4 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%-----------------------------------------------------------------------------%
%
% This simple program reads in terms from standard input, and outputs
% those terms as indented structures, annotating each occurrence of
% a function symbol that is an operator with the operator information
% (infix/prefix/postfix, precedence and associativity) that is applicable
% to that occurrence. It stops at end-of-file, and also on any error.
%
% This can be useful when one wants to see how Mercury parses a term
% containing operators, and (which is sometimes just as important)
% *why* it parses a term the way it does.
%
% One can also explore the effects of different operator tables on
% term parsing by simply replacing the operator table assigned to Ops in main
% with a table of one's own choosing.
%
%-----------------------------------------------------------------------------%
:- module show_ops.
:- interface.
:- import_module io.
:- pred main(io::di, io::uo) is det.
:- implementation.
:- import_module int.
:- import_module integer.
:- import_module list.
:- import_module mercury_term_parser.
:- import_module ops.
:- import_module string.
:- import_module term.
:- import_module term_io.
:- import_module varset.
main(!IO) :-
read_term(ReadTerm, !IO),
(
ReadTerm = eof
;
ReadTerm = error(_, _),
io.write_string("error\n", !IO)
;
ReadTerm = term(VarSet, Term),
io.nl(!IO),
Ops = ops.init_mercury_op_table,
print_term(0, Ops, VarSet, Term, !IO),
main(!IO)
).
:- pred print_term(int::in, ops.mercury_op_table::in,
varset::in, term::in, io::di, io::uo) is det.
print_term(Indent, Ops, VarSet, Term, !IO) :-
indent(Indent, !IO),
(
Term = variable(Var, _Context),
varset.lookup_name(VarSet, Var, VarName),
io.write_string(VarName, !IO),
io.nl(!IO)
;
Term = functor(Functor, ArgTerms, _Context),
(
Functor = atom(Name),
io.write_string(Name, !IO),
( if ops.lookup_op_infos(Ops, Name, HeadInfo, TailInfos) then
print_applicable_ops([HeadInfo | TailInfos], ArgTerms, !IO)
else
true
)
;
Functor = integer(_Base, Integer, _Signedeness, _Size),
% XXX should not just write this out as a decimal integer.
io.write_string(to_string(Integer), !IO)
;
Functor = string(Str),
io.write_string("\"", !IO),
io.write_string(Str, !IO),
io.write_string("\"", !IO)
;
Functor = float(Float),
io.write_float(Float, !IO)
;
Functor = implementation_defined(Str),
io.write_string("impl_def ", !IO),
io.write_string(Str, !IO)
),
io.nl(!IO),
list.foldl(print_term(Indent + 1, Ops, VarSet), ArgTerms, !IO)
).
:- pred print_applicable_ops(list(op_info)::in, list(term)::in,
io::di, io::uo) is det.
print_applicable_ops([], _ArgTerms, !IO).
print_applicable_ops([HeadInfo | TailInfos], ArgTerms, !IO) :-
HeadInfo = op_info(Class, Prio),
(
Class = infix(LAssoc, RAssoc),
( if ArgTerms = [_, _] then
io.format(" infix %d %sf%s",
[i(Prio), s(assoc_str(LAssoc)), s(assoc_str(RAssoc))], !IO)
else
true
)
;
Class = binary_prefix(LAssoc, RAssoc),
( if ArgTerms = [_, _] then
io.format(" binary_prefix %d %sf%s",
[i(Prio), s(assoc_str(LAssoc)), s(assoc_str(RAssoc))], !IO)
else
true
)
;
Class = prefix(Assoc),
( if ArgTerms = [_] then
io.format(" prefix %d f%s",
[i(Prio), s(assoc_str(Assoc))], !IO)
else
true
)
;
Class = postfix(Assoc),
( if ArgTerms = [_] then
io.format(" postfix %d %sf",
[i(Prio), s(assoc_str(Assoc))], !IO)
else
true
)
),
print_applicable_ops(TailInfos, ArgTerms, !IO).
:- func assoc_str(ops.assoc) = string.
assoc_str(x) = "x".
assoc_str(y) = "y".
:- pred indent(int::in, io::di, io::uo) is det.
indent(N, !IO) :-
( if N > 0 then
io.write_string(" ", !IO),
indent(N - 1, !IO)
else
true
).