;;; vs-cobol-ii.lisp --- sample grammar for VS-Cobol II ;;; Copyright (C) 2003 by Walter C. Pelissero ;;; Author: Walter C. Pelissero ;;; Project: NPG a Naive Parser Generator ;;; $Id: F-1D03709AEB30BA7644C1CFA2DF60FE8C.lisp,v 1.2 2004/03/09 10:33:07 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: ;;; ;;; A fairly incomplete VS-Cobol II grammar fro NPG. It's probably ;;; not very accurate either. #+cmu (ext:file-comment "$Id: F-1D03709AEB30BA7644C1CFA2DF60FE8C.lisp,v 1.2 2004/03/09 10:33:07 wcp Exp $") (in-package :grammar) (defun make-keyword (string) "Create a keyword from STRING." (intern (string-upcase string) :keyword)) (defun flatten-list (list) "Remove one depth level in LIST." (mapcan #'identity list)) (deflazy define-grammar (let ((*package* #.*package*) (*compile-print* (and parser::*debug* t))) (reset-grammar) (format t "creating Cobol grammar...~%") (populate-grammar) (let ((grammar (parser:generate-grammar))) (reset-grammar) (parser:print-grammar-figures grammar) grammar))) (defun populate-grammar () ;;; ;;; Hereafter PP means Partial Program ;;; #+nil (defrule pp--declarations := identification-division environment-division? data-division? "PROCEDURE" "DIVISION" using-phrase? "." :rest) ;;; We need to split the parsing of the declarations from the rest ;;; because the declarations may change the lexical rules (ie decimal ;;; point) (defrule pp--declarations := identification-division environment-division? data-division-head-or-procedure-division-head :rest) (defrule data-division-head-or-procedure-division-head := data-division-head :reduce :data-division := procedure-division-head :reduce (list :procedure-division $1)) (defrule pp--data-division := data-division-content procedure-division-head :rest) (defrule pp--sentence := sentence :rest := :eof) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; The real grammar ;;; (defrule cobol-source-program := identification-division environment-division? data-division procedure-division end-program?) (defrule identification-division := identification "DIVISION" "." program-id-cobol-source-program identification-division-content :reduce program-id-cobol-source-program) (defrule priority-number := integer) (defrule level-number := integer) (defrule to-id-or-lit := "TO" id-or-lit) (defrule inspect-by-argument := variable-identifier := string := figurative-constant-simple) (defrule figurative-constant-simple := "ZERO" :reduce :zero := "ZEROS" :reduce :zero := "ZEROES" :reduce :zero := "SPACE" :reduce :space := "SPACES" :reduce :space := "HIGH-VALUE" :reduce :high := "HIGH-VALUES" :reduce :high := "LOW-VALUE" :reduce :low := "LOW-VALUES" :reduce :low := "QUOTE" :reduce :quote := "QUOTES" :reduce :quote := "NULL" :reduce :null := "NULLS" :reduce :null) (defrule write-exceptions := at-end-of-page-statement-list? not-at-end-of-page-statement-list? invalid-key-statement-list? not-invalid-key-statement-list?) (defrule set-statement-phrase := variable-identifier+ set-oper set-src) (defrule set-src := variable-identifier := literal := "TRUE" := "ON" := "OFF") (defrule set-oper := "TO" :reduce :to := "UP" "BY" :reduce :up := "DOWN" "BY" :reduce :down) (defrule fce-phrase := reserve-clause := fce-organization := fce-access-mode := record-key-clause := password-clause := alternate-record-key-clause := file-status-clause := padding-character-clause := record-delimiter-clause) (defrule fce-organization := organization-is? alt-indexed-relative-sequential :reduce (list :organization (make-keyword alt-indexed-relative-sequential))) (defrule fce-access-mode := "ACCESS" "MODE"? "IS"? alt-sequential-random-dynamic relative-key-clause? :reduce (list :access-mode (make-keyword alt-sequential-random-dynamic))) (defrule alt-indexed-relative-sequential := "INDEXED" := "RELATIVE" := "SEQUENTIAL") (defrule is-not := "IS"? "NOT"?) (defrule all-procedures := "ALL" "PROCEDURES") (defrule next-sentence := "NEXT" "SENTENCE") (defrule no-rewind := "NO" "REWIND") (defrule for-removal := "FOR"? "REMOVAL") (defrule values := "VALUE" := "VALUES") (defrule records := "RECORD" := "RECORDS") (defrule end-program := "END" "PROGRAM" program-name ".") (defrule environment-division := "ENVIRONMENT" "DIVISION" "." environment-division-content) (defrule data-division-head := "DATA" "DIVISION" ".") (defrule data-division := data-division-head data-division-content :reduce data-division-content) (defrule identification := "IDENTIFICATION" := "ID") (defrule identification-division-content := identification-division-phrase*) (defrule author := "AUTHOR" ".") (defrule installation := "INSTALLATION" ".") (defrule date-written := "DATE-WRITTEN" ".") (defrule date-compiled := "DATE-COMPILED" ".") (defrule security := "SECURITY" ".") (defrule remarks := "REMARKS" ".") (defrule identification-division-phrase := author := installation := date-written := date-compiled := security := remarks) (defrule program-id-cobol-source-program := "PROGRAM-ID" "."? program-name initial-program? "." :reduce program-name) (defrule initial-program := "IS"? "INITIAL" "PROGRAM"?) (defrule environment-division-content := configuration-section? input-output-section?) (defrule input-output-section := "INPUT-OUTPUT" "SECTION" "." file-control-paragraph? i-o-control-paragraph? :reduce file-control-paragraph) (defrule file-control-paragraph := "FILE-CONTROL" "." file-control-entry*) (defrule file-control-entry := select-clause assign-clause fce-phrase* "." :reduce (append select-clause assign-clause (flatten-list fce-phrase))) (defrule organization-is := "ORGANIZATION" "IS"?) (defrule alt-sequential-random-dynamic := "SEQUENTIAL" := "RANDOM" := "DYNAMIC") (defrule select-clause := "SELECT" "OPTIONAL"? file-name :reduce (list file-name :optional (and $2 t))) (defrule assign-clause := "ASSIGN" "TO"? alt-assignment-name-literal+ :reduce (list :assign alt-assignment-name-literal)) (defrule alt-assignment-name-literal := assignment-name := literal) (defrule reserve-clause := "RESERVE" integer areas?) (defrule areas := "AREA" := "AREAS") (defrule padding-character-clause := "PADDING" "CHARACTER"? "IS"? alt-qualified-data-name-literal) (defrule record-delimiter-clause := "RECORD" "DELIMITER" "IS"? record-delimiter-name) (defrule record-delimiter-name := "STANDARD-1" := assignment-name) (defrule password-clause := "PASSWORD" "IS"? data-name) (defrule file-status-clause := "FILE"? "STATUS" "IS"? qualified-data-name qualified-data-name? :reduce (list :file-status qualified-data-name)) (defrule relative-key-clause := "RELATIVE" "KEY"? "IS"? qualified-data-name :reduce (list :relative-key qualified-data-name)) (defrule record-key-clause := "RECORD" "KEY"? "IS"? qualified-data-name :reduce (list :key qualified-data-name)) (defrule alternate-record-key-clause := "ALTERNATE" "RECORD"? "KEY"? "IS"? qualified-data-name password-clause? with-duplicates? :reduce (list :alternate-key qualified-data-name with-duplicates)) (defrule with-duplicates := "WITH"? "DUPLICATES") (defrule i-o-control-paragraph := "I-O-CONTROL" "." i-o-sam? i-o-sort-merge?) (defrule i-o-sam := qsam-or-sam-or-vsam-i-o-control-entries+ ".") (defrule i-o-sort-merge := sort-merge-i-o-control-entries ".") (defrule qsam-or-sam-or-vsam-i-o-control-entries := qsam-or-sam-or-vsam-i-o-control-entries-1 := qsam-or-sam-or-vsam-i-o-control-entries-2 := qsam-or-sam-or-vsam-i-o-control-entries-3 := qsam-or-sam-or-vsam-i-o-control-entries-4) (defrule qsam-or-sam-or-vsam-i-o-control-entries-1 := "RERUN" "ON" alt-assignment-name-file-name "EVERY"? every-phrase "OF"? file-name) (defrule every-phrase-1 := integer "RECORDS") (defrule every-phrase-2 := "END" "OF"? alt-reel-unit) (defrule every-phrase := every-phrase-1 := every-phrase-2) (defrule alt-assignment-name-file-name := assignment-name := file-name) (defrule qsam-or-sam-or-vsam-i-o-control-entries-2 := "SAME" "RECORD"? "AREA"? "FOR"? file-name file-name+) (defrule qsam-or-sam-or-vsam-i-o-control-entries-3 := "MULTIPLE" "FILE" "TAPE"? "CONTAINS"? file-name-position+) (defrule position := "POSITION" integer) (defrule file-name-position := file-name position?) (defrule qsam-or-sam-or-vsam-i-o-control-entries-4 := "APPLY" "WRITE-ONLY" "ON"? file-name+) (defrule sort-merge-i-o-control-entries := rerun-on? same-area+) (defrule rerun-on := "RERUN" "ON" assignment-name) (defrule record-sort := "RECORD" := "SORT" := "SORT-MERGE") (defrule same-area := "SAME" record-sort "AREA"? "FOR"? file-name file-name+) (defrule configuration-section := "CONFIGURATION" "SECTION" "." configuration-section-paragraph* :reduce (flatten-list configuration-section-paragraph)) (defrule configuration-section-paragraph := source-computer-paragraph := object-computer-paragraph := special-names-paragraph) (defrule source-computer-paragraph := "SOURCE-COMPUTER" "." source-computer-name :reduce (list :source-computer source-computer-name)) (defrule with-debugging-mode := "WITH"? "DEBUGGING" "MODE") (defrule source-computer-name := computer-name with-debugging-mode? "." :reduce computer-name) (defrule object-computer-paragraph := "OBJECT-COMPUTER" "." object-computer-name :reduce (list :object-computer object-computer-name)) (defrule memory-size-type := "WORDS" := "CHARACTERS" := "MODULES") (defrule memory-size := "MEMORY" "SIZE"? integer memory-size-type) (defrule object-computer-name := computer-name memory-size? object-computer-paragraph-sequence-phrase "." :reduce computer-name) (defrule object-computer-paragraph-sequence-phrase := program-collating-sequence? segment-limit?) (defrule program-collating-sequence := "PROGRAM"? "COLLATING"? "SEQUENCE" "IS"? alphabet-name) (defrule segment-limit := "SEGMENT-LIMIT" "IS"? priority-number) (defrule special-names-paragraph := "SPECIAL-NAMES" "." special-names-paragraph-phrase* special-names-paragraph-clause* "." :reduce (flatten-list special-names-paragraph-clause)) (defrule is-mnemonic-name := "IS"? mnemonic-name special-names-paragraph-status-phrase?) (defrule special-names-paragraph-phrase-tail := is-mnemonic-name := special-names-paragraph-status-phrase) (defrule special-names-paragraph-phrase := environment-name special-names-paragraph-phrase-tail) (defrule special-names-paragraph-status-phrase := special-names-paragraph-status-phrase-1 := special-names-paragraph-status-phrase-2) (defrule special-names-paragraph-status-phrase-1 := "ON" "STATUS"? "IS"? condition off-status?) (defrule off-status := "OFF" "STATUS"? "IS"? condition) (defrule special-names-paragraph-status-phrase-2 := "OFF" "STATUS"? "IS"? condition on-status?) (defrule on-status := "ON" "STATUS"? "IS"? condition) (defrule special-names-paragraph-clause ;; := alphabet-clause ;; := symbolic-characters-clause := currency-sign-clause := decimal-point-clause) (defrule alphabet-clause := "ALPHABET" alphabet-name "IS"? alphabet-type) (defrule alphabet-type-also := "ALSO" literal) (defrule alphabet-type-alsos := alphabet-type-also+) (defrule alphabet-type-also-through := through-literal := alphabet-type-alsos) (defrule alphabet-type-other := literal alphabet-type-also-through?) (defrule alphabet-type-others := alphabet-type-other+) (defrule alphabet-type := "STANDARD-1" := "STANDARD-2" := "NATIVE" := "EBCDIC" := alphabet-type-others) (defrule symbolic-characters-clause := "SYMBOLIC" "CHARACTERS"? symbolic-character-mapping+ in-alphabet-name?) (defrule are := "ARE" := "IS") (defrule symbolic-character-mapping := symbolic-character+ are? integer+) (defrule in-alphabet-name := "IN" alphabet-name) (defrule currency-sign-clause := "CURRENCY" "SIGN"? "IS"? literal :reduce (list :currency-sign literal)) (defrule decimal-point-clause := "DECIMAL-POINT" "IS"? "COMMA" :reduce (list :decimal-point #\,)) (defrule data-division-content := file-section? working-storage-section? linkage-section?) (defrule file-section-entry := file-and-sort-description-entry data-description-entry+ :reduce (cons file-and-sort-description-entry data-description-entry)) (defrule file-section-head := "FILE" "SECTION" ".") (defrule file-section := file-section-head file-section-entry* :reduce $2) (defrule working-storage-section-head := "WORKING-STORAGE" "SECTION" ".") (defrule working-storage-section := working-storage-section-head data-description-entry* :reduce $2) (defrule linkage-section-head := "LINKAGE" "SECTION" ".") (defrule linkage-section := linkage-section-head data-description-entry* :reduce $2) (defrule file-and-sort-description-entry := alt-fd-sd file-name file-and-sort-description-entry-clause* "." :reduce (list (make-keyword alt-fd-sd) file-name file-and-sort-description-entry-clause)) (defrule alt-fd-sd := "FD" := "SD") (defrule file-and-sort-description-entry-clause := external-clause := global-clause := block-contains-clause := record-clause := label-records-clause := value-of-clause := data-records-clause := linage-clause := recording-mode-clause := code-set-clause) (defrule integer-to := integer "TO") (defrule block-contains-clause := "BLOCK" "CONTAINS"? integer-to? integer alt-characters-records?) (defrule alt-characters-records := "CHARACTERS" := "RECORDS" := "RECORD") (defrule record-clause := "RECORD" record-clause-tail) (defrule depending-on := "DEPENDING" "ON"? data-name) (defrule record-clause-tail-1 := "CONTAINS"? integer "CHARACTERS"?) (defrule record-clause-tail-2 := "CONTAINS"? integer "TO" integer "CHARACTERS"?) (defrule record-clause-tail-3 := record-varying-phrase depending-on?) (defrule record-clause-tail := record-clause-tail-2 := record-clause-tail-1 := record-clause-tail-3) (defrule record-varying-phrase := "IS"? "VARYING" "IN"? "SIZE"? from-integer? to-integer? "CHARACTERS"?) (defrule from-integer := "FROM"? integer) (defrule to-integer := "TO" integer) (defrule label-records-clause := "LABEL" records-are label-records-clause-tail :reduce (list :label-record label-records-clause-tail)) (defrule data-names := data-name+) (defrule label-records-clause-tail := "STANDARD" :reduce :standard := "OMITTED" :reduce :omitted := data-names) (defrule value-of-clause := "VALUE" "OF" value-of-clause-tail+) (defrule alt-qualified-data-name-literal := qualified-data-name := literal) (defrule value-of-clause-tail := variable-identifier "IS"? alt-qualified-data-name-literal) (defrule data-records-clause := "DATA" records-are data-name+) (defrule records-are := records are?) (defrule linage-clause := "LINAGE" "IS"? alt-data-name-integer "LINES"? linage-footing-phrase) (defrule linage-footing-phrase := footing? lines-top? lines-bottom?) (defrule alt-data-name-integer := data-name := integer) (defrule footing := "WITH"? "FOOTING" "AT"? alt-data-name-integer) (defrule lines-top := "LINES"? "AT"? "TOP" alt-data-name-integer) (defrule lines-bottom := "LINES"? "AT"? "BOTTOM" alt-data-name-integer) (defrule recording-mode-clause := "RECORDING" "MODE"? "IS"? variable-identifier) (defrule code-set-clause := "CODE-SET" "IS"? alphabet-name) (defrule data-description-entry := level-number alt-data-name-filler? data-description-entry-clause* "." :reduce (append (list level-number alt-data-name-filler) (flatten-list data-description-entry-clause))) (defrule alt-data-name-filler := data-name := "FILLER" :reduce (list)) (defrule data-description-entry-clause := picture-clause := redefines-clause := blank-when-zero-clause := external-clause := global-clause := justified-clause := occurs-clause := sign-clause := synchronized-clause := usage-clause := renames-clause := value-clause) (defrule value-clause := "VALUE" "IS"? literal :reduce (list :value literal)) (defrule redefines-clause := "REDEFINES" data-name :reduce `(:redefines ,data-name)) (defrule blank-when-zero-clause := "BLANK" "WHEN"? zeroes :reduce '(:blank-when-zero t)) (defrule zeroes := "ZERO" := "ZEROS" := "ZEROES") (defrule external-clause := "IS"? "EXTERNAL" :reduce '(:external t)) (defrule global-clause := "IS"? "GLOBAL" :reduce '(:global t)) (defrule justified-clause := justified "RIGHT"? :reduce `(:justified ,(if $2 :right :left))) (defrule justified := "JUSTIFIED" := "JUST") (defrule occurs-clause := "OCCURS" integer "TIMES"? occurs-clause-key* indexed-by? ;; to be completed -wcp16/7/03. :reduce `(:times ,integer) := "OCCURS" integer "TO" integer "TIMES"? "DEPENDING" "ON"? qualified-data-name occurs-clause-key* indexed-by? ;; to be completed -wcp16/7/03. :reduce `(:times (,integer ,integer2 ,qualified-data-name))) (defrule occurs-clause-key := alt-ascending-descending "KEY"? "IS"? qualified-data-name+) (defrule indexed-by := "INDEXED" "BY"? index-name+) (defrule picture-clause := picture "IS"? picture-string :reduce `(:picture ,picture-string)) (defrule picture := "PICTURE" := "PIC") (defrule sign-clause := sign-is? alt-leading-trailing separate-character? :reduce `(:separate-sign ,separate-character :sign-position ,alt-leading-trailing)) (defrule sign-is := "SIGN" "IS"?) (defrule separate-character := "SEPARATE" "CHARACTER"? :reduce t) (defrule alt-leading-trailing := "LEADING" :reduce :leading := "TRAILING" :reduce :trailing) (defrule synchronized-clause := synchronized alt-left-right? :reduce `(:synchronized ,(if alt-left-right alt-left-right t))) (defrule alt-left-right := "LEFT" :reduce :left := "RIGHT" :reduce :right) (defrule synchronized := "SYNCHRONIZED" := "SYNC") (defrule usage-clause := usage-is? usage :reduce (list :encoding usage)) (defrule usage-is := "USAGE" "IS"?) (defrule usage := "BINARY" :reduce :binary := "COMP" :reduce :comp := "COMP-1" :reduce :comp1 := "COMP-2" :reduce :comp2 := "COMP-3" :reduce :comp3 := "COMP-4" :reduce :comp4 := "COMPUTATIONAL" :reduce :comp := "COMPUTATIONAL-1" :reduce :comp1 := "COMPUTATIONAL-2" :reduce :comp2 := "COMPUTATIONAL-3" :reduce :comp3 := "COMPUTATIONAL-4" :reduce :comp4 := "DISPLAY" :reduce :display := "DISPLAY-1" :reduce :display1 := "INDEX" :reduce :index := "PACKED-DECIMAL" :reduce :packed-decimal := "POINTER" :reduce :pointer) (defrule renames-clause := "RENAMES" qualified-data-name through-qualified-data-name? :reduce `(:renames ,qualified-data-name ,through-qualified-data-name)) (defrule through-qualified-data-name := through qualified-data-name :reduce qualified-data-name) (defrule condition-value-clause := values-are literal-through-literal+) (defrule through-literal := through literal) (defrule literal-through-literal := literal through-literal?) (defrule values-are := values are?) (defrule procedure-division-head := "PROCEDURE" "DIVISION" using-phrase? ".") (defrule procedure-division := procedure-division-head sentence+) (defrule using-phrase := "USING" data-name+) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defrule declaratives := "DECLARATIVES" "." declaratives-content+ "END" "DECLARATIVES" ".") (defrule declaratives-content := cobol-identifier "SECTION" "." use-statement "." sentence*) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defrule paragraph-header := cobol-identifier "SECTION"? :reduce (list (if $2 :section :label) $1)) (defrule sentence := declaratives := statement* "." :reduce $1 := paragraph-header "." :reduce $1) (defrule statement := move-statement := if-statement := perform-statement := go-to-statement := accept-statement := add-statement := alter-statement := call-statement := cancel-statement := close-statement := compute-statement := continue-statement := delete-statement := display-statement := divide-statement := entry-statement := evaluate-statement := exit-program-statement := exit-statement := goback-statement := initialize-statement := inspect-statement := merge-statement := multiply-statement := open-statement := read-statement := release-statement := return-statement := rewrite-statement := search-statement := set-statement := sort-statement := start-statement := stop-statement := string-statement := subtract-statement := unstring-statement := write-statement := paragraph-header) (defrule accept-statement := "ACCEPT" variable-identifier "FROM" date := "ACCEPT" variable-identifier "AT" screen-coordinates :reduce (apply #'list 'accept-at variable-identifier screen-coordinates) := "ACCEPT" variable-identifier from-environment-name?) (defrule from-environment-name := "FROM" cobol-identifier) (defrule date := "DATE" := "DAY" := "DAY-OF-WEEK" := "TIME") (defrule add-statement := "ADD" id-or-lit+ to-id-or-lit? "GIVING" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-ADD"? := "ADD" id-or-lit+ "TO" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-ADD"? := "ADD" corresponding variable-identifier "TO" variable-identifier "ROUNDED"? on-size-error-statement-list? not-on-size-error-statement-list? "END-ADD"?) (defrule statement-list := statement+) (defrule alter-statement := "ALTER" procedure-to-procedure+) (defrule proceed-to := "PROCEED" "TO") (defrule procedure-to-procedure := procedure-name "TO" proceed-to? procedure-name) (defrule call-statement := "CALL" id-or-lit using-parameters? call-rest-phrase "END-CALL"? :reduce (list 'call id-or-lit (cons 'list using-parameters))) (defrule by-reference := "BY"? "REFERENCE") (defrule content-parameter-value := cobol-identifier := literal) (defrule reference-parameter := by-reference? variable-identifier) (defrule content-parameter := "BY"? "CONTENT" content-parameter-value+) (defrule parameter := reference-parameter := content-parameter := literal) (defrule using-parameters := "USING" parameter+) (defrule call-rest-phrase := on-exception-statement-list? not-on-exception-statement-list? on-overflow-statement-list?) (defrule on-exception-statement-list := "ON"? "EXCEPTION" statement-list) (defrule not-on-exception-statement-list := "NOT" "ON"? "EXCEPTION" statement-list) (defrule cancel-statement := "CANCEL" id-or-lit+) (defrule close-statement := "CLOSE" close-statement-file-name+ :reduce (list 'close close-statement-file-name)) (defrule alt-removal-no-rewind := for-removal := with-no-rewind) (defrule alt-reel-unit := "REEL" := "UNIT") (defrule alt-no-rewind-lock := no-rewind := "LOCK") (defrule close-statement-options-1 := alt-reel-unit alt-removal-no-rewind?) (defrule close-statement-options-2 := "WITH"? alt-no-rewind-lock) (defrule close-statement-options := close-statement-options-1 := close-statement-options-2) (defrule close-statement-file-name := file-name close-statement-options?) (defrule compute-statement := "COMPUTE" cobword-rounded+ equal arithmetic-expression on-size-error-statement-list? not-on-size-error-statement-list? "END-COMPUTE"? :reduce (list 'compute cobword-rounded arithmetic-expression :on-size-error on-size-error-statement-list :not-on-size-error not-on-size-error-statement-list)) (defrule equal := "=" := "EQUAL") (defrule continue-statement := "CONTINUE") (defrule delete-statement := "DELETE" file-name "RECORD"? invalid-key-statement-list? not-invalid-key-statement-list? "END-DELETE"? :reduce (list 'delete file-name :invalid invalid-key-statement-list :not-invalid not-invalid-key-statement-list)) (defrule display-statement := "DISPLAY" id-or-lit+ upon-environment-name? with-no-advancing? :reduce (list 'display (cons 'list id-or-lit) :upon upon-environment-name :advance (not with-no-advancing)) := "DISPLAY" id-or-lit "AT" screen-coordinates :reduce (apply #'list 'display-at id-or-lit screen-coordinates)) (defrule screen-coordinates := integer :reduce (multiple-value-list (truncate integer 100))) (defrule upon-environment-name := "UPON" cobol-identifier) (defrule with-no-advancing := "WITH"? "NO" "ADVANCING") (defrule divide-statement := "DIVIDE" id-or-lit "INTO" id-or-lit "GIVING" variable-identifier "ROUNDED"? "REMAINDER" variable-identifier on-size-error-statement-list? not-on-size-error-statement-list? "END-DIVIDE"? := "DIVIDE" id-or-lit "BY" id-or-lit "GIVING" variable-identifier "ROUNDED"? "REMAINDER" variable-identifier on-size-error-statement-list? not-on-size-error-statement-list? "END-DIVIDE"? := "DIVIDE" id-or-lit "INTO" id-or-lit "GIVING" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-DIVIDE"? := "DIVIDE" id-or-lit "BY" id-or-lit "GIVING" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-DIVIDE"? := "DIVIDE" id-or-lit "INTO" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-DIVIDE"?) (defrule entry-statement := "ENTRY" literal using-phrase?) (defrule evaluate-statement := "EVALUATE" evaluate-condition also-phrase* when-phrases+ when-other-phrase? "END-EVALUATE"?) (defrule evaluate-condition := condition := "TRUE" := "FALSE") (defrule also-phrase := "ALSO" evaluate-condition) (defrule when-phrase-also-phrase := "ALSO" evaluate-phrase) (defrule when-phrase := "WHEN" evaluate-phrase when-phrase-also-phrase*) (defrule when-phrases := when-phrase+ statement-list) (defrule when-other-phrase := "WHEN" "OTHER" statement-list) (defrule evaluate-phrase := "ANY" := condition := "TRUE" := "FALSE" := evaluate-phrase-1) (defrule evaluate-phrase-1 := "NOT"? arithmetic-expression through-arithmetic-expression?) (defrule through-arithmetic-expression := through arithmetic-expression) (defrule exit-statement := "EXIT" :reduce '(exit-paragraph)) (defrule exit-program-statement := "EXIT" "PROGRAM" :reduce '(exit-program)) (defrule goback-statement := "GOBACK" :reduce '(go-back)) (defrule go-to-statement := "GO" "TO"? procedure-name+ "DEPENDING" "ON"? variable-identifier :reduce (list 'goto-depending variable-identifier procedure-name) := "GO" "TO"? procedure-name :reduce (list 'goto procedure-name)) (defrule if-phrase := "IF" condition "THEN"? alt-statement-list-next-sentence "ELSE" alt-statement-list-next-sentence :reduce (list 'if condition (if (cdr alt-statement-list-next-sentence) (cons 'progn alt-statement-list-next-sentence) (car alt-statement-list-next-sentence)) (if (cdr alt-statement-list-next-sentence2) (cons 'progn alt-statement-list-next-sentence2) (car alt-statement-list-next-sentence2))) := "IF" condition "THEN"? alt-statement-list-next-sentence :reduce (append (list 'when condition) alt-statement-list-next-sentence)) (defrule if-statement := if-phrase "END-IF"? :reduce $1) (defrule initialize-statement := "INITIALIZE" variable-identifier+ initialize-replacing-phrase?) (defrule initialize-replacing-type := "ALPHABETIC" := "ALPHANUMERIC" := "NUMERIC" := "ALPHANUMERIC-EDITED" := "NUMERIC-EDITED" := "DBCS" := "EGCS") (defrule initialize-replacing-argument := initialize-replacing-type "DATA"? "BY" id-or-lit) (defrule initialize-replacing-phrase := "REPLACING" initialize-replacing-argument+) (defrule inspect-statement := inspect-statement-1 := inspect-statement-2 := inspect-statement-3 := inspect-statement-4) (defrule inspect-statement-1 := "INSPECT" variable-identifier "TALLYING" tallying-argument+) (defrule inspect-statement-2 := "INSPECT" variable-identifier "CONVERTING" id-or-lit "TO" id-or-lit before-after-phrase*) (defrule inspect-statement-3 := "INSPECT" variable-identifier "TALLYING" tallying-argument+ "REPLACING" inspect-replacing-phrase+) (defrule tallying-for-id-or-lit := id-or-lit before-after-phrase*) (defrule alt-all-leading := "ALL" := "LEADING") (defrule tallying-for-argument-1 := "CHARACTERS" before-after-phrase*) (defrule tallying-for-argument-2 := alt-all-leading tallying-for-id-or-lit+) (defrule tallying-for-argument := tallying-for-argument-1 := tallying-for-argument-2) (defrule tallying-argument := variable-identifier "FOR" tallying-for-argument+) (defrule inspect-statement-4 := "INSPECT" variable-identifier "REPLACING" inspect-replacing-phrase+) (defrule inspect-replacing-argument := inspect-by-argument "BY" inspect-by-argument before-after-phrase*) (defrule alt-all-leading-first := "ALL" := "LEADING" := "FIRST") (defrule inspect-replacing-phrase-1 := "CHARACTERS" "BY" id-or-lit before-after-phrase*) (defrule inspect-replacing-phrase-2 := alt-all-leading-first inspect-replacing-argument+) (defrule inspect-replacing-phrase := inspect-replacing-phrase-1 := inspect-replacing-phrase-2) (defrule before-after-phrase := alt-before-after "INITIAL"? id-or-lit) (defrule merge-statement := "MERGE" file-name on-key-phrase+ collating-sequence? "USING" file-name file-name+ merge-statement-tail) (defrule on-key-phrase := "ON"? alt-ascending-descending "KEY"? qualified-data-name+) (defrule merge-statement-tail := output-procedure := giving-file-names) (defrule move-statement := "MOVE" id-or-lit "TO" variable-identifier+ :reduce (apply #'list 'move id-or-lit variable-identifier) := "MOVE" corresponding variable-identifier "TO" variable-identifier+ :reduce (apply #'list 'move-corresponding variable-identifier variable-identifier2)) (defrule multiply-statement := "MULTIPLY" id-or-lit "BY" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-MULTIPLY"? :reduce (list 'multiply id-or-lit cobword-rounded :on-size-error on-size-error-statement-list :not-on-size-error not-on-size-error-statement-list) := "MULTIPLY" id-or-lit "BY" id-or-lit "GIVING" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-MULTIPLY"? :reduce (list 'multiply id-or-lit id-or-lit2 :giving cobword-rounded :on-size-error on-size-error-statement-list :not-on-size-error not-on-size-error-statement-list)) (defrule open-statement := "OPEN" open-statement-phrase+ :reduce (list 'open open-statement-phrase)) (defrule alt-reversed-with-no-rewind := "REVERSED" := with-no-rewind) (defrule open-statement-input-file-name := file-name alt-reversed-with-no-rewind?) (defrule with-no-rewind := "WITH"? "NO" "REWIND") (defrule open-statement-output-file-name := file-name with-no-rewind?) (defrule open-statement-input := "INPUT" open-statement-input-file-name+) (defrule open-statement-output := "OUTPUT" open-statement-output-file-name+) (defrule open-statement-i-o := "I-O" file-name+) (defrule open-statement-extend := "EXTEND" file-name+) (defrule open-statement-phrase := open-statement-input := open-statement-output := open-statement-i-o := open-statement-extend) (defrule perform-statement := "PERFORM" procedure-name through-procedure-name? perform-until-phrase :reduce `(perform-until ,procedure-name ,through-procedure-name ,perform-until-phrase) := "PERFORM" procedure-name through-procedure-name? perform-varying-phrase perform-after-phrase* :reduce `(perform-varying ,perform-varying-phrase ,procedure-name ,through-procedure-name ,perform-after-phrase) := "PERFORM" procedure-name through-procedure-name? cobword-int "TIMES" :reduce `(perform-times ,cobword-int ,procedure-name ,through-procedure-name) := "PERFORM" procedure-name through-procedure-name? :reduce (append (list 'perform procedure-name) through-procedure-name)) (defrule perform-varying-phrase := with-test? "VARYING" variable-identifier "FROM" id-or-lit "BY" id-or-lit "UNTIL" condition) (defrule perform-after-phrase := "AFTER" variable-identifier "FROM" id-or-lit "BY" id-or-lit "UNTIL" condition) (defrule perform-until-phrase := with-test? "UNTIL" condition) (defrule with-test := "WITH"? "TEST" alt-before-after :reduce alt-before-after) (defrule read-statement := "READ" file-name "NEXT"? "RECORD"? into-identifier? key-is-qualified-data-name? invalid-key-statement-list? not-invalid-key-statement-list? at-end-statement-list? not-at-end-statement-list? "END-READ"?) (defrule key-is-qualified-data-name := "KEY" "IS"? qualified-data-name) (defrule release-statement := "RELEASE" record-name from-identifier?) (defrule return-statement := "RETURN" file-name "RECORD"? into-identifier? "AT"? "END" statement-list not-at-end-statement-list? "END-RETURN"?) (defrule into-identifier := "INTO" variable-identifier) (defrule not-at-end-statement-list := "NOT" "AT"? "END" statement-list) (defrule rewrite-statement := "REWRITE" record-name from-identifier? invalid-key-statement-list? not-invalid-key-statement-list? "END-REWRITE"?) (defrule search-statement := search-statement-1 := search-statement-2) (defrule search-statement-1 := "SEARCH" cobol-identifier varying-identifier? at-end-statement-list? when-condition-stats+ "END-SEARCH"?) (defrule varying-identifier := "VARYING" variable-identifier) (defrule when-condition-stats := "WHEN" condition alt-statement-list-next-sentence) (defrule search-statement-2 := "SEARCH" "ALL" variable-identifier at-end-statement-list? "WHEN" search-statement-condition search-statement-condition-tail* alt-statement-list-next-sentence "END-SEARCH"?) (defrule at-end-statement-list := "AT"? "END" statement-list) (defrule search-statement-equal-expression := variable-identifier "IS"? equal-to arithmetic-expression :reduce (list '= variable-identifier arithmetic-expression)) (defrule search-statement-condition := search-statement-equal-expression := condition-name-reference) (defrule search-statement-condition-tail := "AND" search-statement-condition) (defrule alt-statement-list-next-sentence := statement+ := next-sentence :reduce :next-sentence) (defrule set-statement := "SET" set-statement-phrase+) (defrule sort-statement := "SORT" file-name on-key-is-phrase+ with-duplicates-in-order? collating-sequence? sort-statement-in sort-statement-out) (defrule key-is := "KEY" "IS"?) (defrule alt-ascending-descending := "ASCENDING" := "DESCENDING") (defrule on-key-is-phrase := "ON"? alt-ascending-descending key-is? qualified-data-name+) (defrule with-duplicates-in-order := "WITH"? "DUPLICATES" "IN"? "ORDER"?) (defrule collating-sequence := "COLLATING"? "SEQUENCE" "IS"? alphabet-name) (defrule through := "THROUGH" := "THRU") (defrule through-procedure-name := through procedure-name :reduce procedure-name) (defrule using-file-names := "USING" file-name+) (defrule input-procedure := "INPUT" "PROCEDURE" "IS"? procedure-name through-procedure-name?) (defrule giving-file-names := "GIVING" file-name+) (defrule output-procedure := "OUTPUT" "PROCEDURE" "IS"? procedure-name through-procedure-name?) (defrule sort-statement-in := using-file-names := input-procedure) (defrule sort-statement-out := giving-file-names := output-procedure) (defrule start-statement := "START" file-name key-is-rel-op-qualified-data-name? invalid-key-statement-list? not-invalid-key-statement-list? "END-START"?) (defrule rel-op := equal-to :reduce '= := greater-than :reduce '> := greater-equal :reduce '>=) (defrule key-is-rel-op-qualified-data-name := "KEY" "IS"? rel-op qualified-data-name :reduce (list rel-op qualified-data-name)) (defrule stop-statement := "STOP" alt-run-literal :reduce '(stop)) (defrule alt-run-literal := "RUN" := literal) (defrule string-statement := "STRING" delimited-by-phrase+ "INTO" variable-identifier with-pointer-identifier? on-overflow-statement-list? not-on-overflow-statement-list? "END-STRING"? :reduce (list 'string-concat delimited-by-phrase variable-identifier :with-pointer with-pointer-identifier :on-overflow on-overflow-statement-list :not-on-overflow not-on-overflow-statement-list)) (defrule id-or-lit-size := literal := variable-identifier := "SIZE") (defrule delimited-by-phrase := id-or-lit+ "DELIMITED" "BY"? id-or-lit-size :reduce (list id-or-lit id-or-lit-size)) (defrule subtract-statement := "SUBTRACT" id-or-lit+ "FROM" id-or-lit "GIVING" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-SUBTRACT"? :reduce (list 'subtract-giving id-or-lit id-or-lit2 cobword-rounded :on-size-error on-size-error-statement-list :not-on-size-error not-on-size-error-statement-list) := "SUBTRACT" id-or-lit+ "FROM" cobword-rounded+ on-size-error-statement-list? not-on-size-error-statement-list? "END-SUBTRACT"? :reduce (list 'subtract id-or-lit cobword-rounded :on-size-error on-size-error-statement-list :not-on-size-error not-on-size-error-statement-list) := "SUBTRACT" corresponding variable-identifier "FROM" variable-identifier "ROUNDED"? on-size-error-statement-list? not-on-size-error-statement-list? "END-SUBTRACT"? :reduce (list 'subtract-corr variable-identifier variable-identifier :rounded (and $5 t) :on-size-error on-size-error-statement-list :not-on-size-error not-on-size-error-statement-list)) (defrule cobword-rounded := variable-identifier "ROUNDED"? :reduce (list variable-identifier (and $2 t))) (defrule on-size-error-statement-list := "ON"? "SIZE" "ERROR" statement-list :reduce statement-list) (defrule not-on-size-error-statement-list := "NOT" "ON"? "SIZE" "ERROR" statement-list :reduce statement-list) (defrule corresponding := "CORRESPONDING" := "CORR") (defrule unstring-statement := "UNSTRING" variable-identifier delimited-by-all-phrase? "INTO" unstring-statement-dst+ with-pointer-identifier? tallying-in-identifier? on-overflow-statement-list? not-on-overflow-statement-list? "END-UNSTRING"? :reduce (list 'unstring variable-identifier unstring-statement-dst :delimited-by-all delimited-by-all-phrase :with-pointer with-pointer-identifier :tallying tallying-in-identifier :on-overflow on-overflow-statement-list :not-on-overflow not-on-overflow-statement-list)) (defrule id-or-lit := literal := variable-identifier) (defrule or-all-id-or-lit := "OR" "ALL"? id-or-lit) (defrule delimited-by-all-phrase := "DELIMITED" "BY"? "ALL"? id-or-lit or-all-id-or-lit*) (defrule delimiter-in-identifier := "DELIMITER" "IN"? variable-identifier) (defrule count-in-identifier := "COUNT" "IN"? variable-identifier) (defrule unstring-statement-dst := variable-identifier delimiter-in-identifier? count-in-identifier?) (defrule with-pointer-identifier := "WITH"? "POINTER" variable-identifier) (defrule tallying-in-identifier := "TALLYING" "IN"? variable-identifier) (defrule on-overflow-statement-list := "ON"? "OVERFLOW" statement-list) (defrule not-on-overflow-statement-list := "NOT" "ON"? "OVERFLOW" statement-list) (defrule write-statement := "WRITE" record-name from-identifier? advancing-phrase? write-exceptions "END-WRITE"?) (defrule lines := "LINE" := "LINES") (defrule cobword-int := cobol-identifier := integer) (defrule nr-lines-phrase := cobword-int lines?) (defrule page-phrase := nr-lines-phrase := "PAGE") (defrule alt-before-after := "BEFORE" := "AFTER") (defrule advancing-phrase := alt-before-after "ADVANCING"? page-phrase) (defrule from-identifier := "FROM" variable-identifier) (defrule invalid-key-statement-list := "INVALID" "KEY"? statement-list :reduce statement-list) (defrule not-invalid-key-statement-list := "NOT" "INVALID" "KEY"? statement-list :reduce statement-list) (defrule end-of-page := "END-OF-PAGE" := "EOP") (defrule at-end-of-page-statement-list := "AT"? end-of-page statement-list :reduce statement-list) (defrule not-at-end-of-page-statement-list := "NOT" "AT"? end-of-page statement-list :reduce statement-list) ;; This is left in the grammar but is not used. COPYs are handled by ;; the lexical scanner. (defrule copy-statement := "COPY" alt-text-name-literal in-library? "SUPPRESS"? copy-statement-replacing-phrase?) (defrule in := "OF" := "IN") (defrule alt-library-name-literal := library-name := literal) (defrule in-library := in alt-library-name-literal) (defrule copy-statement-by-phrase := copy-operand "BY" copy-operand) (defrule copy-statement-replacing-phrase := "REPLACING" copy-statement-by-phrase+) (defrule alt-text-name-literal := text-name := literal) (defrule copy-operand := cobol-identifier := literal) (defrule use-statement := use-statement-1 := use-statement-2 := use-statement-3) (defrule use-statement-1 := "USE" "GLOBAL"? "AFTER" "STANDARD"? alt-exception-error "PROCEDURE" "ON"? alt-file-names-i-o) (defrule alt-exception-error := "EXCEPTION" := "ERROR") (defrule use-statement-2 := "USE" "GLOBAL"? "AFTER" "STANDARD"? alt-beginning-ending? alt-file-reel-unit? "LABEL" "PROCEDURE" "ON"? alt-file-names-i-o) (defrule alt-beginning-ending := "BEGINNING" := "ENDING") (defrule alt-file-reel-unit := "FILE" := "REEL" := "UNIT") (defrule file-names := file-name+) (defrule alt-file-names-i-o := file-names := "INPUT" := "OUTPUT" := "I-O" := "EXTEND") (defrule use-statement-3 := "USE" "FOR"? "DEBUGGING" "ON"? alt-procedures-all-procedures) (defrule procedure-names := procedure-name+) (defrule alt-procedures-all-procedures := procedure-names := all-procedures) (defrule condition := combinable-condition := combinable-condition "AND" condition :reduce `(and ,combinable-condition ,condition) := combinable-condition "OR" condition :reduce `(or ,combinable-condition ,condition) := combinable-condition "AND" id-or-lit :reduce `(and ,combinable-condition (,(car combinable-condition) ,(cadr combinable-condition) ,id-or-lit)) := combinable-condition "OR" id-or-lit :reduce `(or ,combinable-condition (,(car combinable-condition) ,(cadr combinable-condition) ,id-or-lit))) (defrule combinable-condition := "NOT"? simple-condition :reduce (if $1 (list 'not simple-condition) simple-condition)) (defrule simple-condition := class-condition := relation-condition := sign-condition := "(" condition ")" ;; not sure if it's necessary -wcp15/7/03. ;; := arithmetic-expression ) (defrule class-condition := variable-identifier "IS"? "NOT"? class-type :reduce (if $3 (list 'not (list 'type-of variable-identifier (make-keyword class-type))) (list 'type-of variable-identifier (make-keyword class-type)))) (defrule class-type := "NUMERIC" := "ALPHABETIC" := "ALPHABETIC-LOWER" := "ALPHABETIC-UPPER" := "DBCS") (defun unfold-subrelations (main-relation subs) (destructuring-bind (main-operator main-variable other-variable) main-relation (declare (ignore other-variable)) (labels ((unfold (subs) (if (null subs) main-relation (destructuring-bind (connection operator variable) (car subs) (list connection (list (or operator main-operator) main-variable variable) (unfold (cdr subs))))))) (unfold subs)))) (defrule relation-condition ;; This is too complex ;; := arithmetic-expression relational-operator simple-condition := id-or-lit relational-operator id-or-lit subordinate-relation* :reduce (unfold-subrelations (list relational-operator id-or-lit id-or-lit2) subordinate-relation)) (defrule or-and := "OR" :reduce 'or := "AND" :reduce 'and) (defrule subordinate-relation := or-and relational-operator? id-or-lit :reduce (list or-and relational-operator id-or-lit)) (defrule relational-operator := "IS"? relational-operator-type :reduce relational-operator-type) (defrule less-than := "LESS" "THAN"? := "<") (defrule greater-equal := "GREATER" "THAN"? "OR" "EQUAL" "TO"? := ">=" := ">" "=" := "NOT" "<" := "NOT" "LESS" "THAN"?) (defrule less-equal := "LESS" "THAN"? "OR" "EQUAL" "TO"? := "<=" := "<" "=" := "NOT" ">" := "NOT" "GREATER" "THAN"?) (defrule greater-than := "GREATER" "THAN"? := ">") (defrule equal-to := "EQUAL" "TO"? := "=") (defrule relational-operator-type := greater-equal :reduce 'cob>= := less-equal :reduce 'cob<= := greater-than :reduce 'cob> := less-than :reduce 'cob< := equal-to :reduce 'cob= := "NOT" equal-to :reduce 'cob-not=) (defrule sign-condition := arithmetic-expression "IS"? "NOT"? sign-type :reduce (if $3 `(not (,sign-type ,arithmetic-expression)) `(,sign-type ,arithmetic-expression))) (defrule sign-type := "POSITIVE" :reduce '> := "NEGATIVE" :reduce '< := "ZERO" :reduce '= := "ZEROES" :reduce '= := "ZEROS" :reduce '=) (defrule procedure-name := paragraph-or-section-name in-section-name :reduce (list paragraph-or-section-name in-section-name) := paragraph-or-section-name :reduce paragraph-or-section-name) (defrule in-section-name := in cobol-identifier :reduce cobol-identifier) (defrule variable-identifier := qualified-data-name subscript-parentheses* ;; reference-modification? :reduce (if subscript-parentheses (list :aref qualified-data-name subscript-parentheses) qualified-data-name)) (defrule reference-modification := "(" leftmost-character-position ":" length? ")" :reduce (if length (list :range leftmost-character-position length) leftmost-character-position)) (defrule condition-name-reference := condition-name in-data-or-file-or-mnemonic-name* subscript-parentheses*) (defrule in-data-or-file-or-mnemonic-name := in data-or-file-or-mnemonic-name) (defrule subscript-parentheses := "(" subscript ")") (defrule subscript := subscript-expression+) (defrule plus-minus-integer := plus-or-minus integer) (defrule subscript-expression-ambiguous := qualified-data-name plus-minus-integer?) (defrule subscript-expression := literal := subscript-expression-ambiguous) (defrule qualified-data-name := data-name in-data-or-file-name* :reduce (if in-data-or-file-name (list data-name in-data-or-file-name) ; incomplete -wcp15/7/03. data-name) := "ADDRESS" "OF" data-name :reduce (list 'address-of data-name) := "LENGTH" "OF" cobol-identifier :reduce (list 'length-of cobol-identifier)) (defrule in-data-or-file-name := in data-or-file-name) (defrule leftmost-character-position := arithmetic-expression) (defrule length := arithmetic-expression) (defrule arithmetic-expression := times-div := times-div "+" arithmetic-expression :reduce `(+ ,times-div ,arithmetic-expression) := times-div "-" arithmetic-expression :reduce `(- ,times-div ,arithmetic-expression)) (defrule times-div := power := power "*" times-div :reduce `(* ,power ,times-div) := power "/" times-div :reduce `(/ ,power ,times-div)) (defrule power := plus-or-minus? basis := plus-or-minus? basis "**" power :reduce (if plus-or-minus `(plus-or-minus (expt basis basis2)) `(expt basis basis2))) (defrule plus-or-minus := "+" :reduce '+ := "-" :reduce '-) ;; (defrule power-tail ;; := "**" basis) (defrule basis := literal := variable-identifier := "(" arithmetic-expression ")") (defrule alphabet-name := cobol-identifier) (defrule condition-name := cobol-identifier) (defrule data-name := cobol-identifier) (defrule cobol-identifier := identifier :reduce (intern (string-upcase identifier))) (defrule file-name := cobol-identifier) (defrule data-or-file-name := cobol-identifier) (defrule index-name := cobol-identifier) (defrule mnemonic-name := cobol-identifier) (defrule data-or-file-or-mnemonic-name := cobol-identifier) (defrule record-name := qualified-data-name) (defrule symbolic-character := cobol-identifier) (defrule library-name := cobol-identifier) (defrule program-name := cobol-identifier := string) (defrule text-name := cobol-identifier) (defrule paragraph-or-section-name := cobol-identifier := integer) (defrule computer-name := identifier) (defrule environment-name := cobol-identifier) (defrule assignment-name := cobol-identifier) (defrule figurative-constant := figurative-constant-simple := figurative-constant-all) (defrule figurative-constant-all := "ALL" literal) (defrule literal := string := float := integer := figurative-constant) ) ; defun populate-grammar