### Error Acclimation Example with Eclector and Acclimation
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Shows how Eclector uses the Acclimation library to provide localized error messages. It sets up a German locale and then demonstrates error handling similar to the basic recovery example, but with German output for the error condition and restart description.
```common-lisp
(let* ((language (make-instance 'acclimation:german))
(acclimation:*locale* (make-instance 'acclimation:locale :language language)))
(handler-bind ((error (lambda (condition)
(let ((restart (find-restart 'eclector.reader:recover)))
(format t "Behandle Fehler~%~2@T~A~%durch~%~2@T~A~2%"
condition
restart))
(eclector.reader:recover)))))
(eclector.reader:read-from-string "`(::foo ,`)))
```
--------------------------------
### Example of Syntax Highlighting Call (Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Demonstrates a hypothetical function call `highlight-code` used for syntax highlighting. It takes an HTML string with a code element and presumably returns it with appropriate highlighting applied. This is shown in the context of processing Lisp code with comments and strings.
```lisp
(highlight-code "(list 1 #|foo|# \"bar\"")
```
--------------------------------
### Extended Package Prefix Syntax Example (Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/code/syntax-extensions/README.md
Demonstrates the usage of the extended package prefix syntax `PACKAGE::OBJECT` to read an object in a package other than the current one. This requires setting the `eclector.reader:*client*` to an instance of `eclector.syntax-extensions.extended-package-prefix:extended-package-prefix-syntax-mixin`.
```lisp
(let ((eclector.reader:*client* (make-instance 'eclector.syntax-extensions.extended-package-prefix:extended-package-prefix-syntax-mixin)))
(read-from-string "cl-user::(foo bar 1)"))
; => (cl-user::foo cl-user::bar 1)
```
```lisp
(let ((eclector.reader:*client* (make-instance 'eclector.syntax-extensions.extended-package-prefix:extended-package-prefix-syntax-mixin)))
(read-from-string "cl-user::#(foo)"))
; => #(cl-user::foo)
```
```lisp
(let ((eclector.reader:*client* (make-instance 'eclector.syntax-extensions.extended-package-prefix:extended-package-prefix-syntax-mixin)))
(read-from-string "cl-user::;foo
bar"))
; => cl-user::bar
```
--------------------------------
### Error Recovery Example with Eclector
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Demonstrates how Eclector recovers from various parsing errors. It uses `handler-bind` to catch errors, `find-restart` to locate the 'recover' restart, and `format` to display the error condition and the restart description. Finally, it attempts to recover by calling `eclector.reader:recover`.
```common-lisp
(handler-bind ((error (lambda (condition)
(let ((restart (find-restart 'eclector.reader:recover)))
(format t "Recovering from error:~%~2@T~A~%using~%~2@T~A~2%"
condition
restart))
(eclector.reader:recover))))
(print (eclector.reader:read-from-string "`(::foo ,`))))
```
--------------------------------
### Source Position Tracking in Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
Details how to implement custom source position tracking using `eclector.base:source-position`, `eclector.base:make-source-range`, and `eclector.parse-result:make-expression-result`. This example shows a client that captures line and column information.
```Common Lisp
;; Custom source position tracking with line/column info
(defclass line-tracking-client (eclector.parse-result:parse-result-client)
((line :initform 1 :accessor line)
(column :initform 0 :accessor column)))
(defmethod eclector.base:source-position ((client line-tracking-client) stream)
(list :line (line client) :column (column client) :offset (file-position stream)))
(defmethod eclector.base:make-source-range
((client line-tracking-client) start end)
(list :start start :end end))
(defmethod eclector.parse-result:make-expression-result
((client line-tracking-client) result children source)
`(:value ,result :location ,source))
(eclector.parse-result:read-from-string
(make-instance 'line-tracking-client)
"(test)")
;; => (:VALUE (TEST) :LOCATION (:START (:LINE 1 :COLUMN 0 :OFFSET 0)
;; :END (:LINE 1 :COLUMN 6 :OFFSET 6)))
```
--------------------------------
### Installing Reader Macro Characters
Source: https://context7.com/s-expressionists/eclector/llms.txt
Installs reader macro functions for specific characters within Eclector's readtable. This allows for custom parsing behavior based on special characters, such as defining custom syntax for angle brackets.
```lisp
;; Create a custom readtable
(let ((rt (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
;; Add a reader macro for angle brackets
(eclector.readtable:set-macro-character
rt #<
(lambda (stream char)
(declare (ignore char))
(let ((contents (eclector.reader:read-delimited-list #\> stream t)))
(list 'angle-bracket contents))))
;; Use the custom readtable
(let ((eclector.reader:*readtable* rt))
(eclector.reader:read-from-string "")))
;; => (ANGLE-BRACKET (FOO BAR))
;; Set a non-terminating macro character
(eclector.readtable:set-macro-character
eclector.reader:*readtable*
#$
(lambda (stream char)
(declare (ignore char))
(list 'dollar (eclector.reader:read stream t nil t)))
t) ; non-terminating
```
--------------------------------
### Custom Symbol Interpretation in Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
Explains how to customize symbol creation during the reading process using `eclector.reader:interpret-symbol`. This example shows a client that tracks all symbols read, demonstrating extensibility for symbol processing.
```Common Lisp
;; Custom symbol interpretation that tracks all symbols read
(defvar *symbols-read* '())
(defclass tracking-client ()
())
(defmethod eclector.reader:interpret-symbol
((client tracking-client) input-stream package-indicator symbol-name internp)
(let ((symbol (call-next-method)))
(push symbol *symbols-read*)
symbol))
;; Use the tracking client
(let ((eclector.reader:*client* (make-instance 'tracking-client))
(*symbols-read* '()))
(eclector.reader:read-from-string "(foo bar:baz)")
(reverse *symbols-read*))
;; => (FOO BAR:BAZ)
```
--------------------------------
### S-Expression Comments with Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
Illustrates how to implement and use S-expression comments (`#N;`) similar to SRFI 62. This involves installing a dispatch macro character and demonstrates commenting out single or multiple expressions.
```Common Lisp
;; Install s-expression comment reader macro
(let ((rt (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
(eclector.readtable:set-dispatch-macro-character
rt ## #\;
'eclector.syntax-extensions.s-expression-comment:s-expression-comment)
(let ((eclector.reader:*readtable* rt))
;; Comment out one expression
(eclector.reader:read-from-string "(a #;b c)")))
;; => (A C)
;; Comment out multiple expressions with numeric argument
(let ((rt (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
(eclector.readtable:set-dispatch-macro-character
rt ## #\;
'eclector.syntax-extensions.s-expression-comment:s-expression-comment)
(let ((eclector.reader:*readtable* rt))
(eclector.reader:read-from-string "(a #3;b c d e)")))
;; => (A E) ; comments out b, c, d
```
--------------------------------
### S-expression Comments Example (Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/code/syntax-extensions/README.md
Illustrates the use of S-expression comments, a syntax extension loosely based on SRFI 62. This implementation allows for commenting out a specified number of s-expressions using a numeric infix argument, such as `#2;` to comment out two s-expressions. It leverages Eclector protocols for better error messages and parse results.
```lisp
(frob r1 r2 :k3 4 #4; :k5 6 :k6 7)
```
--------------------------------
### Custom Character Name Resolution in Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
Details how to customize the resolution of character names in `#\` syntax using `eclector.reader:find-character`. The example introduces custom character names like `#\EURO_SIGN` and `#\CHECK_MARK`.
```Common Lisp
;; Add custom character names
(defclass extended-char-client ()
())
(defmethod eclector.reader:find-character
((client extended-char-client) (name string))
(cond ((string-equal name "euro") #\EURO_SIGN)
((string-equal name "check") #\CHECK_MARK)
(t (call-next-method))))
(let ((eclector.reader:*client* (make-instance 'extended-char-client)))
(eclector.reader:read-from-string "#\euro"))
;; => #\EURO_SIGN
```
--------------------------------
### Read Lisp Object from String with Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
The `eclector.reader:read-from-string` function reads a Lisp object from a string and returns the object along with the position where reading stopped. It supports basic usage, specifying start and end positions, complex literal syntax, and preserving whitespace.
```common-lisp
;; Basic usage
(eclector.reader:read-from-string "(foo bar)")
;; => (FOO BAR)
;; => 9
;; Reading with start and end positions
(eclector.reader:read-from-string "prefix (data) suffix"
:start 7 :end 13)
;; => (DATA)
;; => 13
;; Complex literal syntax
(eclector.reader:read-from-string "#C(1 1)")
;; => #C(1 1)
;; => 7
;; Reading with preserve-whitespace
(eclector.reader:read-from-string "symbol next"
:preserve-whitespace t)
;; => SYMBOL
;; => 6 ; stops at first whitespace after symbol
```
--------------------------------
### Parse Results: Concrete and Abstract Syntax Trees
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Illustrates the Concrete Syntax Tree (CST) and Abstract Syntax Tree (AST) generated during parsing.
```APIDOC
## Parse Results: Concrete and Abstract Syntax Trees
### Description
This section visually represents the Concrete Syntax Tree (CST) and Abstract Syntax Tree (AST) that are produced by the Eclector parser.
### Method
N/A (Visual representation)
### Endpoint
N/A
### Parameters
None
### Request Example
N/A
### Response
#### Success Response (200)
Visual diagrams of CST and AST.
#### Response Example


```
--------------------------------
### Naive Float Construction Logic (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Illustrates a naive implementation for constructing floating-point numbers in Common Lisp. It calculates the magnitude based on mantissa and exponent, with a conditional check for the exponent's sign.
```Common Lisp
(let ((magnitude (* (+ (funcall decimal-mantissa)
(/ (funcall fraction-numerator)
fraction-denominator))
(if exponentp
(expt 10 (* exponent-sign (funcall exponent)))
1))))
(return-from interpret-token
(* sign (coerce magnitude type))))
```
--------------------------------
### Customization: Sandboxing
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Details extension points for mitigating threats related to read-time evaluation, structure constructors, and uncontrolled interning.
```APIDOC
## Customization: Sandboxing
### Description
Identifies threats and corresponding extension points for sandboxing the reader, including read-time evaluation, structure construction, and symbol interning.
### Method
`defgeneric`
### Endpoints
- `eclector.reader:evaluate-expression`
- `eclector.reader:make-structure-instance`
- `eclector.reader:interpret-symbol`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
```lisp
(defgeneric eclector.reader:evaluate-expression (client expression))
(defgeneric eclector.reader:make-structure-instance (client constructor-name slots-plist))
(defgeneric eclector.reader:interpret-symbol (client name package-marker))
```
### Response
#### Success Response (200)
N/A (These are function definitions)
#### Response Example
N/A
```
--------------------------------
### Configure Reveal.js Presentation
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
This JavaScript code snippet configures the reveal.js presentation library. It sets various options such as controls, progress indicators, history, slide numbering, and transitions. It also includes a dependency for the notes plugin.
```javascript
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: false,
slideNumber: 'c',
rollingLinks: false,
keyboard: true,
mouseWheel: false,
fragmentInURL: false,
hashOneBasedIndex: false,
pdfSeparateFragments: true,
overview: true,
margin: 0.00,
theme: Reveal.getQueryHash().theme,
transition: Reveal.getQueryHash().transition || 'slide',
transitionSpeed: 'default',
dependencies: [
{
src: './reveal.js/plugin/notes/notes.js',
async: true,
condition: function() {
return !!document.body.classList;
}
}
]
});
```
--------------------------------
### Basic Reading with Eclector
Source: https://github.com/s-expressionists/eclector/blob/master/README.md
Demonstrates the basic usage of the eclector reader to read S-expressions from a string stream or directly from a string. It shows how to read a list and a complex number.
```Common Lisp
(with-input-from-string (stream "(1 2 3)")
(eclector.reader:read stream))
; => (1 2 3)
```
```Common Lisp
(eclector.reader:read-from-string "#C(1 1)")
; => #C(1 1) 7
```
--------------------------------
### Concrete Syntax Tree Generation with Eclector
Source: https://github.com/s-expressionists/eclector/blob/master/README.md
Demonstrates the use of the `eclector.concrete-syntax-tree` system to produce concrete syntax tree (CST) instances. This variant of the reader generates CST objects representing the parsed S-expression.
```Common Lisp
(eclector.concrete-syntax-tree:read-from-string "(1 2 3)")
; => # 7 NIL
```
--------------------------------
### Query and Bind Reader State with Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
Demonstrates how to query and dynamically bind reader state aspects such as the current package and read base using `eclector.reader:state-value` and `eclector.reader:call-with-state-value`. This allows for fine-grained control over the reading process.
```Common Lisp
;; Query current state values
(eclector.reader:state-value eclector.reader:*client* '*package*)
;; => #
(eclector.reader:state-value eclector.reader:*client* '*read-base*)
;; => 10
;; Dynamically bind state values during reading
(defmethod eclector.reader:call-with-state-value
((client my-client) thunk (aspect (eql '*read-base*)) value)
(format t "Reading with base ~D~%" value)
(call-next-method))
;; Read in hexadecimal
(eclector.reader:call-with-state-value
eclector.reader:*client*
(lambda ()
(eclector.reader:read-from-string "FF"))
'*read-base*
16)
;; => 255
```
--------------------------------
### Error Recovery with Eclector
Source: https://github.com/s-expressionists/eclector/blob/master/README.md
Illustrates eclector's error recovery capabilities. It shows how to use `handler-bind` with the `eclector.reader:recover` restart to handle errors during reading and continue processing.
```Common Lisp
(handler-bind ((error (lambda (condition)
(let ((restart (find-restart 'eclector.reader:recover)))
(format t "Recovering from error:~%~2@T~A~%using~%~2@T~A~%"
condition restart))
(eclector.reader:recover))))
(eclector.reader:read-from-string "`(::foo ,a)"))
; Output demonstrates recovery from multiple errors:
; Recovering from error:
; A symbol token must not start with two package markers as in ::name.
; using
; Treat the character as if it had been escaped.
; Recovering from error:
; While reading unquote, expected an object when input ended.
; using
; Use NIL in place of the missing object.
; Recovering from error:
; While reading list, expected the character ) when input ended.
; using
; Return a list of the already read elements.
; => (ECLECTOR.READER:QUASIQUOTE (:FOO (ECLECTOR.READER:UNQUOTE NIL))) 9
```
--------------------------------
### Reader Protocol Functions for Symbols and Packages (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Lists key functions that form a protocol for handling custom symbol and package representations within Eclector's reader. These functions are crucial for extending Eclector's compatibility.
```Common Lisp
eclector.reader:symbolp
eclector.reader:packagep
eclector.reader:find-symbol
eclector.reader:intern
```
--------------------------------
### Customization: Architecture
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines generic functions for customizing reader operations by accepting a client parameter.
```APIDOC
## Customization: Architecture
### Description
Express all operations performed by the reader as a set of protocols in which each generic function accepts a client parameter.
### Method
`defgeneric`
### Endpoints
- `eclector.reader:interpret-symbol-token`
- `eclector.reader:evaluate-feature-expression`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
```lisp
(defgeneric eclector.reader:interpret-symbol-token (client input-stream token position-package-marker-1 position-package-marker-2))
(defgeneric eclector.reader:evaluate-feature-expression (client feature-expression))
```
### Response
#### Success Response (200)
N/A (These are function definitions)
#### Response Example
N/A
```
--------------------------------
### Skipped Input: Architecture
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines how the reader notifies the client about non-object input and provides a `read`-style function that does not skip them.
```APIDOC
## Skipped Input: Architecture
### Description
Notify the client when non-objects are encountered in the input and provide a `read`-style function that does not skip over them.
### Method
`defgeneric`
### Endpoints
- `eclector.reader:note-skipped-input`
- `eclector.reader:call-as-top-level-read`
- `eclector.reader:read-maybe-nothing`
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
None
### Request Example
```lisp
(defgeneric eclector.reader:note-skipped-input (client input-stream reason))
(defgeneric eclector.reader:call-as-top-level-read (client thunk input-stream eof-error-p eof-value preserve-whitespace-p))
(defgeneric eclector.reader:read-maybe-nothing (client input-stream eof-error-p eof-value))
```
### Response
#### Success Response (200)
N/A (These are function definitions)
#### Response Example
N/A
```
--------------------------------
### Extended Package Prefix Syntax in Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
Shows how to enable and use the extended package prefix syntax (PACKAGE::EXPR) for specifying package contexts during reading. This feature is implemented via `eclector.syntax-extensions.extended-package-prefix:extended-package-prefix-syntax-mixin`.
```Common Lisp
;; Enable extended package prefix syntax
(defclass my-ext-client
(eclector.syntax-extensions.extended-package-prefix:extended-package-prefix-syntax-mixin)
())
(let ((eclector.reader:*client* (make-instance 'my-ext-client)))
(eclector.reader:read-from-string "cl-user::(foo bar baz)"))
;; => (CL-USER::FOO CL-USER::BAR CL-USER::BAZ)
;; Works with other syntax
(let ((eclector.reader:*client* (make-instance 'my-ext-client)))
(eclector.reader:read-from-string "keyword::#(a b c)"))
;; => #(:A :B :C)
```
--------------------------------
### Define Generic Function for Structure Instance Creation (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines the generic function `make-structure-instance` in the `eclector.reader` package. This function is an extension point for customizing how structure instances are constructed, which is crucial for sandboxing and controlling object creation during parsing.
```common-lisp
(defgeneric eclector.reader:make-structure-instance (client))
```
--------------------------------
### Reading Concrete Syntax Trees (CST)
Source: https://context7.com/s-expressionists/eclector/llms.txt
Produces concrete syntax tree (CST) objects that preserve the input's structure along with source locations. This functionality relies on the 'concrete-syntax-tree' library and is useful for detailed structural analysis of Lisp code.
```lisp
;; Read a simple list as CST
(eclector.concrete-syntax-tree:read-from-string "(1 2 3)")
;; => #
;; => 7
;; => NIL
;; Access CST properties
(let ((cst (eclector.concrete-syntax-tree:read-from-string "(a b)")))
(values (cst:raw cst) ; The underlying value
(cst:source cst) ; Source location
(cst:raw (cst:first cst)) ; First element
(cst:raw (cst:rest cst)))) ; Rest of list
;; => (A B)
;; => (0 . 5)
;; => A
;; => (B)
;; CSTs preserve structure for dotted lists
(let ((cst (eclector.concrete-syntax-tree:read-from-string "(a . b)")))
(values (cst:consp cst)
(cst:raw (cst:first cst))
(cst:raw (cst:rest cst))))
;; => T
;; => A
;; => B
```
--------------------------------
### Define Generic Function for Float Construction (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines a generic function `make-float` in Common Lisp, intended to provide a more robust or client-defined method for constructing floating-point numbers with various components like sign, mantissa, and exponent.
```Common Lisp
(defgeneric make-float
(client type
sign decimal-mantissa fraction-numerator fraction-denominator
exponent-sign exponent))
```
--------------------------------
### Configuring Dispatch Macro Characters
Source: https://context7.com/s-expressionists/eclector/llms.txt
Configures dispatch macro characters, such as '#', with sub-character handlers. This enables the creation of custom syntax for specific prefixes, like defining a '#!expr' macro for debugging purposes.
```lisp
;; Create a custom dispatch macro #!expr for debugging
(let ((rt (eclector.readtable:copy-readtable eclector.reader:*readtable*)))
(eclector.readtable:set-dispatch-macro-character
rt ## #!
(lambda (stream sub-char numeric-arg)
(declare (ignore sub-char))
(let ((expr (eclector.reader:read stream t nil t)))
`(debug-print ,numeric-arg ',expr ,expr))))
(let ((eclector.reader:*readtable* rt))
(eclector.reader:read-from-string "#!x")))
;; => (DEBUG-PRINT NIL 'X X)
;; With numeric argument
(let ((eclector.reader:*readtable* rt))
(eclector.reader:read-from-string "#3!form"))
;; => (DEBUG-PRINT 3 'FORM FORM)
```
--------------------------------
### Define Generic Functions for Parse Result Construction (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines generic functions for creating expression results and skipped input results, incorporating source position information. These functions are part of Eclector's parsing architecture.
```Common Lisp
(defgeneric eclector.parse-result:source-position (client stream))
(defgeneric eclector.parse-result:make-expression-result (client result children source))
(defgeneric eclector.parse-result:make-skipped-input-result (client stream reason source))
```
--------------------------------
### Define Generic Function for Reading Maybe Nothing (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines the generic function `read-maybe-nothing` in the `eclector.reader` package. This function is part of the 'Skipped Input' architecture, allowing reads that might encounter nothing (e.g., end of file) without necessarily signaling an error, accepting a client, input stream, and error handling parameters.
```common-lisp
(defgeneric eclector.reader:read-maybe-nothing
(client input-stream eof-error-p eof-value))
```
--------------------------------
### Custom Parse Results with Eclector
Source: https://github.com/s-expressionists/eclector/blob/master/README.md
Shows how to customize the parse results produced by eclector. It defines a custom client class `my-client` that overrides `make-expression-result` and `make-skipped-input-result` to control the output format.
```Common Lisp
(defclass my-client (eclector.parse-result:parse-result-client)
())
(defmethod eclector.parse-result:make-expression-result
((client my-client) (result t) (children t) (source t))
(list :result result :source source :children children))
(defmethod eclector.parse-result:make-skipped-input-result
((client my-client) (stream t) (reason t) (children t) (source t))
(list :reason reason :source source :children children))
(with-input-from-string (stream "(1 #|comment|# \"string\")")
(eclector.parse-result:read (make-instance 'my-client) stream))
```
--------------------------------
### Read Lisp Expressions with Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
The `eclector.reader:read` function is the primary entry point for reading Lisp expressions from a stream. It functions similarly to the standard Common Lisp `read` but utilizes Eclector's customizable reader. It supports basic reading, multiple values with EOF handling, and recursive reading within reader macros.
```common-lisp
;; Basic reading from a string stream
(with-input-from-string (stream "(1 2 3)")
(eclector.reader:read stream))
;; => (1 2 3)
;; Reading multiple values with EOF handling
(with-input-from-string (stream "hello world")
(values (eclector.reader:read stream)
(eclector.reader:read stream nil :eof)))
;; => HELLO
;; => WORLD
;; Recursive reading within reader macros
(defmethod eclector.reader:call-reader-macro
((client my-client) stream char readtable)
(let ((object (eclector.reader:read stream t nil t))) ; recursive-p = t
(list :wrapped object)))
```
--------------------------------
### Define Generic Function for Notifying Skipped Input (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines the generic function `note-skipped-input` within the `eclector.reader` package. This function is designed to notify the client when non-object input is encountered, allowing for custom handling of skipped data according to the 'Skipped Input: Architecture Idea 2'.
```common-lisp
(defgeneric eclector.reader:note-skipped-input (client input-stream reason))
```
--------------------------------
### Define Generic Function for Top-Level Read Call (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines the generic function `call-as-top-level-read` in the `eclector.reader` package. This function provides a `read`-style interface that does not skip over non-object input, as described in 'Skipped Input: Architecture Idea 2'. It accepts a client, a thunk, an input stream, and error handling parameters.
```common-lisp
(defgeneric eclector.reader:call-as-top-level-read
(client thunk input-stream eof-error-p eof-value preserve-whitespace-p))
```
--------------------------------
### Custom Parse Results with Source Location Tracking
Source: https://context7.com/s-expressionists/eclector/llms.txt
Reads expressions and produces custom parse results with source location tracking. Requires a client object implementing the parse result protocol. This allows for detailed analysis of parsed code, including the exact source span of each element.
```lisp
;; Define a custom parse result client
(defclass my-client (eclector.parse-result:parse-result-client) ())
(defmethod eclector.parse-result:make-expression-result
((client my-client) (result t) (children t) (source t))
(list :result result :source source :children children))
(defmethod eclector.parse-result:make-skipped-input-result
((client my-client) (stream t) (reason t) (children t) (source t))
(list :skipped reason :source source))
;; Read with parse results
(with-input-from-string (stream "(1 2 3)")
(eclector.parse-result:read (make-instance 'my-client) stream))
;; => (:RESULT (1 2 3)
;; :SOURCE (0 . 7)
;; :CHILDREN ((:RESULT 1 :SOURCE (1 . 2) :CHILDREN NIL)
;; (:RESULT 2 :SOURCE (3 . 4) :CHILDREN NIL)
;; (:RESULT 3 :SOURCE (5 . 6) :CHILDREN NIL)))
;; Read with comments preserved as skipped input
(with-input-from-string (stream "(a ;comment
b)")
(eclector.parse-result:read (make-instance 'my-client) stream))
;; => includes :SKIPPED :LINE-COMMENT for the comment
```
--------------------------------
### Define Generic Function for Symbol Token Interpretation (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines a generic function `interpret-symbol-token` within the `eclector.reader` package. This function is designed to interpret symbol tokens during the reading process, accepting a client, input stream, token, and package marker positions as arguments. It's a key part of Eclector's extensibility for customizing how symbols are read.
```common-lisp
(defgeneric eclector.reader:interpret-symbol-token (client input-stream
token
position-package-marker-1
position-package-marker-2))
```
--------------------------------
### Performance Test: Reading S-expressions (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
A performance test that repeatedly reads a complex s-expression string using `read-from-string`. This snippet is used to compare the performance of different Common Lisp implementations.
```Common Lisp
(time (loop :repeat 10000
:do (read-from-string "(1 (2 3) #+sbcl #1=\"foo\" \`(,#1#))")))
```
--------------------------------
### Error Recovery in Eclector Reader
Source: https://context7.com/s-expressionists/eclector/llms.txt
Eclector implements error recovery using a restart mechanism, allowing the reading process to continue after encountering syntax errors. This enables the detection and handling of multiple errors in a single pass, with options to recover by skipping, substituting, or collecting errors.
```common-lisp
;; Recover from multiple errors in one read operation
(handler-bind
((error (lambda (condition)
(format t "Error: ~A~%" condition)
(let ((restart (find-restart 'eclector.reader:recover)))
(when restart
(format t "Recovering with: ~A~%" restart)
(eclector.reader:recover))))))
(eclector.reader:read-from-string "`(::foo ,`))
;; Output:
;; Error: A symbol token must not start with two package markers
;; Recovering with: Treat the character as if it had been escaped.
;; Error: While reading unquote, expected an object when input ended.
;; Recovering with: Use NIL in place of the missing object.
;; Error: While reading list, expected ) when input ended.
;; Recovering with: Return a list of the already read elements.
;; => (ECLECTOR.READER:QUASIQUOTE (:FOO (ECLECTOR.READER:UNQUOTE NIL)))
;; Collect all errors while reading
(let ((errors '()))
(handler-bind
((error (lambda (c)
(push c errors)
(eclector.reader:recover))))
(eclector.reader:read-from-string "(#C(a b) #\invalid-char)"))
(length errors))
;; => 2 ; collected two errors
```
--------------------------------
### Define Generic Function for Expression Evaluation (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines the generic function `evaluate-expression` in the `eclector.reader` package. This function is central to Eclector's sandboxing capabilities, allowing for controlled evaluation of expressions read from input. It is used to mitigate risks associated with read-time evaluation.
```common-lisp
(defgeneric eclector.reader:evaluate-expression (client))
```
--------------------------------
### Convenience Function for Reading Parse Results from String
Source: https://context7.com/s-expressionists/eclector/llms.txt
A convenience function that simplifies reading parse results directly from a string. It utilizes a provided client object to format the parse results.
```lisp
(defclass simple-client (eclector.parse-result:parse-result-client) ())
(defmethod eclector.parse-result:make-expression-result
((client simple-client) result children source)
`(:expr ,result :src ,source))
(eclector.parse-result:read-from-string
(make-instance 'simple-client)
"(defun foo (x) x)")
;; => (:EXPR (DEFUN FOO (X) X) :SRC (0 . 17))
;; => 17 ; position
;; => NIL ; orphan results
```
--------------------------------
### Define Generic Function for Symbol Interpretation (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines the generic function `interpret-symbol` in the `eclector.reader` package. This function provides an interface for customizing how symbols are interpreted, addressing the threat of uncontrolled interning and enhancing security in sandboxed environments.
```common-lisp
(defgeneric eclector.reader:interpret-symbol (client))
```
--------------------------------
### Define Generic Function for Feature Expression Evaluation (Common Lisp)
Source: https://github.com/s-expressionists/eclector/blob/master/documentation/presentation-slides/slides.html
Defines a generic function `evaluate-feature-expression` within the `eclector.reader` package. This function is intended for evaluating feature expressions, taking a client and the feature expression itself as arguments. It plays a role in conditional compilation and feature detection within the Lisp environment.
```common-lisp
(defgeneric eclector.reader:evaluate-feature-expression (client feature-expression))
```
--------------------------------
### Read Delimited List with Eclector
Source: https://context7.com/s-expressionists/eclector/llms.txt
The `eclector.reader:read-delimited-list` function reads objects from a stream until a specified delimiter character is encountered, returning them as a list. This is useful for implementing custom list readers, such as bracketed lists.
```common-lisp
;; Custom list reader macro using read-delimited-list
(defun my-bracket-reader (stream char)
(declare (ignore char))
(cons :bracketed
(eclector.reader:read-delimited-list #\] stream t)))
;; Register the macro character
(eclector.readtable:set-macro-character
eclector.reader:*readtable*
#[ #'my-bracket-reader)
;; Usage
(eclector.reader:read-from-string "[a b c]")
;; => (:BRACKETED A B C)
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.