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
  • 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: 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". Commented Nov 15, 2012 at 17:52

1 Answer 1

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.)

Sign up to request clarification or add additional context in comments.

3 Comments

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?
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.)
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!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.