Done using
    find third_party/lisp/{sclf,mime4cl,npg} \
      -name '*.lisp' -or -name '*.asd' \
      -exec bash -c 'expand -i -t 8 "$0" | sponge "$0"' {} \;
Change-Id: If84afac9c1d5cbc74e137a5aa0ae61472f0f1e90
Reviewed-on: https://cl.tvl.fyi/c/depot/+/5066
Tested-by: BuildkiteCI
Reviewed-by: sterni <sternenseemann@systemli.org>
		
	
			
		
			
				
	
	
		
			336 lines
		
	
	
	
		
			8 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
			
		
		
	
	
			336 lines
		
	
	
	
		
			8 KiB
		
	
	
	
		
			Common Lisp
		
	
	
	
	
	
| ;;;  python.lisp --- sample grammar definition for the Python language
 | |
| 
 | |
| ;;;  Copyright (C) 2003 by Walter C. Pelissero
 | |
| 
 | |
| ;;;  Author: Walter C. Pelissero <walter@pelissero.de>
 | |
| ;;;  Project: NPG a Naive Parser Generator
 | |
| ;;;  $Id: F-C1A8CD5961889C584B22F05E8B956006.lisp,v 1.3 2004/03/09 10:33:06 wcp Exp $
 | |
| 
 | |
| ;;; This library is free software; you can redistribute it and/or
 | |
| ;;; modify it under the terms of the GNU Lesser General Public License
 | |
| ;;; as published by the Free Software Foundation; either version 2.1
 | |
| ;;; of the License, or (at your option) any later version.
 | |
| ;;; This library 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
 | |
| ;;; Lesser General Public License for more details.
 | |
| ;;; You should have received a copy of the GNU Lesser General Public
 | |
| ;;; License along with this library; if not, write to the Free
 | |
| ;;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | |
| ;;; 02111-1307 USA
 | |
| 
 | |
| ;;;  Commentary:
 | |
| ;;;
 | |
| ;;; This is far from being a complete Python grammar.  Actually I
 | |
| ;;; haven't even read a Python book before starting to write this
 | |
| ;;; stuff, so the code below comes mostly from wild guessing while
 | |
| ;;; reading a Python source file.
 | |
| ;;;
 | |
| ;;; It's a design decision to avoid writing any transformation in this
 | |
| ;;; module; only tagging is done at this level.  This improves the
 | |
| ;;; separation between parsing and transformation, making the grammar
 | |
| ;;; reusable for other purposes.
 | |
| 
 | |
| 
 | |
| #+cmu (ext:file-comment "$Id: F-C1A8CD5961889C584B22F05E8B956006.lisp,v 1.3 2004/03/09 10:33:06 wcp Exp $")
 | |
| 
 | |
| (in-package :grammar)
 | |
| 
 | |
