[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