Hi Ernest,

FWIW, I was able to get correct behavior by simply changing the line in
nextToken from:

  // ******************************
  // second and later characters of a multi-character token
  do
   {
    c = nextChar();
    if (Character.isSpace((char)c))
      {
           m_ios.reset();
         return finishToken(0, s);
      }

to:
  // ******************************
  // second and later characters of a multi-character token
  do
   {
    c = nextChar();    if (Character.isSpace((char)c))
      {
         if(c!='\n')            // don't replace whitespace if eol
             m_ios.reset();
         return finishToken(0, s);
      }

As you can tell, this avoids putting back the first 'whitespace'
character after a token if the char is a newline.  This means that
readline will not retrieve it.  But, if the user enters just \r\n again,
the readline will see it.  This works because the token ends with a
newline.

I've been thinking it over, and this doesn't seem to be as bad a hack as
I first thought.  Whether reading from console or file, I can't think of
when this newline would have been intended for read or readline to see
it.  If a blank line is intended for readline, then there would be two
newlines in a row, one after the token, and another one on the next line
of incoming text.  If another read is performed after read, it would
skip over the 'whitespace' anyway, so with this fix we just have one
less whitespace character to skip over.  By 'return finishToken(...)'
we've already decided this token is ended, even though the next char in
the input stream may not be whitespace (having not reset the \n char).
I've pretty much convinced myself that this is one exception to putting
back the first whitespace character found after a token.  Have I
convinced you?

This fix doesn't depend on the streams source, whether console or file.
Anyway, if you choose not to use this, I won't feel offended, or get
indignant, but here it is 'for what its worth'.

Mike



-----Original Message-----
From: Ernest Friedman-Hill [mailto:[EMAIL PROTECTED]]
Sent: Wednesday, June 24, 1998 15:24
To: [EMAIL PROTECTED]
Subject: Re: JESS: read followed by readline


Hi Micahel,

You're right, "Animals" is broken again. 

Lest everyone think I'm a complete moron, let me explain what's going
on:
1) CLIPS' treatment of (read) and (readline) is -extremely-
context-sensitive; 2) The buffering behaviour of Java's higher-level
I/O streams change with each new release; 3) I personally rarely write
systems that use (read).

#2 is why Jess 4.1's biggest new feature is an entire new tokenization
scheme that doesn't use DataInputStream or StreamTokenizer at
all. Remember, that's what we're testing during this beta period!

#1 is the biggest problem. CLIPS treats (read) and (readline)
differently if the stream being read from is standard input as opposed
to a file. At the console, (read) actually consumes an entire line of
input (including the readline,) then keeps only the first token. In
contrast, (read) from a file finds the next token, crossing line
boundries only if needed. If the consumed token is the last token on a
line, then the following newline is LEFT ON THE STREAM, so that a
subsequent (readline) call returns an empty string.

Now, in Java, "standard input" might be System.in, or a textfield in a
GUI, or a network stream... so it's not clear how the implementation
of read is supposed to know what kind of router it's talking to. I
could special-case the 't' router, for example, I suppose; but this
would not always help. For example, if I'm writing a GUI, and I 
install a new stream 'foo' connected to a GUI console, and I write
rules to explicitly read from the 'foo' router, well, than this won't
be enough.

So here's an idea that strikes me as even uglier, but which I suppose
would work: the 'addInputRouter' function gets another argument, a
boolean named 'actAsConsole'. Routers added with this flag set to true
get the console (read) behaviour; false give the file behaviour. Jess
would internally take care of this for opened files and the standard
streams, of course. I guess there'd need also to be a function
getInputRouterBehavior().

I guess that's not so bad. Thanks for giving me the chance to write
this; it was therapeutic, and I might even get it straight this time! :)


I think Michael A. Fochtman wrote:
> 
> Hi all,
> 
> Using Jess 41b2, I came across a problem with using read and readline.
> I'm using NT4.0, VJ++ and MS SDK 2.01, just for the record.
> 
> The problem can be seen in the 'animal.clp' demo, in the rule
> 'replace-answer-node'.  When the intrinsic function 'read' is called,
it
> eventually gets around to calling jess.Tokenizer.nextToken().  This
> calls jess.Tokenizer.nextChar().  nextChar() correctly converts \r\n
> pairs to \n.  Since \n is considered whitespace, when nextChar()
returns
> that in the second loop of nextToken(), it puts the last char back by
> calling m_ios.reset() and terminates.  This seems okay.
> 
> My problem is, when the rule then calls 'readline', the first
character
> read in is the \n put back by nextToken().  The function treats this
as
> the end of the line, and returns a string of zero length.  (in the
> animal.clp demo, when it asks for a question to differentiate the last
> known animal with your new animal, it completes immediately with a
zero
> length question).
> 
> Now it seems to me, that nextToken() is doing the right thing, by
> restoring the first whitespace character after the token.  And, it
seems
> reasonable for the readline method to allow entering just a newline
for
> a string of zero length.  So, how do I get the animal.clp demo to
> behave??  that is, get 'read' and 'readline' to work together??
> 
> Or, maybe this isn't a problem with other compilers/javaVMs??  Anyone
> have this problem on other platforms, java VM?
> 
> TIA
> 
> Mike Fochtman
> 



---------------------------------------------------------
Ernest Friedman-Hill  
Distributed Systems Research        Phone: (510) 294-2154
Sandia National Labs                FAX:   (510) 294-2234
Org. 8920, MS 9214                  [EMAIL PROTECTED]
PO Box 969                  http://herzberg.ca.sandia.gov
Livermore, CA 94550

---------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the
list. List problems? Notify [EMAIL PROTECTED]
---------------------------------------------------------------------
---------------------------------------------------------------------
To unsubscribe, send the words 'unsubscribe jess-users [EMAIL PROTECTED]'
in the BODY of a message to [EMAIL PROTECTED], NOT to the
list. List problems? Notify [EMAIL PROTECTED]
---------------------------------------------------------------------

Reply via email to