From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Stefan Israelsson Tampe Newsgroups: gmane.lisp.guile.devel,gmane.lisp.guile.user Subject: stis-parser v0.1 Date: Thu, 13 Jul 2017 20:30:20 +0200 Message-ID: NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="001a1138e4e00e52740554372049" X-Trace: blaine.gmane.org 1499970654 14975 195.159.176.226 (13 Jul 2017 18:30:54 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Thu, 13 Jul 2017 18:30:54 +0000 (UTC) To: guile-devel , "guile-user@gnu.org" Original-X-From: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Thu Jul 13 20:30:43 2017 Return-path: Envelope-to: guile-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dVisn-0002ra-Bu for guile-devel@m.gmane.org; Thu, 13 Jul 2017 20:30:37 +0200 Original-Received: from localhost ([::1]:33475 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dViso-0007MD-2o for guile-devel@m.gmane.org; Thu, 13 Jul 2017 14:30:38 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:49384) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dVisd-0007Lm-TJ for guile-devel@gnu.org; Thu, 13 Jul 2017 14:30:30 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dVisb-0000P5-0s for guile-devel@gnu.org; Thu, 13 Jul 2017 14:30:27 -0400 Original-Received: from mail-oi0-x22c.google.com ([2607:f8b0:4003:c06::22c]:33680) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dVisa-0000O7-LS; Thu, 13 Jul 2017 14:30:24 -0400 Original-Received: by mail-oi0-x22c.google.com with SMTP id p188so53333032oia.0; Thu, 13 Jul 2017 11:30:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=N1ZWnXbPpfGJkhpAcF7S1foh7WGYHsSXOPptJPiFVW8=; b=PIhmRf5zspXIOVCPe4AI4JNuI7E+J2C6tTV9PQ+L5RbSw6O1dyebD6AXeelbLv4Wmv TDVMAT3nto1OEa7xhtbmlKOpA7FOc4y3l23qCuQ/J//PKpkceCd4K6RXvDFlGEHQ7nMM wh2XBTOoUxelFPMMvNc9IqdqavMk0duh2kN0/QdzR2fuzosMApuwoKxSjcApI4Y54/61 2R0FuAlzGjvGNVitqrw+LUIiyjAZmugZG0oC4qM9u3+vEmJOwkpMhCnYBEKQqMpQ1s5w t2X2LAY+N1UOV1fQJief4gTK5uj05FQY5tSUnlUlsVDnsNnLmkNrv3RE7WaXQlvWrh2p 9ciA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=N1ZWnXbPpfGJkhpAcF7S1foh7WGYHsSXOPptJPiFVW8=; b=N9IMKI4XgJRFUioXlkmdBE3DvDV2m+BF4Y3QLhSB17utkt8Y4sslhs+2pzDtyEKQcp SImjD/J0ShOll301A8+ipbGMCPYv6r54CnjYiFtrnJ+1ISf/ljvEIj3UgMFOHS2vxz5m vf5zIYhHPZew8Ly3O3zqtNIofWzoKhpDMGXJzw3OWMBTPMEVnaZPYE9pv98pcUUZph5o UVu3mGwjQZWblFvPYelwRsoMVDkPMEntJp8GNx2VJ69M0YF2MDW0t7vLt6J3KSpxtESx CoHw91jdgm6Vyb3Ph3BjsIYZPAhzDVC+1tvUMJr7iunJEQB3uw5lw7ZXPlhO7WK84peO V1bQ== X-Gm-Message-State: AIVw112zXp0fqi+9ZS/XIf3RjmLdK0RxPt6lG3/d5O0MxYo5b2rYS+ey r5k5By2b4wlo37GVEv6YBhnMEziVz3Ln X-Received: by 10.202.44.148 with SMTP id s142mr3072137ois.122.1499970621295; Thu, 13 Jul 2017 11:30:21 -0700 (PDT) Original-Received: by 10.202.63.66 with HTTP; Thu, 13 Jul 2017 11:30:20 -0700 (PDT) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4003:c06::22c X-BeenThere: guile-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Developers list for Guile, the GNU extensibility library" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guile-devel-bounces+guile-devel=m.gmane.org@gnu.org Original-Sender: "guile-devel" Xref: news.gmane.org gmane.lisp.guile.devel:19246 gmane.lisp.guile.user:13917 Archived-At: --001a1138e4e00e52740554372049 Content-Type: text/plain; charset="UTF-8" I'm pleased to announce version 0.1 of stis parser, a parser framework. It contains a small logic programming framework, logical variables, parser combinators and memoization capabilities. Is functional in it's core. With the repository follows a C expression parser and a full parser for python 3. It can backtrack, Also a small program for tutorial learning, calc.scm is included as well. Also included is a expression parser that is really compact. Se example at the bottom of this email. https://gitlab.com/tampe/stis-parser Happy Parsing!! Example (calc.scm) (define-module (parser stis-parser examples calc) #:use-module (ice-9 match) #:use-module (parser stis-parser) #:use-module (parser stis-parser operator-parser) #:export (p e c p2)) (define ws (f* (f-or! f-nl (f-char #\space) (f-char #\tab)))) ;;;; let's define whitespace as a sequence fo nl/space/tab (fluid-set! *whitespace* ws) ;(f-or! a b ...) try first a if that fails b ... ! means only one solution ;;;;Define the tokenizer ;;number (define int (f+ (f-reg! "[0-9]"))) ; ! means store character ; f+ mean 1 or more matches ; f-reg mean that the character ; should match the regular expression ; for one character ; does not work for multiple characters (define decimal (f+ (f-or! (f-seq int (f-tag! ".") int) (f-seq int (f-tag ".")) (f-seq (f-tag! ".") int) int))) ;! mean store match ;f-seq a ... means match a, then b ... ;f-tag means literal match of all ;characters in string (define exp (f-seq decimal (f-reg! "[eE]") (f? (f-reg! "[+-]")) decimal)) (define num (f-or! exp decimal)) ;; lets make a token (define number- (p-freeze 'number (mk-token num) (lambda (s cin cout) (string->number cout)))) ;(mk-token f) will combine the result of ;f in one string ;(p-freeze tag f translate) ;well memoize the result of f tagging it ;with the uique tag tag and translate ;the result with (lambda (s in out) ..) ;most cases will use out ;;Tag the token e.g. produce a value '(#:number 2322.2e-122.2) we also have ;; f-cons f-cons* that works naturally there is whitespace between the sub ;; expressions (define number (f-list #:number number-)) ;;symbol ; nothing new just a c-symbol (define sym (f-seq (f-reg! "[_a-zA-Z]") (f* (f-reg! "[_a-zA-Z0-9]")))) (define symbol- (p-freeze 'symbol (mk-token sym) (lambda (s cin cout) (string->symbol cout)))) (define symbol (f-list #:symbol symbol-)) (define comma (f-cons* (D add/sub-expr) (ff* (f-seq "," (D add/sub-expr))))) (define fkn (f-cons* #:fkn symbol (f-seq "(" comma ")"))) ;f-cons a ... b will cons* the ouput ;of a .... b ;ff+ and ff* creates lists of the ;results ;; paranthesizes expressions, note use (D f) when f is not defined yet (define sexpr (f-seq (f-tag "(") (D add/sub-expr) f-tag ")")) (define term (f-or! sexpr fkn symbol number)) (define term-1 (f-or! (f-list #:+ "+" (D term-1)) (f-list #:- "-" (D term-1)) term)) ;note that strings will sielently match ;it's value (define eql-expr (f-list #:= symbol "=" (D add/sub-expr))) (define pow-expr (f-or! (f-cons* #:^ term-1 (ff+ (f-seq "^" term-1))) term-1)) (define mul-expr (f-list #:* pow-expr "*" (D mul/div-expr))) (define div-expr (f-list #:/ pow-expr "/" (D mul/div-expr))) (define mul/div-expr (f-or! (f-or! mul-expr div-expr) pow-expr)) (define add-expr (f-list #:+ mul/div-expr "+" (D add/sub-expr))) (define sub-expr (f-list #:- mul/div-expr "-" (D add/sub-expr))) (define add/sub-expr (f-or! add-expr sub-expr mul/div-expr)) (define expr (f-or! eql-expr add/sub-expr)) ;;;;Now lets define the parser (define (p string) ((@ (parser stis-parser) parse) string (f-seq expr f-eof))) ;we must end with f-eof e.g. ;end of string in order to not parse ;a prefix ;;;; Voila ;; cheme@(guile-user)> (use-modules (parser stis-parser examples calc)) ;;scheme@(guile-user)> (calc-parse "1234 + 4^-3*12-3/2 - a") ;;(#:= (#:symbol b) ;; (#:+ (#:number 1234) ;; (#:- (#:* (#:^ (#:number 4) ;; (#:- (#:number 3))) ;; (#:number 12)) ;; (#:- (#:/ (#:number 3) (#:number 2)) ;; (#:symbol a))))) (define (e str) (let ((mod (current-module))) (let lp ((r (p str))) (match r ((#:= (#:symbol s) expr) (let ((e (lp expr))) (if (module-defined? mod s) (module-set! mod s (lp expr)) (module-define! mod s (lp expr))) e)) ((#:+ a) (lp a)) ((#:symbol s) (module-ref mod s)) ((#:number n) n) ((#:fkn (#:symbol s) . a) (eval (cons s (map lp a)) mod)) ((#:- a) (- (lp a))) ((#:+ a b) (+ (lp a) (lp b))) ((#:- a b) (- (lp a) (lp b))) ((#:* a b) (* (lp a) (lp b))) ((#:/ a b) (/ (lp a) (lp b))) ((#:^ a b) (expt (lp a) (lp b))) ((#:^ a . b) (expt (lp a) (lp (cons #:^ b)))))))) (define (c str) (let lp ((r (p str))) (match r ((#:= (#:symbol s) expr) (let ((x (gensym "x"))) `(let ((,x ,(lp expr))) (define! ',s ,x) ,x))) ((#:+ a) (lp a)) ((#:symbol s) s) ((#:number n) n) ((#:fkn (#:symbol s) . a) (cons* s (map lp a))) ((#:- a) `(- ,(lp a))) ((#:+ a b) `(+ ,(lp a) ,(lp b))) ((#:- a b) `(- ,(lp a) ,(lp b))) ((#:* a b) `(* ,(lp a) ,(lp b))) ((#:/ a b) `(/ ,(lp a) ,(lp b))) ((#:^ a b) `(expt ,(lp a) ,(lp b))) ((#:^ a . b) `(expt ,(lp a) ,(lp (cons #:^ b))))))) ;;with the compiler c to scheme you can now do #| scheme@(guile-user)> ,L calc Happy hacking with Calc! To switch back, type `,L scheme'. calc@(guile-user)> x=1 $1 = 1 calc@(guile-user)> x+2 $2 = 3 calc@(guile-user)> pi=3.13 $3 = 3.13 calc@(guile-user)> pi $4 = 3.13 calc@(guile-user)> sin(pi) $5 = 0.011592393936158275 calc@(guile-user)> sin(pi/2) $6 = 0.9999832013448761 calc@(guile-user)> sin(pi/3) $7 = 0.8640868338458068 calc@(guile-user)> sin(pi/3)^10 $8 = 0.2320458886621503 calc@(guile-user)> y=sin(pi/3)^10 $9 = 0.2320458886621503 calc@(guile-user)> y $10 = 0.2320458886621503 calc@(guile-user)> |# ;;;; Let's checkout the expression dynamic parser here you define a set ;;;; of operators and some rules and get a parser emmediately out of it ;;;; you can even dynamically create operators :-) (define *ops* (make-opdata)) (for-each (lambda (x) (match x ((a b c) (add-operator *ops* a c b ws)))) `((xfy 50 ",") (xfy 30 +) ; binary operators l-r (xfy 30 -) (xfy 20 *) (xfy 20 /) (yfx 10 ^) ; right to left expression (xfx 40 =) ; only a binary expression (fy 5 +) ; unary postfix operators (fy 5 -))) #| xfy = left to right yfx = right to left xfx = binary expression with just two terms xf = prefix operator fy = postfix operator the numbers are the binding strength lower binds harder |# (define fkn2 (f-cons* #:fkn symbol (f-seq "(" (D expr2) ")"))) (define sexpr2 (f-seq (f-tag "(") (D expr2) (f-tag ")"))) (define term2 (f-or! sexpr2 fkn2 symbol number)) (define expr2 ((mk-operator-expression ws term2 f-false *ops*) 50)) ; 50 is highest level ; ws = whitespace ; term2 = the term ; f-false expert option leave as ity is ; *ops* the generated operator table (define (p2 string) ((@ (parser stis-parser) parse) string (f-seq expr2 f-eof))) #| scheme@(guile-user)> (p2 "1^2^3") $1 = ((yfx 10 "^" #\^) ((yfx 10 "^" #\^) (#:number 1) (#:number 2) 3 1) (#:number 3) 5 1) So the parse tree has format Binary = (Tag Term Term Line column) UNARY = (Tag Term Line column) Tag = (type level operator first-char) With this one can deduce a simple evaluator compiler etc using e.g. C semantics |# enjoy making parsers for your favorite syntax. --001a1138e4e00e52740554372049 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
I'm pleased to announce version 0.1 of stis parse= r, a parser framework. It contains a small logic programming framework, log= ical variables, parser combinators and memoization capabilities.=C2=A0
Is functional in it's core. With the repository follows a C expre= ssion parser and a full parser for=C2=A0
python 3. It can backtra= ck, Also a small program for tutorial learning, calc.scm is included as wel= l.
Also included is a expression parser that is really compact. S= e example at the bottom of this email.

https://gitlab.com/tampe/stis-parser


Happy Parsing!!

Example (calc.scm)

(define-module (parser = stis-parser examples calc)
=C2=A0 #:use-module (ice-9 match)
=C2=A0 #:use-module (parser stis-parser)
=C2=A0 #:use-modul= e (parser stis-parser operator-parser)
=C2=A0 #:export (p e c p2)= )

(define ws (f* (f-or! f-nl (f-char #\space) (f-c= har #\tab))))

;;;; let's define whitespace as = a sequence fo nl/space/tab
(fluid-set! *whitespace* ws)

=C2=A0 =C2=A0 ;(f-or! a b ...) try first a if that fails b = ... ! means only one solution

;;;;Define the token= izer

;;number
(define int (f+ (f-reg! &q= uot;[0-9]")))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 ; ! means store character
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ; f+ mean 1 or more matche= s
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 ; f-reg mean that the character
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ; should match the regular expressio= n
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 ; for one character
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 ; does not work for multiple characters
=
(define decimal (f+ (f-or! (f-seq int (f-tag! ".")= int)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(f-seq int (f-tag "."))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(f-seq (f-tag! ".") int)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0int)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;! mean store match
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;f-seq a ... means mat= ch a, then b ...
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 ;f-tag means literal match of all
=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;characters in string<= /div>

(define exp (f-seq decimal (f-reg! "[eE]"= ;) (f? (f-reg! "[+-]")) decimal))
(define num (f-or! ex= p decimal))

;; lets make a token
(define= number-
=C2=A0 (p-freeze 'number (mk-token num)
= =C2=A0 =C2=A0 (lambda (s cin cout)
=C2=A0 =C2=A0 =C2=A0 (string-&= gt;number cout))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 ;(mk-token f) will combine the result of
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;f in one st= ring
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 ;(p-freeze tag f translate)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;well memoize the result of f taggin= g it
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 ;with the uique tag tag and translate
=C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;the result with (lambda (s i= n out) ..)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ;most cases will use out
;;Tag the token e.g. produ= ce a value '(#:number 2322.2e-122.2) we also have
;; =C2=A0f-= cons f-cons* that works naturally there is whitespace between the sub
=
;; =C2=A0expressions
(define number (f-list #:number number-= ))

;;symbol ; nothing new just a c-symbol
(define sym (f-seq (f-reg! "[_a-zA-Z]") (f* (f-reg! "[_a-z= A-Z0-9]"))))
(define symbol-
=C2=A0 (p-freeze '= ;symbol (mk-token sym)
=C2=A0 =C2=A0 (lambda (s cin cout)
=C2=A0 =C2=A0 =C2=A0 (string->symbol cout))))
(define symbo= l (f-list #:symbol symbol-))

(define comma (f-cons= * (D add/sub-expr) (ff* (f-seq "," (D add/sub-expr)))))
(define fkn =C2=A0 (f-cons* #:fkn symbol (f-seq "(" comma "= )")))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ;f-cons a ... b will cons* the ouput
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;of a .... b
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;ff+ and= ff* creates lists of the
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;results

;; paranthesi= zes expressions, note use (D f) when f is not defined yet
(define= sexpr =C2=A0 =C2=A0(f-seq (f-tag "(") (D add/sub-expr) f-tag &qu= ot;)"))
(define term =C2=A0 =C2=A0 (f-or! sexpr fkn symbol n= umber))

(define term-1 =C2=A0 (f-or! (f-list #:+ &= quot;+" (D term-1))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (f-list #:- "-" (D = term-1))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 term))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;note that strings will sielently ma= tch
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 ;it's value

(define eql-expr (f-list #:= =3D symbol "=3D" (D add/sub-expr)))
(define pow-expr (f= -or! (f-cons* #:^ term-1 (ff+ (f-seq "^" term-1)))
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 term-1))

(define mul-expr (f-list #:* pow-e= xpr "*" (D mul/div-expr)))
(define div-expr (f-list #:/= pow-expr "/" (D mul/div-expr)))
(define mul/div-expr (= f-or! (f-or! mul-expr div-expr)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 pow-expr= ))

(define add-expr (f-list #:+ mul/div-expr =C2= =A0 "+" (D add/sub-expr)))
(define sub-expr (f-list #:-= mul/div-expr =C2=A0 "-" (D add/sub-expr)))
(define add= /sub-expr (f-or! add-expr
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sub-expr
<= div>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 mul/div-expr))





(define expr (f-or! eq= l-expr add/sub-expr))

;;;;Now lets define the pars= er
(define (p string) ((@ (parser stis-parser) parse)
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 strin= g (f-seq expr f-eof)))

=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;we must end with f-eof e.g.
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;end = of string in order to not parse
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ;a prefix

;;;; = Voila
;; cheme@(guile-user)> (use-modules (parser stis-parser = examples calc))

;;scheme@(guile-user)> (calc-pa= rse "1234 + 4^-3*12-3/2 - a")
;;(#:=3D (#:symbol b)
;; =C2=A0 =C2=A0 (#:+ (#:number 1234)
;; =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0(#:- (#:* (#:^ (#:number 4)
;; =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (#:- (#:= number 3)))
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0(#:number 12))
;; =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 (#:- (#:/ (#:number 3) (#:number 2))
;; =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(#:symbol= a)))))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0
(define (e str)
=C2=A0 (let ((mod (current-module)))
= =C2=A0 =C2=A0 (let lp ((r (p str)))
=C2=A0 =C2=A0 =C2=A0 (match r=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:=3D (#:symbol s) expr)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((e (lp expr)))
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(if (module-defined? mod s) =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0(module-set! mod s (lp expr))
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(module-define! mod s (lp e= xpr)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0e))
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 ((#:+ a)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0(lp a))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:symbol s)
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(module-ref mod s))
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 ((#:number n)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0n)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:fkn (#:symbol s) . a)
=
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(eval (cons s (map lp a)) mod))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:- a)
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0(- (lp a)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:+ a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(+ (lp a) (lp b)))
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 ((#:- a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0(- (lp a) (lp b)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:* a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(* (lp a) (lp b)))
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 ((#:/ a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0(/ (lp a) (lp b)))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:^ a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(expt (lp a) (lp b)))
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((#:^ a . b)
=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0(expt (lp a) (lp (cons #:^ b))))))))

(de= fine (c str)
=C2=A0 (let lp ((r (p str)))
=C2=A0 =C2=A0= (match r
=C2=A0 =C2=A0 =C2=A0 ((#:=3D (#:symbol s) expr)
=C2=A0 =C2=A0 =C2=A0 =C2=A0(let ((x (gensym "x")))
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0`(let ((,x ,(lp expr)))
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (define! ',s ,x)
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ,x)))
=C2=A0 =C2=A0 =C2=A0=C2= =A0
=C2=A0 =C2=A0 =C2=A0 ((#:+ a)
=C2=A0 =C2=A0 =C2=A0 = =C2=A0(lp a))
=C2=A0 =C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0 = =C2=A0 ((#:symbol s)
=C2=A0 =C2=A0 =C2=A0 =C2=A0s)
=C2= =A0 =C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0 =C2=A0 ((#:number n)
<= div>=C2=A0 =C2=A0 =C2=A0 =C2=A0n)
=C2=A0 =C2=A0 =C2=A0=C2=A0
=C2=A0 =C2=A0 =C2=A0 ((#:fkn (#:symbol s) . a)
=C2=A0 =C2= =A0 =C2=A0 =C2=A0(cons* s (map lp a)))
=C2=A0 =C2=A0 =C2=A0 ((#:-= a)
=C2=A0 =C2=A0 =C2=A0 =C2=A0`(- ,(lp a)))
=C2=A0 =C2= =A0 =C2=A0 ((#:+ a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0`(+ ,(lp a) ,(lp= b)))
=C2=A0 =C2=A0 =C2=A0 ((#:- a b)
=C2=A0 =C2=A0 =C2= =A0 =C2=A0`(- ,(lp a) ,(lp b)))
=C2=A0 =C2=A0 =C2=A0 ((#:* a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0`(* ,(lp a) ,(lp b)))
=C2=A0 = =C2=A0 =C2=A0 ((#:/ a b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0`(/ ,(lp a) ,= (lp b)))
=C2=A0 =C2=A0 =C2=A0 ((#:^ a b)
=C2=A0 =C2=A0 = =C2=A0 =C2=A0`(expt ,(lp a) ,(lp b)))
=C2=A0 =C2=A0 =C2=A0 ((#:^ = a . b)
=C2=A0 =C2=A0 =C2=A0 =C2=A0`(expt ,(lp a) ,(lp (cons #:^ b= )))))))


;;with the compiler c to sc= heme you can now do

#|
scheme@(guile-use= r)> ,L calc
Happy hacking with Calc!=C2=A0 To switch back, typ= e `,L scheme'.
calc@(guile-user)> x=3D1
$1 =3D 1=
calc@(guile-user)> x+2
$2 =3D 3
calc@(gui= le-user)> pi=3D3.13
$3 =3D 3.13
calc@(guile-user)>= ; pi
$4 =3D 3.13
calc@(guile-user)> sin(pi)
$5 =3D 0.011592393936158275
calc@(guile-user)> sin(pi/2)
$6 =3D 0.9999832013448761
calc@(guile-user)> sin(pi/3)<= /div>
$7 =3D 0.8640868338458068
calc@(guile-user)> sin(pi/= 3)^10
$8 =3D 0.2320458886621503
calc@(guile-user)> y= =3Dsin(pi/3)^10
$9 =3D 0.2320458886621503
calc@(guile-u= ser)> y
$10 =3D 0.2320458886621503
calc@(guile-user)= >=C2=A0
|#


;;;; Let= 9;s checkout the expression dynamic parser here you define a set
= ;;;; of operators and some rules and get a parser emmediately out of it
;;;; you can even dynamically create operators :-)

=C2=A0=C2=A0
(define *ops* (make-opdata))

<= /div>
(for-each
=C2=A0(lambda (x)
=C2=A0 =C2=A0(mat= ch x
=C2=A0 =C2=A0 =C2=A0((a b c) (add-operator *ops* a c b ws)))= )
=C2=A0`((xfy 50 ",")
=C2=A0 =C2=A0(xfy 30 += ) ; binary operators l-r
=C2=A0 =C2=A0(xfy 30 -)
=C2=A0= =C2=A0(xfy 20 *)
=C2=A0 =C2=A0(xfy 20 /)
=C2=A0 =C2=A0= (yfx 10 ^) ; right to left expression
=C2=A0 =C2=A0(xfx 40 =3D) ;= only a binary expression
=C2=A0 =C2=A0(fy =C2=A05 =C2=A0+) ; una= ry postfix operators
=C2=A0 =C2=A0(fy =C2=A05 =C2=A0-)))
#|
xfy =3D left to right
yfx =3D right to left
<= div>xfx =3D binary expression with just two terms
xf =C2=A0=3D pr= efix operator
fy =C2=A0=3D postfix operator

<= div>the numbers are the binding strength lower binds harder
|#


(define fkn2 =C2=A0 =C2=A0 (f-cons* #= :fkn symbol (f-seq "(" (D expr2) ")")))
(defi= ne sexpr2 =C2=A0 (f-seq (f-tag "(") (D expr2) (f-tag ")"= ;)))
(define term2 =C2=A0 =C2=A0(f-or! sexpr2 fkn2 symbol number)= )

(define expr2 ((mk-operator-expression ws term2 = f-false *ops*) 50))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 ; 50 is highest level
=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ; ws =3D whitespace
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ; term2 = =3D the term
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 ; f-false expert option leave as ity is
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ; *ops* the generat= ed operator table

(define (p2 string) ((@ (parser = stis-parser) parse)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0string (f-seq expr2 f-eof)))

<= /div>
#|
scheme@(guile-user)> (p2 "1^2^3")
=
$1 =3D ((yfx 10 "^" #\^)=C2=A0
=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0((yfx 10 "^" #\^)=C2=A0
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (#:number 1)=C2=A0
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (#:number 2)=C2=A0
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 3 1)=C2=A0
=C2=A0 =C2=A0 =C2=A0 (#:nu= mber 3)=C2=A0
=C2=A0 =C2=A0 =C2=A0 5 1)

= So the parse tree has format
Binary =3D (Tag Term Term Line colum= n)
UNARY =C2=A0=3D (Tag Term Line column)
Tag =C2=A0 = =C2=A0=3D (type level operator first-char)

With th= is one can deduce a simple evaluator compiler etc using e.g.=C2=A0
C semantics
|#



enjoy making parsers for your favorite syntax. =C2=A0
--001a1138e4e00e52740554372049--