### 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 ![cst.png](images/cst.png) ![ast.png](images/ast.png) ``` -------------------------------- ### 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.