forked from mabragor/esrap-liquid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
example-very-context-sensitive.lisp
69 lines (48 loc) · 1.85 KB
/
example-very-context-sensitive.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
;;;; Esrap example: grammar, in which context is determined by a natural number
(require :esrap-liquid)
(defpackage :very-context-sensitive
(:use :cl :esrap-liquid))
(in-package :very-context-sensitive)
(enable-read-macro-tokens)
(defparameter indent 0 "Indent that is stripped from all lines.")
(defrule spaces ()
(length (times #\space)))
(defun indented-p (len)
(>= len indent))
(defrule indented-spaces ()
(- (pred #'indented-p spaces)
indent))
(defrule digit ()
(character-ranges (#\0 #\9)))
(defrule indent-spec-line ()
(parse-integer (text (progm (progn (v spaces) (v "|"))
(postimes digit)
(progn (v "|") (v spaces) (v #\newline))))))
(defrule indented-line ()
(prog1 (text (make-string (v indented-spaces) :initial-element #\space)
(times (!! #\newline)))
(v #\newline)))
(defun more-indented-block-p (explicit-block)
(>= (caddr explicit-block)
indent))
(defrule explicit-indented-block ()
(let ((indent indent-spec-line))
`(expl-block :indent ,indent
:contents ,(times (|| (pred #'more-indented-block-p
explicit-indented-block)
(progn (! indent-spec-line)
indented-line))))))
(defrule explicit-blocks ()
(postimes explicit-indented-block))
;; (defrule implicit-indented-block (wrap ""
;; (* (and (! indent-spec-line)
;; indented-line)))
;; (:wrap-around (let ((indent 0))
;; (call-parser)))
;; (:lambda (lst)
;; (mapcar #'cadr lst)))
;; (defrule implicit-blocks (+ implicit-indented-block))
;; (defrule indented-block (or implicit-indented-block
;; explicit-indented-block))
;; (defrule blocks (* indented-block))
;; (defrule multi-spaces (+ spaces))