mes: Remove PEG.
PEG is not used and mostly broken. * mes/module/mes/peg.mes, mes/module/mes/peg/cache.scm, mes/module/mes/peg/codegen.scm, mes/module/mes/peg/simplify-tree.scm, mes/module/mes/peg/string-peg.scm, mes/module/mes/peg/using-parsers.scm, tests/peg.test: Remove. * AUTHORS: Remove mention.
This commit is contained in:
parent
ed62c40cc6
commit
94643f8361
3
AUTHORS
3
AUTHORS
|
@ -56,9 +56,6 @@ module/mes/getopt-long.scm
|
|||
Optargs from Guile
|
||||
mes/module/mes/optargs.scm
|
||||
|
||||
PEG from Guile
|
||||
mes/module/mes/peg/
|
||||
|
||||
Pmatch from Guile
|
||||
mes/module/system/base/pmatch.scm
|
||||
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
;;; -*-scheme-*-
|
||||
|
||||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright © 2016,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; peg.mes is loaded after syntax-case: psyntax. It provides PEG
|
||||
;;; from Guile-2.1.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(mes-use-module (mes let))
|
||||
(mes-use-module (mes scm))
|
||||
(mes-use-module (mes guile))
|
||||
(mes-use-module (mes pretty-print))
|
||||
(mes-use-module (mes psyntax))
|
||||
(mes-use-module (srfi srfi-13))
|
||||
;;(mes-use-module (srfi srfi-9-psyntax))
|
||||
;;(mes-use-module (srfi srfi-9))
|
||||
(mes-use-module (mes pmatch))
|
||||
(include-from-path "mes/peg/cache.scm")
|
||||
(include-from-path "mes/peg/codegen.scm")
|
||||
(include-from-path "mes/peg/string-peg.scm")
|
||||
(include-from-path "mes/peg/using-parsers.scm")
|
||||
(include-from-path "mes/peg/simplify-tree.scm")
|
|
@ -1,47 +0,0 @@
|
|||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Taken from GNU Guile
|
||||
;;; cache.scm --- cache the results of parsing
|
||||
|
||||
(define-module (ice-9 peg cache)
|
||||
#:export (cg-cached-parser))
|
||||
|
||||
;; The results of parsing using a nonterminal are cached. Think of it like a
|
||||
;; hash with no conflict resolution. Process for deciding on the cache size
|
||||
;; wasn't very scientific; just ran the benchmarks and stopped a little after
|
||||
;; the point of diminishing returns on my box.
|
||||
(define *cache-size* 512)
|
||||
|
||||
(define (make-cache)
|
||||
(make-vector *cache-size* #f))
|
||||
|
||||
;; given a syntax object which is a parser function, returns syntax
|
||||
;; which, if evaluated, will become a parser function that uses a cache.
|
||||
(define (cg-cached-parser parser)
|
||||
#`(let ((cache (make-cache)))
|
||||
(lambda (str strlen at)
|
||||
(let* ((vref (vector-ref cache (modulo at *cache-size*))))
|
||||
;; Check to see whether the value is cached.
|
||||
(if (and vref (eq? (car vref) str) (= (cadr vref) at))
|
||||
(caddr vref);; If it is return it.
|
||||
(let ((fres ;; Else calculate it and cache it.
|
||||
(#,parser str strlen at)))
|
||||
(vector-set! cache (modulo at *cache-size*)
|
||||
(list str at fres))
|
||||
fres))))))
|
|
@ -1,361 +0,0 @@
|
|||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright (C) 2011 Free Software Foundation, Inc.
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Taken from GNU Guile
|
||||
|
||||
;;; codegen.scm --- code generation for composable parsers
|
||||
|
||||
(define-module (ice-9 peg codegen)
|
||||
#:export (compile-peg-pattern wrap-parser-for-users add-peg-compiler!)
|
||||
#:use-module (ice-9 pretty-print)
|
||||
#:use-module (system base pmatch))
|
||||
|
||||
(define-syntax single?
|
||||
(syntax-rules ()
|
||||
;;"Return #t if X is a list of one element."
|
||||
((_ x)
|
||||
(pmatch x
|
||||
((_) #t)
|
||||
(else #f)))))
|
||||
|
||||
(define-syntax single-filter
|
||||
(syntax-rules ()
|
||||
;;"If EXP is a list of one element, return the element. Otherwise return EXP."
|
||||
((_ exp)
|
||||
(pmatch exp
|
||||
((,elt) elt)
|
||||
(,elts elts)))))
|
||||
|
||||
(define-syntax push-not-null!
|
||||
(syntax-rules ()
|
||||
;;"If OBJ is non-null, push it onto LST, otherwise do nothing."
|
||||
((_ lst obj)
|
||||
(if (not (null? obj))
|
||||
(push! lst obj)))))
|
||||
|
||||
(define-syntax push!
|
||||
(syntax-rules ()
|
||||
;;"Push an object onto a list."
|
||||
((_ lst obj)
|
||||
(set! lst (cons obj lst)))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;; CODE GENERATORS
|
||||
;; These functions generate scheme code for parsing PEGs.
|
||||
;; Conventions:
|
||||
;; accum: (all name body none)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Code we generate will have a certain return structure depending on how we're
|
||||
;; accumulating (the ACCUM variable).
|
||||
(define (cg-generic-ret accum name body-uneval at)
|
||||
;; name, body-uneval and at are syntax
|
||||
#`(let ((body #,body-uneval))
|
||||
#,(cond
|
||||
((and (eq? accum 'all) name)
|
||||
#`(list #,at
|
||||
(cond
|
||||
((not (list? body)) (list '#,name body))
|
||||
((null? body) '#,name)
|
||||
((symbol? (car body)) (list '#,name body))
|
||||
(else (cons '#,name body)))))
|
||||
((eq? accum 'name)
|
||||
#`(list #,at '#,name))
|
||||
((eq? accum 'body)
|
||||
#`(list #,at
|
||||
(cond
|
||||
((single? body) (car body))
|
||||
(else body))))
|
||||
((eq? accum 'none)
|
||||
#`(list #,at '()))
|
||||
(else
|
||||
(begin
|
||||
(pretty-print `(cg-generic-ret-error ,accum ,name ,body-uneval ,at))
|
||||
(pretty-print "Defaulting to accum of none.\n")
|
||||
#`(list #,at '()))))))
|
||||
|
||||
;; The short name makes the formatting below much easier to read.
|
||||
(define cggr cg-generic-ret)
|
||||
|
||||
;; Generates code that matches a particular string.
|
||||
;; E.g.: (cg-string syntax "abc" 'body)
|
||||
(define (cg-string pat accum)
|
||||
(let ((plen (string-length pat)))
|
||||
#`(lambda (str len pos)
|
||||
(let ((end (+ pos #,plen)))
|
||||
(and (<= end len)
|
||||
(string= str #,pat pos end)
|
||||
#,(case accum
|
||||
((all) #`(list end (list 'cg-string #,pat)))
|
||||
((name) #`(list end 'cg-string))
|
||||
((body) #`(list end #,pat))
|
||||
((none) #`(list end '()))
|
||||
(else (error "bad accum" accum))))))))
|
||||
|
||||
;; Generates code for matching any character.
|
||||
;; E.g.: (cg-peg-any syntax 'body)
|
||||
(define (cg-peg-any accum)
|
||||
#`(lambda (str len pos)
|
||||
(and (< pos len)
|
||||
#,(case accum
|
||||
((all) #`(list (1+ pos)
|
||||
(list 'cg-peg-any (substring str pos (1+ pos)))))
|
||||
((name) #`(list (1+ pos) 'cg-peg-any))
|
||||
((body) #`(list (1+ pos) (substring str pos (1+ pos))))
|
||||
((none) #`(list (1+ pos) '()))
|
||||
(else (error "bad accum" accum))))))
|
||||
|
||||
;; Generates code for matching a range of characters between start and end.
|
||||
;; E.g.: (cg-range syntax #\a #\z 'body)
|
||||
(define (cg-range pat accum)
|
||||
(syntax-case pat ()
|
||||
((start end)
|
||||
(if (not (and (char? (syntax->datum #'start))
|
||||
(char? (syntax->datum #'end))))
|
||||
(error "range PEG should have characters after it; instead got"
|
||||
#'start #'end))
|
||||
#`(lambda (str len pos)
|
||||
(and (< pos len)
|
||||
(let ((c (string-ref str pos)))
|
||||
(and (char>=? c start)
|
||||
(char<=? c end)
|
||||
#,(case accum
|
||||
((all) #`(list (1+ pos) (list 'cg-range (string c))))
|
||||
((name) #`(list (1+ pos) 'cg-range))
|
||||
((body) #`(list (1+ pos) (string c)))
|
||||
((none) #`(list (1+ pos) '()))
|
||||
(else (error "bad accum" accum))))))))))
|
||||
|
||||
;; Generate code to match a pattern and do nothing with the result
|
||||
(define (cg-ignore pat accum)
|
||||
(syntax-case pat ()
|
||||
((inner)
|
||||
(compile-peg-pattern #'inner 'none))))
|
||||
|
||||
(define (cg-capture pat accum)
|
||||
(syntax-case pat ()
|
||||
((inner)
|
||||
(compile-peg-pattern #'inner 'body))))
|
||||
|
||||
;; Filters the accum argument to compile-peg-pattern for buildings like string
|
||||
;; literals (since we don't want to tag them with their name if we're doing an
|
||||
;; "all" accum).
|
||||
(define (builtin-accum-filter accum)
|
||||
(cond
|
||||
((eq? accum 'all) 'body)
|
||||
((eq? accum 'name) 'name)
|
||||
((eq? accum 'body) 'body)
|
||||
((eq? accum 'none) 'none)))
|
||||
(define baf builtin-accum-filter)
|
||||
|
||||
;; Top-level function builder for AND. Reduces to a call to CG-AND-INT.
|
||||
(define (cg-and clauses accum)
|
||||
#`(lambda (str len pos)
|
||||
(let ((body '()))
|
||||
#,(cg-and-int clauses (baf accum) #'str #'len #'pos #'body))))
|
||||
|
||||
;; Internal function builder for AND (calls itself).
|
||||
(define (cg-and-int clauses accum str strlen at body)
|
||||
(syntax-case clauses ()
|
||||
(()
|
||||
(cggr accum 'cg-and #`(reverse #,body) at))
|
||||
((first rest ...)
|
||||
#`(let ((res (#,(compile-peg-pattern #'first accum) #,str #,strlen #,at)))
|
||||
(and res
|
||||
;; update AT and BODY then recurse
|
||||
(let ((newat (car res))
|
||||
(newbody (cadr res)))
|
||||
(set! #,at newat)
|
||||
(push-not-null! #,body (single-filter newbody))
|
||||
#,(cg-and-int #'(rest ...) accum str strlen at body)))))))
|
||||
|
||||
;; Top-level function builder for OR. Reduces to a call to CG-OR-INT.
|
||||
(define (cg-or clauses accum)
|
||||
#`(lambda (str len pos)
|
||||
#,(cg-or-int clauses (baf accum) #'str #'len #'pos)))
|
||||
|
||||
;; Internal function builder for OR (calls itself).
|
||||
(define (cg-or-int clauses accum str strlen at)
|
||||
(syntax-case clauses ()
|
||||
(()
|
||||
#f)
|
||||
((first rest ...)
|
||||
#`(or (#,(compile-peg-pattern #'first accum) #,str #,strlen #,at)
|
||||
#,(cg-or-int #'(rest ...) accum str strlen at)))))
|
||||
|
||||
(define (cg-* args accum)
|
||||
(syntax-case args ()
|
||||
((pat)
|
||||
#`(lambda (str strlen at)
|
||||
(let ((body '()))
|
||||
(let lp ((end at) (count 0))
|
||||
(let* ((match (#,(compile-peg-pattern #'pat (baf accum))
|
||||
str strlen end))
|
||||
(new-end (if match (car match) end))
|
||||
(count (if (> new-end end) (1+ count) count)))
|
||||
(if (> new-end end)
|
||||
(push-not-null! body (single-filter (cadr match))))
|
||||
(if (and (> new-end end)
|
||||
#,#t)
|
||||
(lp new-end count)
|
||||
(let ((success #,#t))
|
||||
#,#`(and success
|
||||
#,(cggr (baf accum) 'cg-body
|
||||
#'(reverse body) #'new-end)))))))))))
|
||||
|
||||
(define (cg-+ args accum)
|
||||
(syntax-case args ()
|
||||
((pat)
|
||||
#`(lambda (str strlen at)
|
||||
(let ((body '()))
|
||||
(let lp ((end at) (count 0))
|
||||
(let* ((match (#,(compile-peg-pattern #'pat (baf accum))
|
||||
str strlen end))
|
||||
(new-end (if match (car match) end))
|
||||
(count (if (> new-end end) (1+ count) count)))
|
||||
(if (> new-end end)
|
||||
(push-not-null! body (single-filter (cadr match))))
|
||||
(if (and (> new-end end)
|
||||
#,#t)
|
||||
(lp new-end count)
|
||||
(let ((success #,#'(>= count 1)))
|
||||
#,#`(and success
|
||||
#,(cggr (baf accum) 'cg-body
|
||||
#'(reverse body) #'new-end)))))))))))
|
||||
|
||||
(define (cg-? args accum)
|
||||
(syntax-case args ()
|
||||
((pat)
|
||||
#`(lambda (str strlen at)
|
||||
(let ((body '()))
|
||||
(let lp ((end at) (count 0))
|
||||
(let* ((match (#,(compile-peg-pattern #'pat (baf accum))
|
||||
str strlen end))
|
||||
(new-end (if match (car match) end))
|
||||
(count (if (> new-end end) (1+ count) count)))
|
||||
(if (> new-end end)
|
||||
(push-not-null! body (single-filter (cadr match))))
|
||||
(if (and (> new-end end)
|
||||
#,#'(< count 1))
|
||||
(lp new-end count)
|
||||
(let ((success #,#t))
|
||||
#,#`(and success
|
||||
#,(cggr (baf accum) 'cg-body
|
||||
#'(reverse body) #'new-end)))))))))))
|
||||
|
||||
(define (cg-followed-by args accum)
|
||||
(syntax-case args ()
|
||||
((pat)
|
||||
#`(lambda (str strlen at)
|
||||
(let ((body '()))
|
||||
(let lp ((end at) (count 0))
|
||||
(let* ((match (#,(compile-peg-pattern #'pat (baf accum))
|
||||
str strlen end))
|
||||
(new-end (if match (car match) end))
|
||||
(count (if (> new-end end) (1+ count) count)))
|
||||
(if (> new-end end)
|
||||
(push-not-null! body (single-filter (cadr match))))
|
||||
(if (and (> new-end end)
|
||||
#,#'(< count 1))
|
||||
(lp new-end count)
|
||||
(let ((success #,#'(= count 1)))
|
||||
#,#`(and success
|
||||
#,(cggr (baf accum) 'cg-body #''() #'at)))))))))))
|
||||
|
||||
(define (cg-not-followed-by args accum)
|
||||
(syntax-case args ()
|
||||
((pat)
|
||||
#`(lambda (str strlen at)
|
||||
(let ((body '()))
|
||||
(let lp ((end at) (count 0))
|
||||
(let* ((match (#,(compile-peg-pattern #'pat (baf accum))
|
||||
str strlen end))
|
||||
(new-end (if match (car match) end))
|
||||
(count (if (> new-end end) (1+ count) count)))
|
||||
(if (> new-end end)
|
||||
(push-not-null! body (single-filter (cadr match))))
|
||||
(if (and (> new-end end)
|
||||
#,#'(< count 1))
|
||||
(lp new-end count)
|
||||
(let ((success #,#'(= count 1)))
|
||||
#,#`(if success
|
||||
#f
|
||||
#,(cggr (baf accum) 'cg-body #''() #'at)))))))))))
|
||||
|
||||
;; Association list of functions to handle different expressions as PEGs
|
||||
(define peg-compiler-alist '())
|
||||
|
||||
(define (add-peg-compiler! symbol function)
|
||||
(set! peg-compiler-alist
|
||||
(assq-set! peg-compiler-alist symbol function)))
|
||||
|
||||
(add-peg-compiler! 'range cg-range)
|
||||
(add-peg-compiler! 'ignore cg-ignore)
|
||||
(add-peg-compiler! 'capture cg-capture)
|
||||
(add-peg-compiler! 'and cg-and)
|
||||
(add-peg-compiler! 'or cg-or)
|
||||
(add-peg-compiler! '* cg-*)
|
||||
(add-peg-compiler! '+ cg-+)
|
||||
(add-peg-compiler! '? cg-?)
|
||||
(add-peg-compiler! 'followed-by cg-followed-by)
|
||||
(add-peg-compiler! 'not-followed-by cg-not-followed-by)
|
||||
|
||||
;; Takes an arbitrary expressions and accumulation variable, then parses it.
|
||||
;; E.g.: (compile-peg-pattern syntax '(and "abc" (or "-" (range #\a #\z))) 'all)
|
||||
(define (compile-peg-pattern pat accum)
|
||||
(syntax-case pat (peg-any)
|
||||
(peg-any
|
||||
(cg-peg-any (baf accum)))
|
||||
(sym (identifier? #'sym) ;; nonterminal
|
||||
#'sym)
|
||||
(str (string? (syntax->datum #'str)) ;; literal string
|
||||
(cg-string (syntax->datum #'str) (baf accum)))
|
||||
((name . args) (let* ((nm (syntax->datum #'name))
|
||||
(entry (assq-ref peg-compiler-alist nm)))
|
||||
(if entry
|
||||
(entry #'args accum)
|
||||
(error "Bad peg form" nm #'args
|
||||
"Not one of" (map car peg-compiler-alist)))))))
|
||||
|
||||
;; Packages the results of a parser
|
||||
(define (wrap-parser-for-users for-syntax parser accumsym s-syn)
|
||||
#`(lambda (str strlen at)
|
||||
(let ((res (#,parser str strlen at)))
|
||||
;; Try to match the nonterminal.
|
||||
(if res
|
||||
;; If we matched, do some post-processing to figure out
|
||||
;; what data to propagate upward.
|
||||
(let ((at (car res))
|
||||
(body (cadr res)))
|
||||
#,(cond
|
||||
((eq? accumsym 'name)
|
||||
#`(list at '#,s-syn))
|
||||
((eq? accumsym 'all)
|
||||
#`(list (car res)
|
||||
(cond
|
||||
((not (list? body))
|
||||
(list '#,s-syn body))
|
||||
((null? body) '#,s-syn)
|
||||
((symbol? (car body))
|
||||
(list '#,s-syn body))
|
||||
(else (cons '#,s-syn body)))))
|
||||
((eq? accumsym 'none) #`(list (car res) '()))
|
||||
(else #`(begin res))))
|
||||
;; If we didn't match, just return false.
|
||||
#f))))
|
|
@ -1,100 +0,0 @@
|
|||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Taken from GNU Guile
|
||||
|
||||
;;; simplify-tree.scm --- utility functions for the PEG parser
|
||||
|
||||
(define-module (ice-9 peg simplify-tree)
|
||||
#:export (keyword-flatten context-flatten string-collapse)
|
||||
#:use-module (system base pmatch))
|
||||
|
||||
(define-syntax single?
|
||||
(syntax-rules ()
|
||||
;;"Return #t if X is a list of one element."
|
||||
((_ x)
|
||||
(pmatch x
|
||||
((_) #t)
|
||||
(else #f)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;; POST-PROCESSING FUNCTIONS (TO CANONICALIZE MATCH TREES)
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Is everything in LST true?
|
||||
(define (andlst lst)
|
||||
(or (null? lst)
|
||||
(and (car lst) (andlst (cdr lst)))))
|
||||
|
||||
;; Is LST a list of strings?
|
||||
(define (string-list? lst)
|
||||
(and (list? lst) (not (null? lst))
|
||||
(andlst (map string? lst))))
|
||||
|
||||
;; Groups all strings that are next to each other in LST. Used in
|
||||
;; STRING-COLLAPSE.
|
||||
(define (string-group lst)
|
||||
(if (not (list? lst))
|
||||
lst
|
||||
(if (null? lst)
|
||||
'()
|
||||
(let ((next (string-group (cdr lst))))
|
||||
(if (not (string? (car lst)))
|
||||
(cons (car lst) next)
|
||||
(if (and (not (null? next))
|
||||
(list? (car next))
|
||||
(string? (caar next)))
|
||||
(cons (cons (car lst) (car next)) (cdr next))
|
||||
(cons (list (car lst)) next)))))))
|
||||
|
||||
|
||||
;; Collapses all the string in LST.
|
||||
;; ("a" "b" (c d) "e" "f") -> ("ab" (c d) "ef")
|
||||
(define (string-collapse lst)
|
||||
(if (list? lst)
|
||||
(let ((res (map (lambda (x) (if (string-list? x)
|
||||
(apply string-append x)
|
||||
x))
|
||||
(string-group (map string-collapse lst)))))
|
||||
(if (single? res) (car res) res))
|
||||
lst))
|
||||
|
||||
;; If LST is an atom, return (list LST), else return LST.
|
||||
(define (mklst lst)
|
||||
(if (not (list? lst)) (list lst) lst))
|
||||
|
||||
;; Takes a list and "flattens" it, using the predicate TST to know when to stop
|
||||
;; instead of terminating on atoms (see tutorial).
|
||||
(define (context-flatten tst lst)
|
||||
(if (or (not (list? lst)) (null? lst))
|
||||
lst
|
||||
(if (tst lst)
|
||||
(list lst)
|
||||
(apply append
|
||||
(map (lambda (x) (mklst (context-flatten tst x)))
|
||||
lst)))))
|
||||
|
||||
;; Takes a list and "flattens" it, using the list of keywords KEYWORD-LST to
|
||||
;; know when to stop at (see tutorial).
|
||||
(define (keyword-flatten keyword-lst lst)
|
||||
(context-flatten
|
||||
(lambda (x)
|
||||
(if (or (not (list? x)) (null? x))
|
||||
#t
|
||||
(member (car x) keyword-lst)))
|
||||
lst))
|
|
@ -1,275 +0,0 @@
|
|||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Taken from GNU Guile
|
||||
|
||||
;;; string-peg.scm --- representing PEG grammars as strings
|
||||
|
||||
(define-module (ice-9 peg string-peg)
|
||||
#:export (peg-as-peg
|
||||
define-peg-string-patterns
|
||||
peg-grammar)
|
||||
#:use-module (ice-9 peg using-parsers)
|
||||
#:use-module (ice-9 peg codegen)
|
||||
#:use-module (ice-9 peg simplify-tree))
|
||||
|
||||
;; Gets the left-hand depth of a list.
|
||||
(define (depth lst)
|
||||
(if (or (not (list? lst)) (null? lst))
|
||||
0
|
||||
(+ 1 (depth (car lst)))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;; Parse string PEGs using sexp PEGs.
|
||||
;; See the variable PEG-AS-PEG for an easier-to-read syntax.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Grammar for PEGs in PEG grammar.
|
||||
(define peg-as-peg
|
||||
"grammar <-- (nonterminal ('<--' / '<-' / '<') sp pattern)+
|
||||
pattern <-- alternative (SLASH sp alternative)*
|
||||
alternative <-- ([!&]? sp suffix)+
|
||||
suffix <-- primary ([*+?] sp)*
|
||||
primary <-- '(' sp pattern ')' sp / '.' sp / literal / charclass / nonterminal !'<'
|
||||
literal <-- ['] (!['] .)* ['] sp
|
||||
charclass <-- LB (!']' (CCrange / CCsingle))* RB sp
|
||||
CCrange <-- . '-' .
|
||||
CCsingle <-- .
|
||||
nonterminal <-- [a-zA-Z0-9-]+ sp
|
||||
sp < [ \t\n]*
|
||||
SLASH < '/'
|
||||
LB < '['
|
||||
RB < ']'
|
||||
")
|
||||
|
||||
(define-syntax define-sexp-parser
|
||||
(lambda (x)
|
||||
(syntax-case x ()
|
||||
((_ sym accum pat)
|
||||
(let* ((matchf (compile-peg-pattern #'pat (syntax->datum #'accum)))
|
||||
(accumsym (syntax->datum #'accum))
|
||||
(syn (wrap-parser-for-users x matchf accumsym #'sym)))
|
||||
#`(define sym #,syn))))))
|
||||
|
||||
(define-sexp-parser peg-grammar all
|
||||
(+ (and peg-nonterminal (or "<--" "<-" "<") peg-sp peg-pattern)))
|
||||
(define-sexp-parser peg-pattern all
|
||||
(and peg-alternative
|
||||
(* (and (ignore "/") peg-sp peg-alternative))))
|
||||
(define-sexp-parser peg-alternative all
|
||||
(+ (and (? (or "!" "&")) peg-sp peg-suffix)))
|
||||
(define-sexp-parser peg-suffix all
|
||||
(and peg-primary (* (and (or "*" "+" "?") peg-sp))))
|
||||
(define-sexp-parser peg-primary all
|
||||
(or (and "(" peg-sp peg-pattern ")" peg-sp)
|
||||
(and "." peg-sp)
|
||||
peg-literal
|
||||
peg-charclass
|
||||
(and peg-nonterminal (not-followed-by "<"))))
|
||||
(define-sexp-parser peg-literal all
|
||||
(and "'" (* (and (not-followed-by "'") peg-any)) "'" peg-sp))
|
||||
(define-sexp-parser peg-charclass all
|
||||
(and (ignore "[")
|
||||
(* (and (not-followed-by "]")
|
||||
(or charclass-range charclass-single)))
|
||||
(ignore "]")
|
||||
peg-sp))
|
||||
(define-sexp-parser charclass-range all (and peg-any "-" peg-any))
|
||||
(define-sexp-parser charclass-single all peg-any)
|
||||
(define-sexp-parser peg-nonterminal all
|
||||
(and (+ (or (range #\a #\z) (range #\A #\Z) (range #\0 #\9) "-")) peg-sp))
|
||||
(define-sexp-parser peg-sp none
|
||||
(* (or " " "\t" "\n")))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;; PARSE STRING PEGS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Takes a string representing a PEG grammar and returns syntax that
|
||||
;; will define all of the nonterminals in the grammar with equivalent
|
||||
;; PEG s-expressions.
|
||||
(define (peg-parser str for-syntax)
|
||||
(let ((parsed (match-pattern peg-grammar str)))
|
||||
(if (not parsed)
|
||||
(begin
|
||||
;; (display "Invalid PEG grammar!\n")
|
||||
#f)
|
||||
(let ((lst (peg:tree parsed)))
|
||||
(cond
|
||||
((or (not (list? lst)) (null? lst))
|
||||
lst)
|
||||
((eq? (car lst) 'peg-grammar)
|
||||
#`(begin
|
||||
#,@(map (lambda (x) (peg-nonterm->defn x for-syntax))
|
||||
(context-flatten (lambda (lst) (<= (depth lst) 2))
|
||||
(cdr lst))))))))))
|
||||
|
||||
;; Macro wrapper for PEG-PARSER. Parses PEG grammars expressed as strings and
|
||||
;; defines all the appropriate nonterminals.
|
||||
(define-syntax define-peg-string-patterns
|
||||
(lambda (x)
|
||||
(syntax-case x ()
|
||||
((_ str)
|
||||
(peg-parser (syntax->datum #'str) x)))))
|
||||
|
||||
;; lst has format (nonterm grabber pattern), where
|
||||
;; nonterm is a symbol (the name of the nonterminal),
|
||||
;; grabber is a string (either "<", "<-" or "<--"), and
|
||||
;; pattern is the parse of a PEG pattern expressed as as string.
|
||||
(define (peg-nonterm->defn lst for-syntax)
|
||||
(let* ((nonterm (car lst))
|
||||
(grabber (cadr lst))
|
||||
(pattern (caddr lst))
|
||||
(nonterm-name (datum->syntax for-syntax
|
||||
(string->symbol (cadr nonterm)))))
|
||||
#`(define-peg-pattern #,nonterm-name
|
||||
#,(cond
|
||||
((string=? grabber "<--") (datum->syntax for-syntax 'all))
|
||||
((string=? grabber "<-") (datum->syntax for-syntax 'body))
|
||||
(else (datum->syntax for-syntax 'none)))
|
||||
#,(compressor (peg-pattern->defn pattern for-syntax) for-syntax))))
|
||||
|
||||
;; lst has format ('peg-pattern ...).
|
||||
;; After the context-flatten, (cdr lst) has format
|
||||
;; (('peg-alternative ...) ...), where the outer list is a collection
|
||||
;; of elements from a '/' alternative.
|
||||
(define (peg-pattern->defn lst for-syntax)
|
||||
#`(or #,@(map (lambda (x) (peg-alternative->defn x for-syntax))
|
||||
(context-flatten (lambda (x) (eq? (car x) 'peg-alternative))
|
||||
(cdr lst)))))
|
||||
|
||||
;; lst has format ('peg-alternative ...).
|
||||
;; After the context-flatten, (cdr lst) has the format
|
||||
;; (item ...), where each item has format either ("!" ...), ("&" ...),
|
||||
;; or ('peg-suffix ...).
|
||||
(define (peg-alternative->defn lst for-syntax)
|
||||
#`(and #,@(map (lambda (x) (peg-body->defn x for-syntax))
|
||||
(context-flatten (lambda (x) (or (string? (car x))
|
||||
(eq? (car x) 'peg-suffix)))
|
||||
(cdr lst)))))
|
||||
|
||||
;; lst has the format either
|
||||
;; ("!" ('peg-suffix ...)), ("&" ('peg-suffix ...)), or
|
||||
;; ('peg-suffix ...).
|
||||
(define (peg-body->defn lst for-syntax)
|
||||
(cond
|
||||
((equal? (car lst) "&")
|
||||
#`(followed-by #,(peg-suffix->defn (cadr lst) for-syntax)))
|
||||
((equal? (car lst) "!")
|
||||
#`(not-followed-by #,(peg-suffix->defn (cadr lst) for-syntax)))
|
||||
((eq? (car lst) 'peg-suffix)
|
||||
(peg-suffix->defn lst for-syntax))
|
||||
(else `(peg-parse-body-fail ,lst))))
|
||||
|
||||
;; lst has format ('peg-suffix <peg-primary> (? (/ "*" "?" "+")))
|
||||
(define (peg-suffix->defn lst for-syntax)
|
||||
(let ((inner-defn (peg-primary->defn (cadr lst) for-syntax)))
|
||||
(cond
|
||||
((null? (cddr lst))
|
||||
inner-defn)
|
||||
((equal? (caddr lst) "*")
|
||||
#`(* #,inner-defn))
|
||||
((equal? (caddr lst) "?")
|
||||
#`(? #,inner-defn))
|
||||
((equal? (caddr lst) "+")
|
||||
#`(+ #,inner-defn)))))
|
||||
|
||||
;; Parse a primary.
|
||||
(define (peg-primary->defn lst for-syntax)
|
||||
(let ((el (cadr lst)))
|
||||
(cond
|
||||
((list? el)
|
||||
(cond
|
||||
((eq? (car el) 'peg-literal)
|
||||
(peg-literal->defn el for-syntax))
|
||||
((eq? (car el) 'peg-charclass)
|
||||
(peg-charclass->defn el for-syntax))
|
||||
((eq? (car el) 'peg-nonterminal)
|
||||
(datum->syntax for-syntax (string->symbol (cadr el))))))
|
||||
((string? el)
|
||||
(cond
|
||||
((equal? el "(")
|
||||
(peg-pattern->defn (caddr lst) for-syntax))
|
||||
((equal? el ".")
|
||||
(datum->syntax for-syntax 'peg-any))
|
||||
(else (datum->syntax for-syntax
|
||||
`(peg-parse-any unknown-string ,lst)))))
|
||||
(else (datum->syntax for-syntax
|
||||
`(peg-parse-any unknown-el ,lst))))))
|
||||
|
||||
;; Trims characters off the front and end of STR.
|
||||
;; (trim-1chars "'ab'") -> "ab"
|
||||
(define (trim-1chars str) (substring str 1 (- (string-length str) 1)))
|
||||
|
||||
;; Parses a literal.
|
||||
(define (peg-literal->defn lst for-syntax)
|
||||
(datum->syntax for-syntax (trim-1chars (cadr lst))))
|
||||
|
||||
;; Parses a charclass.
|
||||
(define (peg-charclass->defn lst for-syntax)
|
||||
#`(or
|
||||
#,@(map
|
||||
(lambda (cc)
|
||||
(cond
|
||||
((eq? (car cc) 'charclass-range)
|
||||
#`(range #,(datum->syntax
|
||||
for-syntax
|
||||
(string-ref (cadr cc) 0))
|
||||
#,(datum->syntax
|
||||
for-syntax
|
||||
(string-ref (cadr cc) 2))))
|
||||
((eq? (car cc) 'charclass-single)
|
||||
(datum->syntax for-syntax (cadr cc)))))
|
||||
(context-flatten
|
||||
(lambda (x) (or (eq? (car x) 'charclass-range)
|
||||
(eq? (car x) 'charclass-single)))
|
||||
(cdr lst)))))
|
||||
|
||||
;; Compresses a list to save the optimizer work.
|
||||
;; e.g. (or (and a)) -> a
|
||||
(define (compressor-core lst)
|
||||
(if (or (not (list? lst)) (null? lst))
|
||||
lst
|
||||
(cond
|
||||
((and (or (eq? (car lst) 'or) (eq? (car lst) 'and))
|
||||
(null? (cddr lst)))
|
||||
(compressor-core (cadr lst)))
|
||||
((and (eq? (car lst) 'body)
|
||||
(eq? (cadr lst) 'lit)
|
||||
(eq? (cadddr lst) 1))
|
||||
(compressor-core (caddr lst)))
|
||||
(else (map compressor-core lst)))))
|
||||
|
||||
(define (compressor syn for-syntax)
|
||||
(datum->syntax for-syntax
|
||||
(compressor-core (syntax->datum syn))))
|
||||
|
||||
;; Builds a lambda-expressions for the pattern STR using accum.
|
||||
(define (peg-string-compile args accum)
|
||||
(syntax-case args ()
|
||||
((str-stx) (string? (syntax->datum #'str-stx))
|
||||
(let ((string (syntax->datum #'str-stx)))
|
||||
(compile-peg-pattern
|
||||
(compressor
|
||||
(peg-pattern->defn
|
||||
(peg:tree (match-pattern peg-pattern string)) #'str-stx)
|
||||
#'str-stx)
|
||||
(if (eq? accum 'all) 'body accum))))
|
||||
(else (error "Bad embedded PEG string" args))))
|
||||
|
||||
(add-peg-compiler! 'peg peg-string-compile)
|
|
@ -1,118 +0,0 @@
|
|||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright (C) 2010, 2011 Free Software Foundation, Inc.
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Taken from GNU Guile
|
||||
|
||||
;;; using-parsers.scm --- utilities to make using parsers easier
|
||||
|
||||
(define-module (ice-9 peg using-parsers)
|
||||
#:use-module (ice-9 peg simplify-tree)
|
||||
#:use-module (ice-9 peg codegen)
|
||||
#:use-module (ice-9 peg cache)
|
||||
#:export (match-pattern define-peg-pattern search-for-pattern
|
||||
prec make-prec peg:start peg:end peg:string
|
||||
peg:tree peg:substring peg-record?))
|
||||
|
||||
;;;
|
||||
;;; Helper Macros
|
||||
;;;
|
||||
|
||||
(define-syntax until
|
||||
(syntax-rules ()
|
||||
;;"Evaluate TEST. If it is true, return its value. Otherwise,execute the STMTs and try again."
|
||||
((_ test stmt stmt* ...)
|
||||
(let lp ()
|
||||
(or test
|
||||
(begin stmt stmt* ... (lp)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;; FOR DEFINING AND USING NONTERMINALS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Parses STRING using NONTERM
|
||||
(define (match-pattern nonterm string)
|
||||
;; We copy the string before using it because it might have been modified
|
||||
;; in-place since the last time it was parsed, which would invalidate the
|
||||
;; cache. Guile uses copy-on-write for strings, so this is fast.
|
||||
(let ((res (nonterm (string-copy string) (string-length string) 0)))
|
||||
(if (not res)
|
||||
#f
|
||||
(make-prec 0 (car res) string (string-collapse (cadr res))))))
|
||||
|
||||
;; Defines a new nonterminal symbol accumulating with ACCUM.
|
||||
(define-syntax define-peg-pattern
|
||||
(lambda (x)
|
||||
(syntax-case x ()
|
||||
((_ sym accum pat)
|
||||
(let ((matchf (compile-peg-pattern #'pat (syntax->datum #'accum)))
|
||||
(accumsym (syntax->datum #'accum)))
|
||||
;; CODE is the code to parse the string if the result isn't cached.
|
||||
(let ((syn (wrap-parser-for-users x matchf accumsym #'sym)))
|
||||
#`(define sym #,(cg-cached-parser syn))))))))
|
||||
|
||||
(define (peg-like->peg pat)
|
||||
(syntax-case pat ()
|
||||
(str (string? (syntax->datum #'str)) #'(peg str))
|
||||
(else pat)))
|
||||
|
||||
;; Searches through STRING for something that parses to PEG-MATCHER. Think
|
||||
;; regexp search.
|
||||
(define-syntax search-for-pattern
|
||||
(lambda (x)
|
||||
(syntax-case x ()
|
||||
((_ pattern string-uncopied)
|
||||
(let ((pmsym (syntax->datum #'pattern)))
|
||||
(let ((matcher (compile-peg-pattern (peg-like->peg #'pattern) 'body)))
|
||||
;; We copy the string before using it because it might have been
|
||||
;; modified in-place since the last time it was parsed, which would
|
||||
;; invalidate the cache. Guile uses copy-on-write for strings, so
|
||||
;; this is fast.
|
||||
#`(let ((string (string-copy string-uncopied))
|
||||
(strlen (string-length string-uncopied))
|
||||
(at 0))
|
||||
(let ((ret (until (or (>= at strlen)
|
||||
(#,matcher string strlen at))
|
||||
(set! at (+ at 1)))))
|
||||
(if (eq? ret #t) ;; (>= at strlen) succeeded
|
||||
#f
|
||||
(let ((end (car ret))
|
||||
(match (cadr ret)))
|
||||
(make-prec
|
||||
at end string
|
||||
(string-collapse match))))))))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;; PMATCH STRUCTURE MUNGING
|
||||
;; Pretty self-explanatory.
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(define prec
|
||||
(make-record-type "peg" '(start end string tree)))
|
||||
(define make-prec
|
||||
(record-constructor prec '(start end string tree)))
|
||||
(define (peg:start pm)
|
||||
(if pm ((record-accessor prec 'start) pm) #f))
|
||||
(define (peg:end pm)
|
||||
(if pm ((record-accessor prec 'end) pm) #f))
|
||||
(define (peg:string pm)
|
||||
(if pm ((record-accessor prec 'string) pm) #f))
|
||||
(define (peg:tree pm)
|
||||
(if pm ((record-accessor prec 'tree) pm) #f))
|
||||
(define (peg:substring pm)
|
||||
(if pm (substring (peg:string pm) (peg:start pm) (peg:end pm)) #f))
|
||||
(define peg-record? (record-predicate prec))
|
|
@ -1,71 +0,0 @@
|
|||
#! /bin/sh
|
||||
# -*-scheme-*-
|
||||
exec ${MES-bin/mes} --no-auto-compile -L ${0%/*} -L module -C module -e '(tests peg)' -s "$0" "$@"
|
||||
!#
|
||||
|
||||
;;; -*-scheme-*-
|
||||
|
||||
;;; GNU Mes --- Maxwell Equations of Software
|
||||
;;; Copyright © 2016 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
|
||||
;;;
|
||||
;;; This file is part of GNU Mes.
|
||||
;;;
|
||||
;;; GNU Mes is free software; you can redistribute it and/or modify it
|
||||
;;; under the terms of the GNU General Public License as published by
|
||||
;;; the Free Software Foundation; either version 3 of the License, or (at
|
||||
;;; your option) any later version.
|
||||
;;;
|
||||
;;; GNU Mes is distributed in the hope that it will be useful, but
|
||||
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;; GNU General Public License for more details.
|
||||
;;;
|
||||
;;; You should have received a copy of the GNU General Public License
|
||||
;;; along with GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (tests peg)
|
||||
#:use-module (mes mes-0)
|
||||
#:use-module (mes test))
|
||||
|
||||
(cond-expand
|
||||
(mes
|
||||
(mes-use-module (mes peg))
|
||||
(mes-use-module (mes test)))
|
||||
(guile-2.2
|
||||
(use-modules (ice-9 peg)))
|
||||
(guile
|
||||
(use-modules (ice-9 syncase))
|
||||
(display "guile 2.0: no PEG\n" (current-error-port))
|
||||
(exit 0)))
|
||||
|
||||
(pass-if "first dummy" #t)
|
||||
(pass-if-not "second dummy" #f)
|
||||
|
||||
(define *etc-passwd*
|
||||
"root:x:0:0:root:/root:/bin/bash
|
||||
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
|
||||
bin:x:2:2:bin:/bin:/bin/sh
|
||||
sys:x:3:3:sys:/dev:/bin/sh
|
||||
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
|
||||
messagebus:x:103:107::/var/run/dbus:/bin/false")
|
||||
|
||||
(define-peg-string-patterns
|
||||
"string-passwd <- entry* !.
|
||||
entry <-- (! NL .)* NL*
|
||||
NL < '\n'")
|
||||
|
||||
(pass-if-equal "peg-tree"
|
||||
(map (lambda (x) (list 'entry x)) (string-split *etc-passwd* #\newline))
|
||||
(peg:tree (match-pattern string-passwd *etc-passwd*)))
|
||||
|
||||
(define-peg-pattern passwd body (and (* entry) (not-followed-by peg-any)))
|
||||
(define-peg-pattern entry all (and (* (and (not-followed-by NL) peg-any))
|
||||
(* NL)))
|
||||
(define-peg-pattern NL none "\n")
|
||||
(define-peg-pattern passwd body (peg "entry* !."))
|
||||
|
||||
(pass-if-equal "peg-tree"
|
||||
(map (lambda (x) (list 'entry x)) (string-split *etc-passwd* #\newline))
|
||||
(peg:tree (match-pattern passwd *etc-passwd*)))
|
||||
|
||||
(result 'report)
|
Loading…
Reference in a new issue