[m-rev.] Re: [m-dev.] '|' as an operator
David Overton
dmo at cs.mu.OZ.AU
Tue Feb 11 15:09:47 AEDT 2003
On Tue, Feb 11, 2003 at 02:31:58PM +1100, Fergus Henderson wrote:
> On 11-Feb-2003, David Overton <dmo at cs.mu.OZ.AU> wrote:
> > We have been using `|' as an operator in HAL using the SICstus reader
> > (which treats it the same as `;', except in lists). Now that the HAL
> > compiler is compiling to Mercury, we are using lexer.m from the Mercury
> > library instead. Unfortunately, lexer.m treats `|' as a special token
> > `ht_sep' so it is not possible to define it as an operator.
>
> The reason lexer.m treats `|' as a special token is because that is
> what ISO Prolog specifies.
>
> > It would seem to me that `|' only needs to be treated as a special token
> > when we are inside a [ ... ] construct. My plan is to change lexer.m so
> > that `|' produces the token `name("|")' and then changing parser.m to
> > use `name("|")' instead of `ht_sep' when parsing lists. This would then
> > allow `|' to also be defined as an operator.
> >
> > Can anyone see any problem with this?
>
> Well, if `|' is defined as an operator with priority =< arg_priority, then
> there would be no way to use `|' in list syntax -- the parser would always
> prefer to parse it as an operator. Furthermore, in Mercury currently
> arg_priority is 1201, i.e. *all* operators have priority =< arg_priority.
Okay, how about if we do something like the following? It's backwards
compatible and allows `|' to be used as a `name("|")' except when we are
parsing a list. (I'm still in the middle of bootchecking this, btw, but
I think it should be okay.)
Estimated hours taken: 2
Branches: main
library/parser.m:
Allow `|' to be treated as an ordinary token unless we are parsing a
list. This allows, e.g. for `|' to be defined as an operator.
Use record syntax for the `parser_state' type.
Index: parser.m
===================================================================
RCS file: /home/mercury1/repository/mercury/library/parser.m,v
retrieving revision 1.38
diff -u -r1.38 parser.m
--- parser.m 8 Nov 2001 15:30:38 -0000 1.38
+++ parser.m 11 Feb 2003 03:53:39 -0000
@@ -523,7 +523,7 @@
parser__parse_simple_term_2(name(Atom), Context, Prec, Term) -->
parser__get_term_context(Context, TermContext),
( parser__get_token(open_ct) ->
- parser__parse_args(Args0),
+ parser__leave_list_context(parser__parse_args, Args0),
( { Args0 = ok(Args) },
{ Term = ok(term__functor(term__atom(Atom), Args,
TermContext)) }
@@ -559,7 +559,7 @@
{ Term = ok(term__functor(term__string(String), [], TermContext)) }.
parser__parse_simple_term_2(open, _, _, Term) -->
- parser__parse_term(Term0),
+ parser__leave_list_context(parser__parse_term, Term0),
( { Term0 = ok(_) } ->
( parser__get_token(close) ->
{ Term = Term0 }
@@ -579,7 +579,7 @@
( parser__get_token(close_list) ->
parser__parse_special_atom("[]", TermContext, Term)
;
- parser__parse_list(Term)
+ parser__enter_list_context(parser__parse_list, Term)
).
parser__parse_simple_term_2(open_curly, Context, _, Term) -->
@@ -593,7 +593,7 @@
% it as "'{}'(1,2,3)". This makes the
% structure of tuple functors the same
% as other functors.
- parser__parse_term(SubTerm0),
+ parser__leave_list_context(parser__parse_term, SubTerm0),
( { SubTerm0 = ok(SubTerm) } ->
{ conjunction_to_list(SubTerm, ArgTerms) },
( parser__get_token(close_curly) ->
@@ -756,14 +756,20 @@
:- type parser__state(Ops, T) % <= op_table(Ops)
---> parser__state(
- string, % the name of the stream being parsed
- Ops, % the current set of operators
- varset(T), % the names of the variables in the
+ filename :: string,
+ % the name of the stream being parsed
+ ops_table :: Ops, % the current set of operators
+ varset :: varset(T),
+ % the names of the variables in the
% term being parsed
- token_list, % the remaining tokens
- map(string, var(T))
+ tokens :: token_list,
+ % the remaining tokens
+ names :: map(string, var(T)),
% a map from variable name to variable
% so we know when to make a fresh var
+ in_list_context :: bool
+ % Are we inside a list context where `|'
+ % must be treated specially?
).
%-----------------------------------------------------------------------------%
@@ -815,7 +821,7 @@
:- mode parser__error(in, out, in, out) is det.
parser__error(Message, error(Message, Tokens), ParserState, ParserState) :-
- ParserState = parser__state(_, _, _, Tokens, _).
+ Tokens = ParserState ^ tokens.
%-----------------------------------------------------------------------------%
@@ -851,13 +857,12 @@
parser__init_state(Ops, FileName, Tokens, ParserState) :-
varset__init(VarSet),
map__init(Names),
- ParserState = parser__state(FileName, Ops, VarSet, Tokens, Names).
+ ParserState = parser__state(FileName, Ops, VarSet, Tokens, Names, no).
:- pred parser__final_state(parser__state(Ops, T), varset(T), token_list).
:- mode parser__final_state(in, out, out) is det.
-parser__final_state(parser__state(_FileName, _OpTable, VarSet, TokenList,
- _Names), VarSet, TokenList).
+parser__final_state(State, State ^ varset, State ^ tokens).
%-----------------------------------------------------------------------------%
@@ -870,12 +875,18 @@
:- pred parser__get_token(token, token_context,
parser__state(Ops, T), parser__state(Ops, T)).
:- mode parser__get_token(out, out, in, out) is semidet.
-:- mode parser__get_token(in, in, out, in) is det.
-parser__get_token(Token, Context,
- parser__state(FileName, OpTable, VarSet, Tokens0, Names),
- parser__state(FileName, OpTable, VarSet, Tokens, Names)) :-
- Tokens0 = token_cons(Token, Context, Tokens).
+parser__get_token(Token, Context, State0, State) :-
+ State0 ^ tokens = token_cons(Token0, Context, Tokens),
+ State = ( State0 ^ tokens := Tokens ),
+ (
+ State ^ in_list_context = no,
+ Token0 = ht_sep
+ ->
+ Token = name("|")
+ ;
+ Token = Token0
+ ).
:- pred parser__unget_token(token, token_context,
parser__state(Ops, T), parser__state(Ops, T)).
@@ -883,7 +894,9 @@
:- mode parser__unget_token(out, out, out, in) is semidet.
parser__unget_token(Token, Context, ParseState0, ParseState) :-
- parser__get_token(Token, Context, ParseState, ParseState0).
+ ParseState0 ^ tokens = Tokens,
+ ParseState = ( ParseState0 ^ tokens :=
+ token_cons(Token, Context, Tokens) ).
:- pred parser__peek_token(token, parser__state(Ops, T), parser__state(Ops, T)).
:- mode parser__peek_token(out, in, out) is semidet.
@@ -896,7 +909,7 @@
:- mode parser__peek_token(out, out, in, out) is semidet.
parser__peek_token(Token, Context) -->
- =(parser__state(_, _, _, Tokens, _)),
+ Tokens =^ tokens,
{ Tokens = token_cons(Token, Context, _) }.
%-----------------------------------------------------------------------------%
@@ -905,27 +918,52 @@
parser__state(Ops, T)).
:- mode parser__add_var(in, out, in, out) is det.
-parser__add_var(VarName, Var,
- parser__state(FileName, OpTable, VarSet0, Tokens, Names0),
- parser__state(FileName, OpTable, VarSet, Tokens, Names)) :-
+parser__add_var(VarName, Var, State0, State) :-
+ VarSet0 = State0 ^ varset,
+ Names0 = State0 ^ names,
( VarName = "_" ->
varset__new_var(VarSet0, Var, VarSet),
- Names = Names0
+ State = ( State0 ^ varset := VarSet )
; map__search(Names0, VarName, Var0) ->
Var = Var0,
- VarSet = VarSet0,
- Names = Names0
+ State = State0
;
varset__new_named_var(VarSet0, VarName, Var, VarSet),
- map__det_insert(Names0, VarName, Var, Names)
+ map__det_insert(Names0, VarName, Var, Names),
+ State1 = ( State0 ^ varset := VarSet ),
+ State = ( State1 ^ names := Names )
).
:- pred parser__get_ops_table(Ops, parser__state(Ops, T),
parser__state(Ops, T)) <= op_table(Ops).
:- mode parser__get_ops_table(out, in, out) is det.
-parser__get_ops_table(OpTable) -->
- =(parser__state(_, OpTable, _, _, _)).
+parser__get_ops_table(OpsTable) -->
+ OpsTable =^ ops_table.
+
+:- pred parser__enter_list_context(
+ pred(U, parser__state(Ops, T), parser__state(Ops, T)), U,
+ parser__state(Ops, T), parser__state(Ops, T)) <= op_table(Ops).
+:- mode parser__enter_list_context(pred(out, in, out) is det, out, in, out)
+ is det.
+
+parser__enter_list_context(P, Result) -->
+ InListContext =^ in_list_context,
+ ^in_list_context := yes,
+ P(Result),
+ ^in_list_context := InListContext.
+
+:- pred parser__leave_list_context(
+ pred(U, parser__state(Ops, T), parser__state(Ops, T)), U,
+ parser__state(Ops, T), parser__state(Ops, T)) <= op_table(Ops).
+:- mode parser__leave_list_context(pred(out, in, out) is det, out, in, out)
+ is det.
+
+parser__leave_list_context(P, Result) -->
+ InListContext =^ in_list_context,
+ ^in_list_context := no,
+ P(Result),
+ ^in_list_context := InListContext.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
@@ -950,7 +988,7 @@
:- mode parser__get_term_context(in, out, in, out) is det.
parser__get_term_context(TokenContext, TermContext) -->
- =(parser__state(FileName, _Ops, _VarSet, _Tokens, _Names)),
+ FileName =^ filename,
{ term__context_init(FileName, TokenContext, TermContext) }.
%-----------------------------------------------------------------------------%
--
David Overton Uni of Melbourne +61 3 8344 1354
dmo at cs.mu.oz.au Monash Uni (Clayton) +61 3 9905 5779
http://www.cs.mu.oz.au/~dmo Mobile Phone +61 4 0337 4393
--------------------------------------------------------------------------
mercury-reviews mailing list
post: mercury-reviews at cs.mu.oz.au
administrative address: owner-mercury-reviews at cs.mu.oz.au
unsubscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: unsubscribe
subscribe: Address: mercury-reviews-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------
More information about the reviews
mailing list