Files
mercury/browser/parse.m
Mark Brown 6cd413a850 Enhance the configuration parameters of the browser.
Estimated hours taken: 25

Enhance the configuration parameters of the browser.  The browser is now
sensitive to the type of caller (print, browse, or print *) and can have
different settings for each type.  E.g., the default line limit per variable
can be made shorter for `print *' than for `print'.  The browser also allows
different settings for each format.

The browser also accepts an optional format, which overrides the current
setting for the duration of the call.

To make use of these features, mdb has a new `set' command that allows the
settings to be updated in various ways.  The browser version of `set'
still works, although it doesn't yet accept the options that the former does.
Also, `print' and `browse' can now take options that override the default
format.

browser/browser_info.m:
	New module which defines the key browser data structures.  The
	`browser_state' previously used by browse.m has been split into
	two parts: the transient state (browser_info) and the persistent
	state (browser_persistent_state).  The persistent state is created
	when the browser is first called, and is saved between calls to the
	browser, whereas a new transient state is created each time the
	browser is called, and lasts for the duration of the call.

	The persistent state contains settings for each possible combination
	of format and caller type.

	This module exports C functions that update the persistent state.

browser/browse.m:
	Move the browser_state into the new module.

	Change the interface so that it allows optional format and caller
	type input arguments.  This allows its behaviour to vary depending on
	whether the caller is implementing `print', `browse', or `print *'.
	It also allows the default format to be overridden by options to
	these commands.

	General rearrangement of the browser code to avoid code duplication.
	This addresses the following comment from the module:
	% XXX: could abstract out the code common to the following preds.
	along with other similar problems.

	The code for testing the size of a term and deciding between
	`io__write' and a depth limited printer has been moved from `print'
	to `portray_flat'.  This allows `print' to be used with formats
	other than flat.

	TODO: allow browser commands to take format options; currently only
	mdb commands can.

browser/declarative_user.m:
	Update this for the changed interfaces.

browser/mdb.m:
	Add the new module.

browser/parse.m:
	Move the definitions of `dir', `setting', and `portray_format'
	to the interface of the new module.

	The argument to the `<' command, which sets the depth limit, is
	no longer optional.  The default used to be to use the system
	default, but now there are multiple system defaults and no way to
	select which one.

browser/*.m:
tests/debugger/browse_pretty.inp:
tests/debugger/browse_pretty.exp:
	s/clipx/width/g
	s/clipy/lines/g

	The reason for this change is that the names are used in the
	context of all formats, but only verbose format actually clips
	the output, so `clipx' and `clipy' are misleading.

tests/debugger/browser_test.inp:
tests/debugger/browser_test.exp:
	Test the new features.

doc/user_guide.texi:
	Document the new features.

trace/mercury_trace_browse.c:
trace/mercury_trace_browse.h:
	Allow extra arguments for the print and browse functions, to specify
	the format and the caller type (in the case of print).

	Export the function MR_trace_set_browser_param, which calls the
	browser to do the work of mdb's set command.

	Export the types MR_Browse_Caller_Type and MR_Browse_Format, which
	mirror two of the types in the new browser module.

trace/mercury_trace_external.c:
	Update for the change to MR_trace_browse_one: pass `browse' as
	the caller type, and always use the default format.

trace/mercury_trace_internal.c:
	Add functions to parse the format and caller type options.  Update
	the print and browse commands to expect format options.  Add the
	`set' command.

	Replace MR_trace_print_var and MR_trace_browse_var with one function,
	MR_trace_browse_internal.  This function takes the caller type as an
	argument, so there is no need for two functions.

	Remove occurrences of:
	/* XXX should use MR_mdb_in and MR_mdb_out */
	since we already do this.

trace/mercury_trace_vars.c:
trace/mercury_trace_vars.h:
	Change the function type MR_Browser so that it also expects a caller
	type and a format.  These arguments are now required by the browser.
	This means that some of the functions that take an MR_Browser
	argument needed to be updated to also take a caller and/or format,
	so they can pass this on to the browser function when it is called.
2000-10-27 08:38:58 +00:00

