Added support for excluding some nonterminals from grammar

This commit is contained in:
waldemar%netscape.com 1999-02-10 06:39:58 +00:00
Родитель c37ccfbc4c
Коммит 331b7966a8
8 изменённых файлов: 162 добавлений и 64 удалений

Просмотреть файл

@ -2126,7 +2126,8 @@
(grammar preprocess-grammar)
(lexer preprocess-lexer)
(grammar-argument preprocess-grammar-argument)
(production preprocess-production))
(production preprocess-production)
(exclude preprocess-exclude))
(:macro
(let expand-let depict-let)
@ -2532,6 +2533,7 @@
(parametrization nil :type (or null grammar-parametrization)) ;Parametrization of the grammar being accumulated or nil if none
(start-symbol nil :type symbol) ;Start symbol of the grammar being accumulated or nil if none
(grammar-source-reverse nil :type list) ;List of productions in the grammar being accumulated (in reverse order)
(excluded-nonterminals-source nil :type list) ;List of nonterminals to be excluded from the grammar
(charclasses-source nil) ;List of charclasses in the lexical grammar being accumulated
(lexer-actions-source nil) ;List of lexer actions in the lexical grammar being accumulated
(grammar-infos-reverse nil :type list)) ;List of grammar-infos already completed (in reverse order)
@ -2551,12 +2553,16 @@
(and kind
(let ((parametrization (preprocessor-state-parametrization preprocessor-state))
(start-symbol (preprocessor-state-start-symbol preprocessor-state))
(grammar-source (nreverse (preprocessor-state-grammar-source-reverse preprocessor-state))))
(grammar-source (nreverse (preprocessor-state-grammar-source-reverse preprocessor-state)))
(excluded-nonterminals-source (preprocessor-state-excluded-nonterminals-source preprocessor-state)))
(multiple-value-bind (grammar lexer extra-commands)
(ecase kind
(:grammar
(values (make-and-compile-grammar (preprocessor-state-kind2 preprocessor-state)
parametrization start-symbol grammar-source)
parametrization
start-symbol
grammar-source
excluded-nonterminals-source)
nil
nil))
(:lexer
@ -2565,7 +2571,10 @@
(preprocessor-state-kind2 preprocessor-state)
(preprocessor-state-charclasses-source preprocessor-state)
(preprocessor-state-lexer-actions-source preprocessor-state)
parametrization start-symbol grammar-source)
parametrization
start-symbol
grammar-source
excluded-nonterminals-source)
(values (lexer-grammar lexer) lexer extra-commands))))
(let ((grammar-info (make-grammar-info (preprocessor-state-name preprocessor-state) grammar lexer)))
(setf (preprocessor-state-kind preprocessor-state) nil)
@ -2574,6 +2583,7 @@
(setf (preprocessor-state-parametrization preprocessor-state) nil)
(setf (preprocessor-state-start-symbol preprocessor-state) nil)
(setf (preprocessor-state-grammar-source-reverse preprocessor-state) nil)
(setf (preprocessor-state-excluded-nonterminals-source preprocessor-state) nil)
(setf (preprocessor-state-charclasses-source preprocessor-state) nil)
(setf (preprocessor-state-lexer-actions-source preprocessor-state) nil)
(push grammar-info (preprocessor-state-grammar-infos-reverse preprocessor-state))
@ -2745,3 +2755,15 @@
actions))
t))
; (exclude <lhs> ... <lhs>)
; ==>
; grammar excluded nonterminals:
; <lhs> ... <lhs>;
(defun preprocess-exclude (preprocessor-state command &rest excluded-nonterminals-source)
(declare (ignore command))
(preprocess-ensure-grammar preprocessor-state)
(setf (preprocessor-state-excluded-nonterminals-source preprocessor-state)
(append excluded-nonterminals-source (preprocessor-state-excluded-nonterminals-source preprocessor-state)))
(values nil nil))

Просмотреть файл

