4

We are trying to generate (in guile) a parser and a lexer that read characters from a string instead of stdin.

We started modifying the calculator example included in the code at http://code.google.com/p/lalr-scm/source/browse/trunk/calc.scm?r=52

The problem seems to be in the following line:

(let* ((location (make-source-location "*stdin*" 
(port-line (current-input-port)) 
(port-column (current-input-port)) -1 -1))

We tried to define a new input port:

(let* ((location (make-source-location "*stdin*" 
(port-line (open-input-string program)) 
(port-column (open-input-string program)) -1 -1))

and variable program was defined this way:

(define program
"int x = 2;
 int y = 0;
 y= x*(2+3);"
 )     

but it doesn't work, it still waits for standard input characters.

The documentation lacks details, so we can't figure out how we can solve this.

Thank you

  • 1
    Chris Jester-Young's note about how most of the I/O in Scheme uses the current-input-port as default is spot on. You'll want to explicitly pass your string port to each of the I/O functions. See the documentation to `read-char`, for example: http://www.gnu.org/software/guile/manual/guile.html#Reading. Note that the `port` argument is in brackets: that's the documentation's notation for "optional argument". – dyoo Nov 15 '12 at 17:52

1 Answers1

2

You are very, very close to the solution! Well, sort of. But here's a start. Look at the original code, around where you were modifying it:

(let* ((location (make-source-location "*stdin*" (port-line (current-input-port)) (port-column (current-input-port)) -1 -1))
       (c (read-char)))
  ...)

Here, you changed all your (current-input-port) to your string port (BTW, don't call open-input-string more than once, since you create a new string port each time, each with independent cursors), but it's not the only place that actually uses (current-input-port).

Do you see it? It's actually in the (read-char) call! That function actually takes a port argument, defaulting to (current-input-port).

In fact, if you look above and search for instances of (read-char) and (peek-char), you'll notice that the use of (current-input-port) is pretty much baked into the whole make-lexer function. So you will need to change that.

I would suggest that you specify an input port to the make-lexer function:

(define* (make-lexer errorp #:optional (input (current-input-port)))
  ...

then change all instances of (read-char) and (peek-char) to use the input port. Also don't forget to change your make-source-location call too:

(let* ((location (make-source-location "*stdin*" (port-line input) (port-column input) -1 -1))
       (c (read-char input)))
  ...)

Now, you can use (make-lexer errorp (open-input-string program)) and it should work. (I have not tested it.)

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
  • Hi,thank you for your answer, I tried to do as you said, but I get this error: In expression (define* (make-lexer errorp # ...)) Unbound variable: define*. Have you got any idea of what's the problem? – user1826438 Nov 15 '12 at 22:23
  • What version of Guile are you using? If it's 1.x, you will need to use `(use-modules (ice-9 optargs))` at the top of your program. (Guile 2.x already has `define*` built-in.) – C. K. Young Nov 15 '12 at 23:18
  • 1
    I'm using the 1.8, while a friend of mine uses the 2.0 and it works...so this evening I'll import (use-modules (ice-9 optargs))..Thank you very much Chris! – user1826438 Nov 16 '12 at 08:11