| (deflazy define-grammar
 | |
|   (let ((*package* #.*package*)
 | |
|         (*compile-print* (and parser::*debug* t)))
 | |
|     (reset-grammar)
 | |
|     (format t "~&creating Python grammar...~%")
 | |
|     (populate-grammar)
 | |
|     (let ((grammar (parser:generate-grammar)))
 | |
|       (reset-grammar)
 | |
|       (parser:print-grammar-figures grammar)
 | |
|       grammar)))
 | |
| 
 | |
| (defun populate-grammar ()
 | |
| 
 | |
| (defrule program
 | |
|     := comment-string? statement+)
 | |
| 
 | |
| (defrule comment-string
 | |
|     := string eol
 | |
|     :reduce string)
 | |
| 
 | |
| ;;; BOB = Beginning Of Block, EOB = End Of Block.  It's lexical
 | |
| ;;; analyzer's task to find out where a statement or block starts/ends.
 | |
| 
 | |
| (defrule suite
 | |
|     := statement-list eol
 | |
|     :reduce statement-list
 | |
|     := statement-block)
 | |
| 
 | |
| (defrule commentable-suite
 | |
|     := statement-list eol
 | |
|     :reduce statement-list
 | |
|     := commented-statement-block)
 | |
| 
 | |
| (defrule statement-block
 | |
|     := bob statement+ eob
 | |
|     :reduce $2)
 | |
| 
 | |
| (defrule commented-statement-block
 | |
|     := bob comment-string? statement* eob
 | |
|     :reduce (cons comment-string statement))
 | |
| 
 | |
| (defrule statement-list
 | |
|     := (+ simple-statement ";")
 | |
|     :reduce (if (cdr $1)
 | |
|                 (cons :statement-list $1)
 | |
|                 (car $1)))
 | |
| 
 | |
| (defrule statement
 | |
|     := statement-list eol
 | |
|     :reduce statement-list
 | |
|     := compound-statement)
 | |
| 
 | |
| (defrule simple-statement
 | |
|     := import-statement
 | |
|     := raise-statement
 | |
|     := assignment
 | |
|     := function-call
 | |
|     := return-statement
 | |
|     := assert-statement
 | |
|     := pass-statement
 | |
|     := break-statement
 | |
|     := continue-statement)
 | |
| 
 | |
| (defrule compound-statement
 | |
|     := class-definition
 | |
|     := method-definition
 | |
|     := try-statement
 | |
|     := if-statement
 | |
|     := while-statement
 | |
|     := for-statement)
 | |
| 
 | |
| (defrule import-statement
 | |
|     := "import" (+ package-name ",")
 | |
|     :tag :import
 | |
|     := "from" package-name "import" (+ symbol-name ",")
 | |
|     :tag :import-from)
 | |
| 
 | |
| (defrule package-name := identifier)
 | |
| 
 | |
| (defrule symbol-name
 | |
|     := identifier
 | |
|     := "*")
 | |
| 
 | |
| (defrule try-statement
 | |
|     := "try" ":" suite try-except-part* try-finally-part?
 | |
|     :tag :try)
 | |
| 
 | |
| (defrule try-except-part
 | |
|     := "except" exception-subject? ":" suite)
 | |
| 
 | |
| (defrule try-finally-part
 | |
|     := "finally" ":" suite)
 | |
| 
 | |
| (defrule exception-subject
 | |
|     := exception-name exception-variable?)
 | |
| 
 | |
| (defrule exception-variable
 | |
|     := "," identifier)
 | |
| 
 | |
| (defrule exception-name := class-name)
 | |
| 
 | |
| (defrule class-name := identifier)
 | |
| 
 | |
| (defrule raise-statement
 | |
|     := "raise"
 | |
|     :tag :raise-same
 | |
|     := "raise" exception-name
 | |
|     :tag :raise
 | |
|     := "raise" exception-name "," expression
 | |
|     :tag :raise
 | |
|     := "raise" exception-name "(" expression ")"
 | |
|     :tag :raise)
 | |
| 
 | |
| (defrule assignment
 | |
|     := (+ variable-with-optional-subscript ",") "=" more-assignment
 | |
|     :tag :set)
 | |
| 
 | |
| (defrule more-assignment
 | |
|     := expression
 | |
|     := assignment)
 | |
| 
 | |
| (defrule variable-with-optional-subscript
 | |
|     := variable-name subscript
 | |
|     :tag :subscript
 | |
|     := variable-name)
 | |
| 
 | |
| (defrule variable-name
 | |
|     := (+ identifier ".")
 | |
|     :tag :varef)
 | |
| 
 | |
| (defrule expression
 | |
|     := expression "or" expression1
 | |
|     :tag :or
 | |
|     := expression1)
 | |
| 
 | |
| (defrule expression1
 | |
|     := expression1 "and" expression2
 | |
|     :tag :and
 | |
|     := expression2)
 | |
| 
 | |
| (defrule expression2
 | |
|     := expression2 "==" expression3
 | |
|     :tag :equal
 | |
|     := expression2 ">=" expression3
 | |
|     :tag :more-equal
 | |
|     := expression2 "<=" expression3
 | |
|     :tag :less-equal
 | |
|     := expression2 "!=" expression3
 | |
|     :tag :not-equal
 | |
|     := expression2 ">" expression3
 | |
|     :tag :more
 | |
|     := expression2 "<" expression3
 | |
|     :tag :less
 | |
|     := expression2 "is" expression3
 | |
|     :tag :equal
 | |
|     := expression2 "is" "not" expression3
 | |
|     :tag :not-equal
 | |
|     := expression3)
 | |
| 
 | |
| (defrule expression3
 | |
|     := expression3 "+" expression4
 | |
|     :tag :plus
 | |
|     := expression3 "-" expression4
 | |
|     :tag :minus
 | |
|     := expression3 "|" expression4
 | |
|     :tag :bit-or
 | |
|     := expression4)
 | |
| 
 | |
| ;; high priority expression
 | |
| (defrule expression4
 | |
|     := expression4 "*" expression5
 | |
|     :tag :mult
 | |
|     := expression4 "/" expression5
 | |
|     :tag :div
 | |
|     := expression4 "%" expression5
 | |
|     :tag :modulo
 | |
|     := expression4 "&" expression5
 | |
|     :tag :bit-and
 | |
|     := expression4 "in" expression5
 | |
|     :tag :in
 | |
|     := expression5)
 | |
| 
 | |
| (defrule expression5
 | |
|     := "~" expression5
 | |
|     :tag :bit-not
 | |
|     := "not" expression5
 | |
|     :tag :not
 | |
|     := "(" expression ")"
 | |
|     := expression6)
 | |
| 
 | |
| (defrule expression6
 | |
|     := simple-expression subscript
 | |
|     :tag :subscript
 | |
|     := simple-expression)
 | |
| 
 | |
| (defrule simple-expression
 | |
|     := function-call
 | |
|     := variable-name
 | |
|     := constant
 | |
|     := string-conversion
 | |
|     := list-constructor)
 | |
| 
 | |
| (defrule subscript
 | |
|     := "[" expression "]"
 | |
|     := "[" expression ":" expression "]"
 | |
|     := "[" expression ":" "]"
 | |
|     :reduce (list expression nil)
 | |
|     := "[" ":" expression "]"
 | |
|     :reduce (list nil expression))
 | |
| 
 | |
| (defrule string-conversion
 | |
|     := "`" expression "`"
 | |
|     :tag :to-string)
 | |
| 
 | |
| (defrule constant
 | |
|     := number
 | |
|     := string
 | |
|     := lambda-expression)
 | |
| 
 | |
| (defrule number
 | |
|     := float
 | |
|     := integer)
 | |
| 
 | |
| (defrule list-constructor
 | |
|     := "[" (* expression ",") "]"
 | |
|     :tag :make-list)
 | |
| 
 | |
| (defrule class-definition
 | |
|     := "class" class-name superclasses? ":" commentable-suite
 | |
|     :tag :defclass)
 | |
| 
 | |
| (defrule superclasses
 | |
|     := "(" class-name+ ")")
 | |
| 
 | |
| (defrule method-definition
 | |
|     := "def" method-name "(" method-arguments ")" ":" commentable-suite
 | |
|     :tag :defmethod)
 | |
| 
 | |
| (defrule method-arguments
 | |
|     := (* method-argument ","))
 | |
| 
 | |
| (defrule method-argument
 | |
|     := identifier argument-default?)
 | |
| 
 | |
| (defrule argument-default
 | |
|     := "=" expression)
 | |
| 
 | |
| (defrule method-name := identifier)
 | |
| 
 | |
| (defrule if-statement
 | |
|     := "if" expression ":" suite elif-part* else-part?
 | |
|     :tag :if)
 | |
| 
 | |
| (defrule else-part
 | |
|     :=  "else" ":" suite)
 | |
| 
 | |
| (defrule elif-part
 | |
|     := "elif" expression ":" suite)
 | |
| 
 | |
| (defrule lambda-expression
 | |
|     := "lambda" method-arguments ":" expression
 | |
|     :tag :lambda)
 | |
| 
 | |
| (defrule function-call
 | |
|     := (+ identifier ".") "(" (* expression ",") ")"
 | |
|     :tag :funcall)
 | |
| 
 | |
| (defrule for-statement
 | |
|     := "for" identifier "in" expression ":" suite
 | |
|     :tag :do-list
 | |
|     := "for" identifier "in" "range" "(" expression "," expression ")" ":" suite
 | |
|     :tag :do-range)
 | |
| 
 | |
| (defrule while-statement
 | |
|     := "while" expression ":" suite
 | |
|     :tag :while)
 | |
| 
 | |
| (defrule return-statement
 | |
|     := "return" expression?
 | |
|     :tag :return)
 | |
| 
 | |
| (defrule assert-statement
 | |
|     := "assert" expression "," string
 | |
|     :tag :assert)
 | |
| 
 | |
| (defrule pass-statement
 | |
|     := "pass"
 | |
|     :tag :pass)
 | |
| 
 | |
| (defrule break-statement
 | |
|     := "break"
 | |
|     :tag :break)
 | |
| 
 | |
| (defrule continue-statement
 | |
|     := "continue"
 | |
|     :tag :continue)
 | |
| 
 | |
| )					; end of POPULATE-GRAMMAR
 |