[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Making TRs with 'guile-number and 'whitespace

From: Phil
Subject: Making TRs with 'guile-number and 'whitespace
Date: Mon, 10 Jan 2022 00:08:14 +0000
User-agent: mu4e 1.4.15; emacs 27.2


I'm hoping for a bit of help answering the 2 questions I have below on
guile-reader usage.

I'm trying out a solution to a puzzle, which takes as an input a series of
function calls with arguments, which are executed in turn.

The function definitions are in Guile and are trivial/irrelevant to the
issue below.

The tricky thing is that the input file is not in scheme format and so cannot be
trivially loaded - function calls look like this

function arg

Rather than:

(function arg)

Given the lack of s-exps in the input, it seemed I was going to get nowhere 
this with a macro, but writing a new reader seemed like a possibility,
and guile-reader seemed like a sensible way of doing this.  (Obviously I
could solve the problem using read-line and a case statement, or just
the sed the original input file, but I'm interested in learning more
about DSLs, the reader, and macros).

See the code at the bottom of this e-mail which is doing more-or-less
what I want, but I've hit 2 ugly snags I'd like to understand better.

The code works by defining a new reader to load the input file, which
consists of 2 token readers - one matches any line starting with a
lowercase character (assumed within this restricted example to always be
a function call), and another which matches and ignores any newlines, etc.

In the lowercase-matching token reader I can't seem to use the Token Reader
for reading whitespace or numerical values:

1. There should be a "whitespace" Token Reader - however in my function
ws-read, if I replace 'character with 'whitespace, ws-read is set to #f,
suggesting no such reader procedure exists?

2. In my function num-read if I replace 'character with 'guile-number
the returned symbols contain the numerical argument, however it is
prefixed with the first character of the function name, for example:

forward 9

Correctly returns from fn-read:


But for num-read I get an extra "f" returned:


(ws-read returns the space in-between as expected).

Hence to make num-read parse correctly, I've used a character code
instead of an integer parse, which is a bit of a hack, and only works for
single digit numbers.

Can anyone explain what is wrong with my use of 'guile-number and
'whitespace token library readers?

For point 1 I've had a look at the token-readers.c and it may be that there
is no whitepace TR?

For point 2 my guess is that it has something to do with the
make-token-reader function absorbing the first char, but I don't
understand why that's then appearing as part of the 3 parse in my-token-reader?

Also if my approach is daft, please feel free to suggest how else to
load the input.txt directly - although I am keen to understand what I'm
doing wrong in the code below and why, even if the approach isn't
brilliant the point of the exercise was to get familiar with guile-reader!


I'm running on Guile 3.0.7 / guile-reader 0.6.3.

Full Puzzle Details (not really necessary to understand the problem, but
for reference) -

Example input.txt:

Full input is here:

Short Example:
forward 9
down 8
down 2
down 4
up 8
forward 8
down 7
forward 3
down 8
down 9

Example code:

Code is here:

Also included below:
#!/usr/bin/env -S guile -s

;; requires guile-reader >= 0.63

 (system reader))

(define hpos 0)
(define vpos 0)

(define (forward n)
  (set! hpos (+ hpos n)))

(define (up n)
  (set! vpos (- vpos n)))

(define (down n)
  (set! vpos (+ vpos n)))

(define fn-read (token-reader-procedure
                 (standard-token-reader 'guile-symbol-lower-case)))

(define ws-read (token-reader-procedure
                 (standard-token-reader 'character))) ;; why not 'whitespace?

(define num-read (token-reader-procedure
                  (standard-token-reader 'character))) ;; why not 'guile-number?

(define (my-token-reader chr port reader top-level-reader)
  (let* ((fn (fn-read chr port reader))
         (_ (ws-read chr port reader)) ;; read and ignore whitespace character
         (num (- (char->integer (num-read chr port reader)) 48))) ;; crude char 
code -> number
    (list fn num)))

(define my-reader
  (make-reader (list (make-token-reader '(#\a . #\z) my-token-reader)
                     (make-token-reader '(#\space #\newline #\tab) #f))))

(load "input.txt" my-reader)
(format #t "~%Result: ~a~%" (* hpos vpos))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]