[m-rev.] for review: make parsing tail recursive

Peter Wang novalazy at gmail.com
Wed May 7 14:17:55 AEST 2008


On 2008-05-07, Paul Bone <pbone at csse.unimelb.edu.au> wrote:
> On Wed, May 07, 2008 at 10:41:05AM +1000, Peter Wang wrote:

> > diff -u -r1.58 parser.m
> > --- library/parser.m	3 Apr 2008 05:26:47 -0000	1.58
> > +++ library/parser.m	7 May 2008 00:37:32 -0000
> > @@ -251,7 +251,13 @@
> >  
> >  :- pred check_for_bad_token(token_list::in, string::out, int::out) is semidet.
> >  
> > -check_for_bad_token(token_cons(Token, LineNum, Tokens), Message, LineNum) :-
> > +check_for_bad_token(Token, Message, LineNum) :-
> > +    check_for_bad_token_2(Token, Message),
> > +    Token = token_cons(_, LineNum, _).
> > +
> > +:- pred check_for_bad_token_2(token_list::in, string::out) is semidet.
> > +
> > +check_for_bad_token_2(token_cons(Token, _LineNum, Tokens), Message) :-
> >      ( Token = io_error(IO_Error) ->
> >          io.error_message(IO_Error, IO_ErrorMessage),
> >          string.append("I/O error: ", IO_ErrorMessage, Message)
> > @@ -264,7 +270,7 @@
> >      ; Token = error(ErrorMessage) ->
> >          string.append("Syntax error: ", ErrorMessage, Message)
> >      ;
> > -        check_for_bad_token(Tokens, Message, LineNum)
> > +        check_for_bad_token_2(Tokens, Message)
> >      ).
> >  
> 
> This does not return the correct LineNum for the bad token, rather it
> returns the list head's LineNum.

Yes, it did look strange.  I think you're right about the intended
behaviour, and the non-tail-call was simply an oversight when the
recursive call was added.  I haven't been able to make a test case where
the compiler reports a syntax error on the wrong line though.


Index: library/parser.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/parser.m,v
retrieving revision 1.58
diff -u -r1.58 parser.m
--- library/parser.m	3 Apr 2008 05:26:47 -0000	1.58
+++ library/parser.m	7 May 2008 03:56:16 -0000
@@ -251,21 +251,26 @@
 
 :- pred check_for_bad_token(token_list::in, string::out, int::out) is semidet.
 
-check_for_bad_token(token_cons(Token, LineNum, Tokens), Message, LineNum) :-
+check_for_bad_token(token_cons(Token, LineNum0, Tokens), Message, LineNum) :-
     ( Token = io_error(IO_Error) ->
         io.error_message(IO_Error, IO_ErrorMessage),
-        string.append("I/O error: ", IO_ErrorMessage, Message)
+        string.append("I/O error: ", IO_ErrorMessage, Message),
+        LineNum = LineNum0
     ; Token = junk(Char) ->
         char.to_int(Char, Code),
         string.int_to_base_string(Code, 10, Decimal),
         string.int_to_base_string(Code, 16, Hex),
         string.append_list(["Syntax error: Illegal character 0x", Hex,
-            " (", Decimal, ") in input"], Message)
+            " (", Decimal, ") in input"], Message),
+        LineNum = LineNum0
     ; Token = error(ErrorMessage) ->
-        string.append("Syntax error: ", ErrorMessage, Message)
+        string.append("Syntax error: ", ErrorMessage, Message),
+        LineNum = LineNum0
     ;
         check_for_bad_token(Tokens, Message, LineNum)
     ).
+check_for_bad_token(token_nil, _, _) :-
+    fail.
 
 :- pred parse_whole_term(parse(term(T))::out,
     state(Ops, T)::in, state(Ops, T)::out) is det <= op_table(Ops).


--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list