guile-reader-devel
[Top][All Lists]
Advanced

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

Re: Making TRs with 'guile-number and 'whitespace


From: Phil
Subject: Re: Making TRs with 'guile-number and 'whitespace
Date: Sat, 15 Jan 2022 12:05:36 +0000
User-agent: mu4e 1.4.15; emacs 27.2

I've somewhat answered my own question (I hope!) - see below for comments.

Phil writes:

> Hi,
>
> 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 
> solving
> 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.

I've reread the manual and as a result had another crack at the code.

This time it feels like I'm more or less doing the right thing
(hopefully!) - which is to use Readers not TRs to consume each token in
my own TR function.

Is the below approach more idiomatic of the intended use of the library?
Anything I'm doing wrong?

One thing left I don't like is the use of:
(unget-char port chr)

This is to put the first char of the function call in the input file to
be compiled back onto the port, to avoid me reading "orward" instead of
"forward".  My solution works, but feels a ugly - any better way of
doing this?

Cheers,
Phil.



#!/usr/bin/env -S guile -s
!#

;; requires guile-reader >= 0.63

(use-modules
 (system reader)
 (ice-9 textual-ports))

(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 my-fn-reader (make-reader (list (standard-token-reader 
'guile-symbol-lower-case))))
(define my-num-reader (make-reader (list (make-token-reader #\space #f) ;; 
ignore space between func and number
                                         (standard-token-reader 
'guile-number))))

(define (my-token-reader-proc chr port reader top-level-reader)
  (unget-char port chr) ;; can returning the character to the port?
  ;; we use readers here not token-readers because readers
  ;; move our position in the port to end of read symbols, TRs don't?
  (let* ((fn (my-fn-reader port))
         (num (my-num-reader port)))
    (list fn num)))

(define my-reader
  (make-reader (list (make-token-reader '(#\a . #\z) my-token-reader-proc)
                     (make-token-reader #\newline #f)))) ;; ignore newline 
immediately after parsing "func num"

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



reply via email to

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