@ -944,9 +944,7 @@
(multiple-value-bind (lhs-nonterminal lhs-arguments) (grammar-parametrization-intern grammar-parametrization production-lhs-source)
(list lhs-nonterminal
(mapcar #'(lambda (grammar-symbol-source)
(if (consp grammar-symbol-source)
(grammar-parametrization-intern grammar-parametrization grammar-symbol-source lhs-arguments)
grammar-symbol-source))
(grammar-parametrization-intern grammar-parametrization grammar-symbol-source lhs-arguments))
production-rhs-source)
production-name))
production-source)))
@ -963,7 +961,11 @@
; of the lhs nonterminal. The lhs nonterminal must not have duplicate arguments. The lhs
; nonterminal can have attributes, thereby designating a specialization instead of a fully
; generic production.
(defun make-grammar (grammar-parametrization start-symbol grammar-source)
;
; excluded-nonterminals-source is a list of nonterminals not used in the grammar. Productions,
; including productions expanded from generic productions, that have one of these nonterminals
; on the lhs are ignored.
(defun make-grammar (grammar-parametrization start-symbol grammar-source &optional excluded-nonterminals-source)
(let ((interned-grammar-source
(mapcar #'(lambda (production-source)
(intern-production-source grammar-parametrization production-source))
@ -972,7 +974,14 @@
(terminals-hash (make-hash-table :test *grammar-symbol-=*))
(general-productions (make-hash-table :test #'equal))
(production-number 0)
(max-production-length 1))
(max-production-length 1)
(excluded-nonterminals-hash (make-hash-table :test *grammar-symbol-=*)))
;Set up excluded-nonterminals-hash. The values of the hash table are either :seen or :unseen
;depending on whether a production with the particular nonterminal has been seen yet.
(dolist (excluded-nonterminal-source excluded-nonterminals-source)
(setf (gethash (grammar-parametrization-intern grammar-parametrization excluded-nonterminal-source nil) excluded-nonterminals-hash)
:unseen))
;Create the starting production: *start-nonterminal* ==> start-symbol
(setf (gethash *start-nonterminal* rules)
@ -985,7 +994,11 @@
(push production (gethash lhs rules))
(dolist (rhs-terminal (production-terminals production))
(setf (gethash rhs-terminal terminals-hash) t))
production)))
production))
(nonterminal-excluded (nonterminal)
(and (gethash nonterminal excluded-nonterminals-hash)
(setf (gethash nonterminal excluded-nonterminals-hash) :seen))))
(dolist (production-source interned-grammar-source)
(let* ((production-lhs (first production-source))
@ -995,23 +1008,29 @@
(setq max-production-length (max max-production-length (length production-rhs)))
(when (gethash production-name general-productions)
(error "Duplicate production name ~S" production-name))
(setf (gethash production-name general-productions)
(if lhs-arguments
(let ((productions nil))
(grammar-parametrization-each-permutation
grammar-parametrization
#'(lambda (bound-argument-alist)
(push (create-production
(instantiate-general-grammar-symbol bound-argument-alist production-lhs)
(mapcar #'(lambda (general-grammar-symbol)
(instantiate-general-grammar-symbol bound-argument-alist general-grammar-symbol))
production-rhs)
production-name)
productions))
lhs-arguments)
(make-generic-production production-lhs production-rhs production-name (nreverse productions)))
(create-production production-lhs production-rhs production-name))))))
(if lhs-arguments
(let ((productions nil))
(grammar-parametrization-each-permutation
grammar-parametrization
#'(lambda (bound-argument-alist)
(let ((instantiated-lhs (instantiate-general-grammar-symbol bound-argument-alist production-lhs)))
(unless (nonterminal-excluded instantiated-lhs)
(push (create-production
instantiated-lhs
(mapcar #'(lambda (general-grammar-symbol)
(instantiate-general-grammar-symbol bound-argument-alist general-grammar-symbol))
production-rhs)
production-name)
productions))))
lhs-arguments)
(when productions
(setf (gethash production-name general-productions)
(make-generic-production production-lhs production-rhs production-name (nreverse productions)))))
(unless (nonterminal-excluded production-lhs)
(setf (gethash production-name general-productions)
(create-production production-lhs production-rhs production-name)))))))
;Change all values of the rules hash table to contain rule structures
;instead of mere lists of rules. Also check that all referenced nonterminals
@ -1026,6 +1045,13 @@
(make-rule (nreverse rule-productions))))
rules)
;Check that all excluded nonterminals have been seen.
(maphash
#'(lambda (excluded-nonterminal seen)
(unless (eq seen :seen)
(warn "Nonterminal ~S declared excluded but not defined" excluded-nonterminal)))
excluded-nonterminals-hash)
(let ((nonterminals-list (depth-first-search
*grammar-symbol-=*
#'(lambda (nonterminal) (rule-nonterminals (gethash nonterminal rules)))
@ -1078,7 +1104,7 @@
(unless (eq new-derives-epsilon (rule-derives-epsilon rule))
(setf (rule-derives-epsilon rule) t)
(setq changed t)))))
;Compute the parameter-trees entries.
(let ((parameter-trees (grammar-parameter-trees grammar)))
(dolist (production-source interned-grammar-source)

Просмотреть файл

@ -551,10 +551,11 @@
; list of extra commands that:
; define the partitions used in this lexer;
; define the actions of these productions.
(defun make-lexer-and-grammar (kind charclasses-source lexer-actions-source parametrization start-symbol grammar-source)
(defun make-lexer-and-grammar (kind charclasses-source lexer-actions-source parametrization start-symbol grammar-source &optional excluded-nonterminals-source)
(let ((lexer (make-lexer charclasses-source lexer-actions-source grammar-source)))
(multiple-value-bind (extra-grammar-source extra-commands) (lexer-grammar-and-commands lexer)
(let ((grammar (make-and-compile-grammar kind parametrization start-symbol (append extra-grammar-source grammar-source))))
(let ((grammar (make-and-compile-grammar kind parametrization start-symbol
(append extra-grammar-source grammar-source) excluded-nonterminals-source)))
(setf (lexer-grammar lexer) grammar)
(values lexer extra-commands)))))

Просмотреть файл

@ -412,8 +412,8 @@
; Make the grammar and compile its parser. kind should be either :lalr-1 or :lr-1.
(defun make-and-compile-grammar (kind parametrization start-symbol grammar-source)
(compile-parser (make-grammar parametrization start-symbol grammar-source)
(defun make-and-compile-grammar (kind parametrization start-symbol grammar-source &optional excluded-nonterminals-source)
(compile-parser (make-grammar parametrization start-symbol grammar-source excluded-nonterminals-source)
kind))

Просмотреть файл

@ -2126,7 +2126,8 @@
(grammar preprocess-grammar)
(lexer preprocess-lexer)
(grammar-argument preprocess-grammar-argument)
(production preprocess-production))
(production preprocess-production)
(exclude preprocess-exclude))
(:macro
(let expand-let depict-let)
@ -2532,6 +2533,7 @@
(parametrization nil :type (or null grammar-parametrization)) ;Parametrization of the grammar being accumulated or nil if none
(start-symbol nil :type symbol) ;Start symbol of the grammar being accumulated or nil if none
(grammar-source-reverse nil :type list) ;List of productions in the grammar being accumulated (in reverse order)
(excluded-nonterminals-source nil :type list) ;List of nonterminals to be excluded from the grammar
(charclasses-source nil) ;List of charclasses in the lexical grammar being accumulated
(lexer-actions-source nil) ;List of lexer actions in the lexical grammar being accumulated
(grammar-infos-reverse nil :type list)) ;List of grammar-infos already completed (in reverse order)
@ -2551,12 +2553,16 @@
(and kind
(let ((parametrization (preprocessor-state-parametrization preprocessor-state))
(start-symbol (preprocessor-state-start-symbol preprocessor-state))
(grammar-source (nreverse (preprocessor-state-grammar-source-reverse preprocessor-state))))
(grammar-source (nreverse (preprocessor-state-grammar-source-reverse preprocessor-state)))
(excluded-nonterminals-source (preprocessor-state-excluded-nonterminals-source preprocessor-state)))
(multiple-value-bind (grammar lexer extra-commands)
(ecase kind
(:grammar
(values (make-and-compile-grammar (preprocessor-state-kind2 preprocessor-state)
parametrization start-symbol grammar-source)
parametrization
start-symbol
grammar-source
excluded-nonterminals-source)
nil
nil))
(:lexer
@ -2565,7 +2571,10 @@
(preprocessor-state-kind2 preprocessor-state)
(preprocessor-state-charclasses-source preprocessor-state)
(preprocessor-state-lexer-actions-source preprocessor-state)
parametrization start-symbol grammar-source)
parametrization
start-symbol
grammar-source
excluded-nonterminals-source)
(values (lexer-grammar lexer) lexer extra-commands))))
(let ((grammar-info (make-grammar-info (preprocessor-state-name preprocessor-state) grammar lexer)))
(setf (preprocessor-state-kind preprocessor-state) nil)
@ -2574,6 +2583,7 @@
(setf (preprocessor-state-parametrization preprocessor-state) nil)
(setf (preprocessor-state-start-symbol preprocessor-state) nil)
(setf (preprocessor-state-grammar-source-reverse preprocessor-state) nil)
(setf (preprocessor-state-excluded-nonterminals-source preprocessor-state) nil)
(setf (preprocessor-state-charclasses-source preprocessor-state) nil)
(setf (preprocessor-state-lexer-actions-source preprocessor-state) nil)
(push grammar-info (preprocessor-state-grammar-infos-reverse preprocessor-state))
@ -2745,3 +2755,15 @@
actions))
t))
; (exclude <lhs> ... <lhs>)
; ==>
; grammar excluded nonterminals:
; <lhs> ... <lhs>;
(defun preprocess-exclude (preprocessor-state command &rest excluded-nonterminals-source)
(declare (ignore command))
(preprocess-ensure-grammar preprocessor-state)
(setf (preprocessor-state-excluded-nonterminals-source preprocessor-state)
(append excluded-nonterminals-source (preprocessor-state-excluded-nonterminals-source preprocessor-state)))
(values nil nil))

