Linea: line oriented reader
William Hatch <william@hatch.uno>
Note that you can’t represent any arbitrary s-expression with Linea, but you can represent a very useful subset of them.
1 Stability
Everything documented here is stable unless it says otherwise.
2 Linea Guide
TODO
Explanation of inner/outer reading, readtable modifications, #%symbol defaults.
TL;DR
#lang linea "my-lang-bindings.rkt"
finwe feanor fingolfin finarfin
beren (and) \
luthien tinuviel
(huan (vs) werewolf-sauron)
manwe orome {
varda yavanna
aule (mandos
nienna #{ulmo tulkas})
melkor
}
(module <some-file-name> "my-lang-bindings.rkt"
(#%module-begin
(#%linea-line finwe feanor fingolfin finarfin)
(#%linea-line beren (and) luthien tinuviel)
(#%linea-s-exp (huan (vs) werewold-sauron))
(#%linea-line
manwe
orome
(#%linea-expressions-begin
(#%linea-line varda yavanna)
(#%linea-line aule (mandos
nienna
(#%hash-braces
(#%linea-expressions-begin
(#%linea-line ulmo tulkas)))))
(#%linea-line melkor)))))
2.1 Line Macros
Line macros are designed to give lines of code flexible meaning. They are similar to Racket’s treatment of S-expressions with macros and #%app.
Just like the macro expander will check whether the first element of a form is bound as a macro, #%linea-line checks if the first element of a line is a line macro. Just like the macro expander inserts #%app if there is not an explicit macro use, #%linea-line inserts #%linea-default-line-macro.
One major difference is that line macros are specially marked with prop:line-macro, because the macros that you want to override S-expression meaning and line meaning are not necessarily the same. The define-line-macro form defines line macros that also work as a normal macro (and execute the same syntax transformer), but that is not required.
3 Linea Reference
3.1 linea/defaults
TODO: #%hash-braces – currently #%hash-braces are not defined by default, but they are defined if you (require rash/demo/setup)...
syntax
(#%linea-expressions-begin e ...)
syntax
(#%linea-line starter e ...)
syntax
(#%linea-s-exp e)
syntax
The identifier #%linea-default-line-macro is the default that is inserted when no explicit line macro is used. But by default it just raises an error. This is configured with with-default-line-macro.
Don’t count on the name being the same at any future time. Don’t set it yourself. Use with-default-line-macro.
3.2 linea/line-macro
syntax
(define-line-macro name transformer)
;; in a language like Rash that uses the Linea reader... (require (for-syntax racket/base syntax/parse)) (define-line-macro basic-app (syntax-parser [(_ e ...) #'(#%app e ...)])) basic-app println "hello world" (define-line-macro my-for (syntax-parser [(_ i:id (~datum in) from:id ... (~datum do) body:expr) #'(for ([i (list 'from ...)]) body)])) my-for f in file1.txt file2.txt do { basic-app println f }
Use with-default-line-macro to set it for a region of code.
line-macro
(with-default-line-macro new-default-line-macro body ...)
(with-default-line-macro basic-app { displayln "Oh hi" displayln "what's up?" }) ;; or with-default-line-macro basic-app { displayln "Oh hi" displayln "what's up?" }
line-macro
(splicing-with-default-line-macro new-default-line-macro body ...)
3.3 linea/line-macro-prop
syntax class
The property should hold a procedure that takes a struct instance as its first argument and a syntax object as its second argument.
(struct my-line-macro-struct (transformer) #:property prop:line-macro (λ (inst . args) (apply (my-line-macro-struct-transformer inst) args)))
procedure
(line-macro? x) → any/c
x : any/c
3.4 #lang linea
#lang linea | package: linea |
#lang racket/base (require linea/defaults linea/line-macro (for-syntax racket/base syntax/parse)) (define-line-macro print-quoted-list (syntax-parser [(_ e ...) #'(println '(e ...))])) (provide (all-from-out linea/defaults linea/line-macro racket/base) print-quoted-list)
#lang linea "mylang.rkt" ;; prints '(a b c) print-quoted-list a b c with-default-line-macro print-quoted-list { ;; prints '(hello world) hello world }
Be sure that the module you name at the top-level provides a binding for #%linea-line, #%linea-s-exp, and #%linea-expressions-begin, in addition to other #% identifiers that a module needs (eg. #%module-begin, #%app, ...).
3.5 linea/read
TODO:
linea-read-syntax
linea-read
make-linea-read-funcs
readtable-add-linea-escape
default-linea-s-exp-readtable
default-linea-line-readtable
default-linea-line-avoid-list
current-linea-s-exp-readtable
current-linea-line-readtable
current-linea-line-avoid-list
4 Code and License
The code is available on github.
This library is licensed under the terms of the LGPL version 3, or (at your option) any later version published by the Free Software Foundation (IE LGPL3+).