435 lines
9.4 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1998-2000 The University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% file: parse.m:
% author: aet
% This file contains the parser for the term browser command language.
% If the term browser is called from mdb, it parses the stuff you type
% at the "browser> " prompt after typing "browse" from the mdb prompt.
% If it is called from the external debugger, then it parses the stuff
% contained in a term `external_request(<string to parse>)' send by the
% external debugger.
%---------------------------------------------------------------------------%
% The Command Language
%
% commandline:
% "?" // SICstus help
% "^" [numlist] // SICstus cd
% "d" // SICstus display
% "w" // SICstus write
% "help"
% "cd" [path]
% "pwd"
% "ls"
% "display"
% "write"
% "set" [varvalue]
% "quit"
%
% varvalue:
% "depth" num
% "size" num
% "clipx" num
% "clipy" num
% "format" fmt
%
% numlist:
% num
% num numlist
%
% fmt:
% "flat"
% "pretty"
% "verbose"
%
% path:
% ["/"] [dirs]
%
% dirs:
% dir ["/" dirs]
%
% dir:
% num
% ".."
%
:- module mdb__parse.
:- interface.
:- import_module io, string, list.
:- import_module mdb__browser_info.
:- type command
---> ls(path)
; ls
; cd(path)
; cd
; pwd
; help
; set(setting)
; set
; quit
; print
; display
; write
; unknown
.
:- type path
---> root_rel(list(dir))
; dot_rel(list(dir)).
% If the term browser is called from the external debugger, the term browser
% commands are send through the socket via terms of type external_request.
:- type external_request
---> external_request(string).
:- pred parse__read_command(string, command, io__state, io__state).
:- mode parse__read_command(in, out, di, uo) is det.
:- pred parse__read_command_external(command, io__state, io__state).
:- mode parse__read_command_external(out, di, uo) is det.
%---------------------------------------------------------------------------%
:- implementation.
:- import_module list, char, int, std_util.
:- import_module mdb__util.
:- type token
---> (.)
; (..)
; (/)
; (?)
; (^)
; (<)
; num(int)
; name(string)
; unknown(char)
.
parse__read_command(Prompt, Comm) -->
util__trace_get_command(Prompt, Line),
{ string__to_char_list(Line, Cs) },
{ lexer(Cs, Tokens) },
( { parse(Tokens, Comm2) } ->
{ Comm = Comm2 }
;
{ Comm = unknown }
).
parse__read_command_external(Comm) -->
io__read(Result),
(
{ Result = ok(external_request(StringToParse)) }
->
{ string__to_char_list(StringToParse, Cs) },
{ lexer(Cs, Tokens) },
( { parse(Tokens, Comm2) } ->
{ Comm = Comm2 }
;
{ Comm = unknown }
)
; { Result = eof } ->
{ Comm = quit }
;
{ Comm = unknown }
).
:- pred lexer(list(char), list(token)).
:- mode lexer(in, out) is det.
lexer([], []).
lexer([C | Cs], Toks) :-
( C = ('.') ->
lexer_dots(Cs, Toks)
; C = ('/') ->
Toks = [(/) | Toks2],
lexer(Cs, Toks2)
; C = ('?') ->
Toks = [(?) | Toks2],
lexer(Cs, Toks2)
; C = ('^') ->
Toks = [(^) | Toks2],
lexer(Cs, Toks2)
; C = ('<') ->
Toks = [(<) | Toks2],
lexer(Cs, Toks2)
; char__is_digit(C) ->
dig_to_int(C, N),
lexer_num(N, Cs, Toks)
; char__is_alpha(C) ->
lexer_name(C, Cs, Toks)
; char__is_whitespace(C) ->
lexer(Cs, Toks)
;
Toks = [unknown(C) | Toks2],
lexer(Cs, Toks2)
).
:- pred lexer_dots(list(char), list(token)).
:- mode lexer_dots(in, out) is det.
lexer_dots([], []).
lexer_dots([C | Cs], Toks) :-
( C = ('.') ->
Tok = (..),
lexer(Cs, Toks2),
Toks = [Tok | Toks2]
;
Tok = (.),
lexer([C | Cs], Toks2),
Toks = [Tok | Toks2]
).
:- pred dig_to_int(char, int).
:- mode dig_to_int(in, out) is det.
dig_to_int(C, N) :-
char__to_int('0', Zero),
char__to_int(C, CN),
N is CN - Zero.
:- pred lexer_num(int, list(char), list(token)).
:- mode lexer_num(in, in, out) is det.
lexer_num(N, Cs, Toks) :-
list__takewhile(char__is_digit, Cs, Digits, Rest),
digits_to_int_acc(N, Digits, Num),
Toks = [num(Num) | Toks2],
lexer(Rest, Toks2).
:- pred digits_to_int_acc(int, list(char), int).
:- mode digits_to_int_acc(in, in, out) is det.
digits_to_int_acc(Acc, [], Acc).
digits_to_int_acc(Acc, [C | Cs], Num) :-
dig_to_int(C, D),
Acc2 is 10 * Acc + D,
digits_to_int_acc(Acc2, Cs, Num).
:- pred lexer_name(char, list(char), list(token)).
:- mode lexer_name(in, in, out) is det.
lexer_name(C, Cs, Toks) :-
list__takewhile(char__is_alpha, Cs, Letters, Rest),
string__from_char_list([C | Letters], Name),
lexer(Rest, Toks2),
Toks = [name(Name) | Toks2].
:- pred parse(list(token), command).
:- mode parse(in, out) is semidet.
parse(Toks, Comm) :-
start(Toks, Comm).
:- pred start(list(token), command).
:- mode start(in, out) is semidet.
start([Tok | Toks], Comm) :-
( (Tok = name("help") ; Tok = (?) ; Tok = name("h")) ->
Toks = [],
Comm = help
; (Tok = name("cd") ; Tok = (^)) ->
( Toks = [] ->
Comm = cd
;
parse_path(Toks, Path),
Comm = cd(Path)
)
; Tok = name("pwd") ->
Toks = [],
Comm = pwd
; Tok = name("ls") ->
( Toks = [] ->
Comm = ls
;
parse_path(Toks, Path),
Comm = ls(Path)
)
; Tok = name("set") ->
( Toks = [] ->
Comm = set
;
parse_setting(Toks, Setting),
Comm = set(Setting)
)
; Tok = name("quit") ->
Toks = [],
Comm = quit
; (Tok = name("display") ; Tok = name("d")) ->
Toks = [],
Comm = display
; (Tok = name("write") ; Tok = name("w")) ->
Toks = [],
Comm = write
; (Tok = name("print") ; Tok = name("p")) ->
Toks = [],
Comm = print
;
Tok = (<),
Toks = [num(Depth)],
Comm = set(depth(Depth))
).
:- pred parse_path(list(token), path).
:- mode parse_path(in, out) is semidet.
% SICStus is forgiving in the syntax of paths, hence so are we.
% XXX: Be less forgiving?
parse_path([Tok | Toks], Path) :-
( Tok = (/) ->
Path = root_rel(Dirs),
parse_dirs(Toks, Dirs)
;
Path = dot_rel(Dirs),
parse_dirs([Tok | Toks], Dirs)
).
:- pred parse_dirs(list(token), list(dir)).
:- mode parse_dirs(in, out) is semidet.
parse_dirs([], []).
parse_dirs([Tok | Toks], Dirs) :-
(
Tok = num(Subdir),
Dirs = [child(Subdir) | RestDirs],
parse_dirs(Toks, RestDirs)
;
Tok = (..),
Dirs = [parent | RestDirs],
parse_dirs(Toks, RestDirs)
;
% We can effectively ignore slashes (for Unix-style
% pathnames) and carets (for SICStus-style pathnames),
% but anything else is not allowed.
Tok = (/),
parse_dirs(Toks, Dirs)
;
Tok = (^),
parse_dirs(Toks, Dirs)
).
:- pred parse_setting(list(token), setting).
:- mode parse_setting(in, out) is semidet.
parse_setting([Tok | Toks], Setting) :-
( Tok = name("depth") ->
Toks = [num(Depth)],
Setting = depth(Depth)
; Tok = name("size") ->
Toks = [num(Size)],
Setting = size(Size)
; Tok = name("width") ->
Toks = [num(X)],
Setting = width(X)
; Tok = name("lines") ->
Toks = [num(Y)],
Setting = lines(Y)
; Tok = name("format") ->
Toks = [Fmt],
( Fmt = name("flat") ->
Setting = format(flat)
; Fmt = name("pretty") ->
Setting = format(pretty)
;
Fmt = name("verbose"),
Setting = format(verbose)
)
;
fail
).
%---------------------------------------------------------------------------%
:- pred show_command(command, io__state, io__state).
:- mode show_command(in, di, uo) is det.
show_command(ls(Path)) -->
io__write_string("ls "),
show_path(Path),
io__nl.
show_command(ls) -->
io__write_string("ls\n").
show_command(cd(Path)) -->
io__write_string("cd "),
show_path(Path),
io__nl.
show_command(cd) -->
io__write_string("cd\n").
show_command(pwd) -->
io__write_string("pwd\n").
show_command(help) -->
io__write_string("help\n").
show_command(set(Setting)) -->
io__write_string("set "),
show_setting(Setting),
io__nl.
show_command(set) -->
io__write_string("set\n").
show_command(quit) -->
io__write_string("quit\n").
show_command(print) -->
io__write_string("print\n").
show_command(display) -->
io__write_string("display\n").
show_command(write) -->
io__write_string("write\n").
show_command(unknown) -->
io__write_string("unknown\n").
:- pred show_path(path, io__state, io__state).
:- mode show_path(in, di, uo) is det.
show_path(root_rel(Dirs)) -->
io__write_string("/"),
show_dirs(Dirs).
show_path(dot_rel(Dirs)) -->
show_dirs(Dirs).
:- pred show_dirs(list(dir), io__state, io__state).
:- mode show_dirs(in, di, uo) is det.
show_dirs([]) -->
io__nl.
show_dirs([child(Num) | Dirs]) -->
io__write_int(Num),
io__write_string("/"),
show_dirs(Dirs).
show_dirs([parent | Dirs]) -->
io__write_string("../"),
show_dirs(Dirs).
:- pred show_setting(setting, io__state, io__state).
:- mode show_setting(in, di, uo) is det.
show_setting(depth(Depth)) -->
io__write_string("depth "),
io__write_int(Depth),
io__nl.
show_setting(size(Size)) -->
io__write_string("size "),
io__write_int(Size),
io__nl.
show_setting(width(X)) -->
io__write_string("width "),
io__write_int(X),
io__nl.
show_setting(lines(Y)) -->
io__write_string("lines "),
io__write_int(Y),
io__nl.
show_setting(format(Fmt)) -->
io__write_string("format "),
show_format(Fmt),
io__nl.
:- pred show_format(portray_format, io__state, io__state).
:- mode show_format(in, di, uo) is det.
show_format(flat) -->
io__write_string("flat").
show_format(pretty) -->
io__write_string("pretty").
show_format(verbose) -->
io__write_string("verbose").
%---------------------------------------------------------------------------%