Просмотреть файл

@ -944,9 +944,7 @@
(multiple-value-bind (lhs-nonterminal lhs-arguments) (grammar-parametrization-intern grammar-parametrization production-lhs-source)
(list lhs-nonterminal
(mapcar #'(lambda (grammar-symbol-source)
(if (consp grammar-symbol-source)
(grammar-parametrization-intern grammar-parametrization grammar-symbol-source lhs-arguments)
grammar-symbol-source))
(grammar-parametrization-intern grammar-parametrization grammar-symbol-source lhs-arguments))
production-rhs-source)
production-name))
production-source)))
@ -963,7 +961,11 @@
; of the lhs nonterminal. The lhs nonterminal must not have duplicate arguments. The lhs
; nonterminal can have attributes, thereby designating a specialization instead of a fully
; generic production.
(defun make-grammar (grammar-parametrization start-symbol grammar-source)
;
; excluded-nonterminals-source is a list of nonterminals not used in the grammar. Productions,
; including productions expanded from generic productions, that have one of these nonterminals
; on the lhs are ignored.
(defun make-grammar (grammar-parametrization start-symbol grammar-source &optional excluded-nonterminals-source)
(let ((interned-grammar-source
(mapcar #'(lambda (production-source)
(intern-production-source grammar-parametrization production-source))
@ -972,7 +974,14 @@
(terminals-hash (make-hash-table :test *grammar-symbol-=*))
(general-productions (make-hash-table :test #'equal))
(production-number 0)
(max-production-length 1))
(max-production-length 1)
(excluded-nonterminals-hash (make-hash-table :test *grammar-symbol-=*)))
;Set up excluded-nonterminals-hash. The values of the hash table are either :seen or :unseen
;depending on whether a production with the particular nonterminal has been seen yet.
(dolist (excluded-nonterminal-source excluded-nonterminals-source)
(setf (gethash (grammar-parametrization-intern grammar-parametrization excluded-nonterminal-source nil) excluded-nonterminals-hash)
:unseen))
;Create the starting production: *start-nonterminal* ==> start-symbol
(setf (gethash *start-nonterminal* rules)
@ -985,7 +994,11 @@
(push production (gethash lhs rules))
(dolist (rhs-terminal (production-terminals production))
(setf (gethash rhs-terminal terminals-hash) t))
production)))
production))
(nonterminal-excluded (nonterminal)
(and (gethash nonterminal excluded-nonterminals-hash)
(setf (gethash nonterminal excluded-nonterminals-hash) :seen))))
(dolist (production-source interned-grammar-source)
(let* ((production-lhs (first production-source))
@ -995,23 +1008,29 @@
(setq max-production-length (max max-production-length (length production-rhs)))
(when (gethash production-name general-productions)
(error "Duplicate production name ~S" production-name))
(setf (gethash production-name general-productions)
(if lhs-arguments
(let ((productions nil))
(grammar-parametrization-each-permutation
grammar-parametrization
#'(lambda (bound-argument-alist)
(push (create-production
(instantiate-general-grammar-symbol bound-argument-alist production-lhs)
(mapcar #'(lambda (general-grammar-symbol)
(instantiate-general-grammar-symbol bound-argument-alist general-grammar-symbol))
production-rhs)
production-name)
productions))
lhs-arguments)
(make-generic-production production-lhs production-rhs production-name (nreverse productions)))
(create-production production-lhs production-rhs production-name))))))
(if lhs-arguments
(let ((productions nil))
(grammar-parametrization-each-permutation
grammar-parametrization
#'(lambda (bound-argument-alist)
(let ((instantiated-lhs (instantiate-general-grammar-symbol bound-argument-alist production-lhs)))
(unless (nonterminal-excluded instantiated-lhs)
(push (create-production
instantiated-lhs
(mapcar #'(lambda (general-grammar-symbol)
(instantiate-general-grammar-symbol bound-argument-alist general-grammar-symbol))
production-rhs)
production-name)
productions))))
lhs-arguments)
(when productions
(setf (gethash production-name general-productions)
(make-generic-production production-lhs production-rhs production-name (nreverse productions)))))
(unless (nonterminal-excluded production-lhs)
(setf (gethash production-name general-productions)
(create-production production-lhs production-rhs production-name)))))))
;Change all values of the rules hash table to contain rule structures
;instead of mere lists of rules. Also check that all referenced nonterminals
@ -1026,6 +1045,13 @@
(make-rule (nreverse rule-productions))))
rules)
;Check that all excluded nonterminals have been seen.
(maphash
#'(lambda (excluded-nonterminal seen)
(unless (eq seen :seen)
(warn "Nonterminal ~S declared excluded but not defined" excluded-nonterminal)))
excluded-nonterminals-hash)
(let ((nonterminals-list (depth-first-search
*grammar-symbol-=*
#'(lambda (nonterminal) (rule-nonterminals (gethash nonterminal rules)))
@ -1078,7 +1104,7 @@
(unless (eq new-derives-epsilon (rule-derives-epsilon rule))
(setf (rule-derives-epsilon rule) t)
(setq changed t)))))
;Compute the parameter-trees entries.
(let ((parameter-trees (grammar-parameter-trees grammar)))
(dolist (production-source interned-grammar-source)

Просмотреть файл

@ -551,10 +551,11 @@
; list of extra commands that:
; define the partitions used in this lexer;
; define the actions of these productions.
(defun make-lexer-and-grammar (kind charclasses-source lexer-actions-source parametrization start-symbol grammar-source)
(defun make-lexer-and-grammar (kind charclasses-source lexer-actions-source parametrization start-symbol grammar-source &optional excluded-nonterminals-source)
(let ((lexer (make-lexer charclasses-source lexer-actions-source grammar-source)))
(multiple-value-bind (extra-grammar-source extra-commands) (lexer-grammar-and-commands lexer)
(let ((grammar (make-and-compile-grammar kind parametrization start-symbol (append extra-grammar-source grammar-source))))
(let ((grammar (make-and-compile-grammar kind parametrization start-symbol
(append extra-grammar-source grammar-source) excluded-nonterminals-source)))
(setf (lexer-grammar lexer) grammar)
(values lexer extra-commands)))))

Просмотреть файл

@ -412,8 +412,8 @@
; Make the grammar and compile its parser. kind should be either :lalr-1 or :lr-1.
(defun make-and-compile-grammar (kind parametrization start-symbol grammar-source)
(compile-parser (make-grammar parametrization start-symbol grammar-source)
(defun make-and-compile-grammar (kind parametrization start-symbol grammar-source &optional excluded-nonterminals-source)
(compile-parser (make-grammar parametrization start-symbol grammar-source excluded-nonterminals-source)
kind))