mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 14:56:07 +00:00
Added support for highlights.
This commit is contained in:
parent
760079a091
commit
8f752abf38
@ -26,7 +26,7 @@
|
||||
(defvar *trace-variables* nil)
|
||||
|
||||
|
||||
#+mcl (dolist (indent-spec '((apply . 1) (funcall . 1) (production . 3) (rule . 2) (function . 1) (letexc . 1) (deftype . 1) (tuple . 1) (%text . 1)))
|
||||
#+mcl (dolist (indent-spec '((? . 1) (apply . 1) (funcall . 1) (production . 3) (rule . 2) (function . 1) (letexc . 1) (deftype . 1) (tuple . 1) (%text . 1)))
|
||||
(pushnew indent-spec ccl:*fred-special-indent-alist* :test #'equal))
|
||||
|
||||
|
||||
@ -426,6 +426,7 @@
|
||||
(defstruct (world (:constructor allocate-world)
|
||||
(:copier nil)
|
||||
(:predicate world?))
|
||||
(conditionals nil :type list) ;Assoc list of (conditional . highlight), where highlight can be a style keyword, nil (no style), or 'delete
|
||||
(package nil :type package) ;The package in which this world's identifiers are interned
|
||||
(n-type-names 0 :type integer) ;Number of type names defined so far
|
||||
(types-reverse nil :type (or null hash-table)) ;Hash table of (kind tags parameters) -> type; nil if invalid
|
||||
@ -577,6 +578,25 @@
|
||||
(and grammar-info (grammar-info-lexer grammar-info))))
|
||||
|
||||
|
||||
; Return a list of highlights allowed in this world.
|
||||
(defun world-highlights (world)
|
||||
(let ((highlights nil))
|
||||
(dolist (c (world-conditionals world))
|
||||
(let ((highlight (cdr c)))
|
||||
(unless (or (null highlight) (eq highlight 'delete))
|
||||
(pushnew highlight highlights))))
|
||||
(nreverse highlights)))
|
||||
|
||||
|
||||
; Return the highlight to which the given conditional maps.
|
||||
; Return 'delete if the conditional should be omitted.
|
||||
(defun resolve-conditional (world conditional)
|
||||
(let ((h (assoc conditional (world-conditionals world))))
|
||||
(if h
|
||||
(cdr h)
|
||||
(error "Bad conditional ~S" conditional))))
|
||||
|
||||
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; SYMBOLS
|
||||
|
||||
@ -2327,6 +2347,13 @@
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; COMMANDS
|
||||
|
||||
; (%highlight <highlight> <command> ... <command>)
|
||||
; Evaluate the given commands. <highlight> is a hint for printing.
|
||||
(defun scan-%highlight (world grammar-info-var highlight &rest commands)
|
||||
(declare (ignore highlight))
|
||||
(scan-commands world grammar-info-var commands))
|
||||
|
||||
|
||||
; (%... ...)
|
||||
; Ignore any command that starts with a %. These commands are hints for printing.
|
||||
(defun scan-% (world grammar-info-var &rest rest)
|
||||
@ -2415,6 +2442,7 @@
|
||||
|
||||
(defparameter *default-specials*
|
||||
'((:preprocess
|
||||
(? preprocess-?)
|
||||
(define preprocess-define)
|
||||
(action preprocess-action)
|
||||
(grammar preprocess-grammar)
|
||||
@ -2431,6 +2459,7 @@
|
||||
(set-of expand-set-of nil))
|
||||
|
||||
(:command
|
||||
(%highlight scan-%highlight depict-%highlight) ;For internal use only; use ? instead.
|
||||
(%section scan-% depict-%section)
|
||||
(%subsection scan-% depict-%subsection)
|
||||
(%text scan-% depict-%text)
|
||||
@ -2636,8 +2665,15 @@
|
||||
|
||||
|
||||
; Create a world with the given name and set up the built-in properties of its symbols.
|
||||
(defun init-world (name)
|
||||
; conditionals is an association list of (conditional . highlight), where conditional is a symbol
|
||||
; and highlight is either:
|
||||
; a style keyword: Use that style to highlight the contents of any (? conditional ...) commands
|
||||
; nil: Include the contents of any (? conditional ...) commands without highlighting them
|
||||
; delete: Don't include the contents of (? conditional ...) commands
|
||||
(defun init-world (name conditionals)
|
||||
(assert-type conditionals (list (cons symbol (or null keyword (eql delete)))))
|
||||
(let ((world (make-world name)))
|
||||
(setf (world-conditionals world) conditionals)
|
||||
(dolist (specials-list *default-specials*)
|
||||
(let ((property (car specials-list)))
|
||||
(dolist (special-spec (cdr specials-list))
|
||||
@ -2753,10 +2789,8 @@
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; EVALUATION
|
||||
|
||||
; Scan a command. Create types and variables in the world
|
||||
; but do not evaluate variables' types or values yet.
|
||||
; grammar-info-var is a cons cell whose car is either nil
|
||||
; or a grammar-info for the grammar currently being defined.
|
||||
; Scan a command. Create types and variables in the world but do not evaluate variables' types or values yet.
|
||||
; grammar-info-var is a cons cell whose car is either nil or a grammar-info for the grammar currently being defined.
|
||||
(defun scan-command (world grammar-info-var command)
|
||||
(handler-bind ((error #'(lambda (condition)
|
||||
(declare (ignore condition))
|
||||
@ -2769,6 +2803,12 @@
|
||||
(error "Bad command")))))
|
||||
|
||||
|
||||
; Scan a list of commands. See scan-command above.
|
||||
(defun scan-commands (world grammar-info-var commands)
|
||||
(dolist (command commands)
|
||||
(scan-command world grammar-info-var command)))
|
||||
|
||||
|
||||
; Compute the primitives' types from their type-exprs.
|
||||
(defun define-primitives (world)
|
||||
(each-world-external-symbol-with-property
|
||||
@ -2864,8 +2904,7 @@
|
||||
(assert-true (null (world-commands-source world)))
|
||||
(setf (world-commands-source world) commands)
|
||||
(let ((grammar-info-var (list nil)))
|
||||
(dolist (command commands)
|
||||
(scan-command world grammar-info-var command)))
|
||||
(scan-commands world grammar-info-var commands))
|
||||
(unite-types world)
|
||||
(setf (world-bottom-type world) (make-type world :bottom nil nil))
|
||||
(setf (world-void-type world) (make-type world :void nil nil))
|
||||
@ -2884,7 +2923,9 @@
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; PREPROCESSING
|
||||
|
||||
(defstruct preprocessor-state
|
||||
(defstruct (preprocessor-state (:constructor make-preprocessor-state (world)))
|
||||
(world nil :type world :read-only t) ;The world into which preprocessed symbols are interned
|
||||
(highlight nil :type symbol) ;The current highlight style or nil if none
|
||||
(kind nil :type (member nil :grammar :lexer)) ;The kind of grammar being accumulated or nil if none
|
||||
(kind2 nil :type (member nil :lalr-1 :lr-1 :canonical-lr-1)) ;The kind of parser
|
||||
(name nil :type symbol) ;Name of the grammar being accumulated or nil if none
|
||||
@ -2914,7 +2955,8 @@
|
||||
(start-symbol (preprocessor-state-start-symbol preprocessor-state))
|
||||
(grammar-source (nreverse (preprocessor-state-grammar-source-reverse preprocessor-state)))
|
||||
(excluded-nonterminals-source (preprocessor-state-excluded-nonterminals-source preprocessor-state))
|
||||
(grammar-options (preprocessor-state-grammar-options preprocessor-state)))
|
||||
(grammar-options (preprocessor-state-grammar-options preprocessor-state))
|
||||
(highlights (world-highlights (preprocessor-state-world preprocessor-state))))
|
||||
(multiple-value-bind (grammar lexer extra-commands)
|
||||
(ecase kind
|
||||
(:grammar
|
||||
@ -2924,6 +2966,7 @@
|
||||
start-symbol
|
||||
grammar-source
|
||||
:excluded-nonterminals excluded-nonterminals-source
|
||||
:highlights highlights
|
||||
grammar-options)
|
||||
nil
|
||||
nil))
|
||||
@ -2937,6 +2980,7 @@
|
||||
start-symbol
|
||||
grammar-source
|
||||
:excluded-nonterminals excluded-nonterminals-source
|
||||
:highlights highlights
|
||||
grammar-options)
|
||||
(values (lexer-grammar lexer) lexer extra-commands))))
|
||||
(let ((grammar-info (make-grammar-info (preprocessor-state-name preprocessor-state) grammar lexer)))
|
||||
@ -2954,19 +2998,17 @@
|
||||
(append extra-commands (list '(clear-grammar)))))))))
|
||||
|
||||
|
||||
; Helper function for preprocess-source.
|
||||
; source is a list of preprocessor directives and commands. Preprocess these commands
|
||||
; and return the following results:
|
||||
; a list of preprocessed commands;
|
||||
; a list of grammar-infos extracted from preprocessor directives.
|
||||
(defun preprocess-source (world source)
|
||||
(let ((preprocessor-state (make-preprocessor-state)))
|
||||
(labels
|
||||
; using the given preprocessor-state and return the resulting list of commands.
|
||||
(defun preprocess-list (preprocessor-state source)
|
||||
(let ((world (preprocessor-state-world preprocessor-state)))
|
||||
(flet
|
||||
((preprocess-one (form)
|
||||
(when (consp form)
|
||||
(let ((first (car form)))
|
||||
(when (identifier? first)
|
||||
(let* ((symbol (world-intern world first))
|
||||
(action (symbol-preprocessor-function symbol)))
|
||||
(let ((action (symbol-preprocessor-function (world-intern world first))))
|
||||
(when action
|
||||
(handler-bind ((error #'(lambda (condition)
|
||||
(declare (ignore condition))
|
||||
@ -2974,19 +3016,33 @@
|
||||
(multiple-value-bind (preprocessed-form re-preprocess) (apply action preprocessor-state form)
|
||||
(return-from preprocess-one
|
||||
(if re-preprocess
|
||||
(mapcan #'preprocess-one preprocessed-form)
|
||||
(preprocess-list preprocessor-state preprocessed-form)
|
||||
preprocessed-form)))))))))
|
||||
(list form)))
|
||||
|
||||
(let* ((commands (mapcan #'preprocess-one source))
|
||||
(commands (nconc commands (preprocessor-state-finish-grammar preprocessor-state))))
|
||||
(values commands (nreverse (preprocessor-state-grammar-infos-reverse preprocessor-state)))))))
|
||||
(mapcan #'preprocess-one source))))
|
||||
|
||||
|
||||
; source is a list of preprocessor directives and commands. Preprocess these commands
|
||||
; and return the following results:
|
||||
; a list of preprocessed commands;
|
||||
; a list of grammar-infos extracted from preprocessor directives.
|
||||
(defun preprocess-source (world source)
|
||||
(let* ((preprocessor-state (make-preprocessor-state world))
|
||||
(commands (preprocess-list preprocessor-state source))
|
||||
(commands (nconc commands (preprocessor-state-finish-grammar preprocessor-state))))
|
||||
(values commands (nreverse (preprocessor-state-grammar-infos-reverse preprocessor-state)))))
|
||||
|
||||
|
||||
; Create a new world with the given name and preprocess and evaluate the given
|
||||
; source commands in it.
|
||||
(defun generate-world (name source)
|
||||
(let ((world (init-world name)))
|
||||
; conditionals is an association list of (conditional . highlight), where conditional is a symbol
|
||||
; and highlight is either:
|
||||
; a style keyword: Use that style to highlight the contents of any (? conditional ...) commands
|
||||
; nil: Include the contents of any (? conditional ...) commands without highlighting them
|
||||
; delete: Don't include the contents of (? conditional ...) commands
|
||||
(defun generate-world (name source &optional conditionals)
|
||||
(let ((world (init-world name conditionals)))
|
||||
(multiple-value-bind (commands grammar-infos) (preprocess-source world source)
|
||||
(dolist (grammar-info grammar-infos)
|
||||
(clear-actions (grammar-info-grammar grammar-info)))
|
||||
@ -2999,6 +3055,27 @@
|
||||
;;; PREPROCESSOR ACTIONS
|
||||
|
||||
|
||||
; (? <conditional> <command> ... <command>)
|
||||
; ==>
|
||||
; (%highlight <highlight> <command> ... <command>)
|
||||
; or
|
||||
; <empty>
|
||||
(defun preprocess-? (preprocessor-state command conditional &rest commands)
|
||||
(declare (ignore command))
|
||||
(let ((highlight (resolve-conditional (preprocessor-state-world preprocessor-state) conditional))
|
||||
(saved-highlight (preprocessor-state-highlight preprocessor-state)))
|
||||
(cond
|
||||
((eq highlight 'delete) (values nil nil))
|
||||
((eq highlight saved-highlight) (values commands t))
|
||||
(t (values
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setf (preprocessor-state-highlight preprocessor-state) highlight)
|
||||
(list (list* '%highlight highlight (preprocess-list preprocessor-state commands))))
|
||||
(setf (preprocessor-state-highlight preprocessor-state) saved-highlight))
|
||||
nil)))))
|
||||
|
||||
|
||||
; (define <name> <type> <value>)
|
||||
; ==>
|
||||
; (define <name> <type> <value> nil)
|
||||
@ -3123,7 +3200,7 @@
|
||||
; (production <lhs> <rhs> <name> (<action-spec-1> <body-1>) ... (<action-spec-n> <body-n>))
|
||||
; ==>
|
||||
; grammar:
|
||||
; (<lhs> <rhs> <name>)
|
||||
; (<lhs> <rhs> <name> <current-highlight>)
|
||||
; commands:
|
||||
; (%rule <lhs>)
|
||||
; (action <action-spec-1> <name> <body-1>)
|
||||
@ -3133,7 +3210,8 @@
|
||||
(declare (ignore command))
|
||||
(assert-type actions (list (tuple t t)))
|
||||
(preprocess-ensure-grammar preprocessor-state)
|
||||
(push (list lhs rhs name) (preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(push (list lhs rhs name (preprocessor-state-highlight preprocessor-state))
|
||||
(preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(values
|
||||
(cons (list '%rule lhs)
|
||||
(mapcar #'(lambda (action)
|
||||
@ -3149,9 +3227,9 @@
|
||||
; (production <lhs-m> <rhs-m> <name-m> (<action-spec-m-1> <body-m-1>) ... (<action-spec-m-n> <body-m-n>)))
|
||||
; ==>
|
||||
; grammar:
|
||||
; (<lhs-1> <rhs-1> <name-1>)
|
||||
; (<lhs-1> <rhs-1> <name-1> <current-highlight>)
|
||||
; ...
|
||||
; (<lhs-m> <rhs-m> <name-m>)
|
||||
; (<lhs-m> <rhs-m> <name-m> <current-highlight>)
|
||||
; commands:
|
||||
; (%rule <lhs-1>)
|
||||
; ...
|
||||
@ -3188,7 +3266,8 @@
|
||||
(actions (assert-type (cddddr production) (list (tuple t t)))))
|
||||
(unless (actions-match action-declarations actions)
|
||||
(error "Action name mismatch: ~S vs. ~S" action-declarations actions))
|
||||
(push (list lhs rhs name) (preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(push (list lhs rhs name (preprocessor-state-highlight preprocessor-state))
|
||||
(preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(push (list '%rule lhs) commands-reverse)))
|
||||
(dotimes (i (length action-declarations))
|
||||
(let ((action-declaration (nth i action-declarations)))
|
||||
|
@ -113,11 +113,16 @@
|
||||
(error "Bad command: ~S" command)))))
|
||||
|
||||
|
||||
; Emit markup paragraphs for a list of commands.
|
||||
(defun depict-commands (markup-stream world depict-env commands)
|
||||
(dolist (command commands)
|
||||
(depict-command markup-stream world depict-env command)))
|
||||
|
||||
|
||||
; Emit markup paragraphs for the world's commands.
|
||||
(defun depict-world-commands (markup-stream world &key (visible-semantics t))
|
||||
(let ((depict-env (make-depict-env visible-semantics)))
|
||||
(dolist (command (world-commands-source world))
|
||||
(depict-command markup-stream world depict-env command))
|
||||
(depict-commands markup-stream world depict-env (world-commands-source world))
|
||||
(depict-clear-grammar markup-stream world depict-env)))
|
||||
|
||||
|
||||
@ -861,6 +866,14 @@
|
||||
,@body)))
|
||||
|
||||
|
||||
; (%highlight <highlight> <command> ... <command>)
|
||||
; Depict the commands highlighted with the <highlight> block style.
|
||||
(defun depict-%highlight (markup-stream world depict-env highlight &rest commands)
|
||||
(when commands
|
||||
(depict-block-style (markup-stream highlight t)
|
||||
(depict-commands markup-stream world depict-env commands))))
|
||||
|
||||
|
||||
; (%section "section-name")
|
||||
(defun depict-%section (markup-stream world depict-env section-name)
|
||||
(declare (ignore world))
|
||||
@ -936,7 +949,7 @@
|
||||
(when (some #'seen-nonterminal? rule-lhs-nonterminals)
|
||||
(warn "General rule for ~S listed before specific ones; use %rule to disambiguate" general-nonterminal))
|
||||
(when visible
|
||||
(depict-general-rule markup-stream general-rule))
|
||||
(depict-general-rule markup-stream general-rule (grammar-highlights grammar)))
|
||||
(dolist (nonterminal rule-lhs-nonterminals)
|
||||
(setf (gethash nonterminal seen-nonterminals) t))))))))))
|
||||
;******** May still have a problem when a specific rule precedes a general one.
|
||||
|
@ -218,7 +218,8 @@
|
||||
(lhs nil :type general-nonterminal :read-only t) ;The general-nonterminal on the left-hand side of this general-production
|
||||
(rhs nil :type list :read-only t) ;List of general grammar symbols to which that general-nonterminal expands
|
||||
(constraints nil :type list :read-only t) ;List of constraints applying to rhs, sorted by increasing pos values
|
||||
(name nil :read-only t)) ;This general-production's name that will be used to name the parse tree node
|
||||
(name nil :read-only t) ;This general-production's name that will be used to name the parse tree node
|
||||
(highlight nil :read-only t)) ;This general-production's markup style keyword or nil if default
|
||||
|
||||
|
||||
; If general-production is a generic-production, return its list of productions;
|
||||
@ -340,7 +341,7 @@
|
||||
;;; The evaluator is a lisp form that evaluates to a function f that takes one argument --
|
||||
;;; the old state of the parser's value stack -- and returns the new state of that stack.
|
||||
(defstruct (production (:include general-production (lhs nil :type nonterminal :read-only t))
|
||||
(:constructor make-production (lhs rhs constraints name rhs-length number))
|
||||
(:constructor make-production (lhs rhs constraints name highlight rhs-length number))
|
||||
(:copier nil) (:predicate production?))
|
||||
(rhs-length nil :type integer :read-only t) ;Number of grammar symbols in the rhs
|
||||
(number nil :type integer :read-only t) ;This production's serial number
|
||||
@ -385,7 +386,7 @@
|
||||
;;; A generic production is not a production and does not have a number or actions.
|
||||
|
||||
(defstruct (generic-production (:include general-production (lhs nil :type generic-nonterminal :read-only t))
|
||||
(:constructor make-generic-production (lhs rhs constraints name productions))
|
||||
(:constructor make-generic-production (lhs rhs constraints name highlight productions))
|
||||
(:copier nil)
|
||||
(:predicate generic-production?))
|
||||
(productions nil :type list :read-only t)) ;List of instantiations of this generic production
|
||||
@ -404,6 +405,7 @@
|
||||
(generic-production-rhs generic-production))
|
||||
(general-production-constraints generic-production)
|
||||
(generic-production-name generic-production)
|
||||
(generic-production-highlight generic-production)
|
||||
(remove-if #'(lambda (production)
|
||||
(not (general-nonterminal-is-instance? grammar-parametrization new-lhs (production-lhs production))))
|
||||
productions))
|
||||
@ -426,24 +428,62 @@
|
||||
(general-production-lhs (first (general-rule-productions general-rule))))
|
||||
|
||||
|
||||
; Return the given highlight. If it is nil, return nil and ensure that no other
|
||||
; highlight (from the list given by highlights) is currently in effect in the markup-stream.
|
||||
(defun check-highlight (highlight highlights markup-stream)
|
||||
(if highlight
|
||||
(assert-true (member highlight highlights))
|
||||
(dolist (h highlights)
|
||||
(ensure-no-enclosing-style markup-stream h)))
|
||||
highlight)
|
||||
|
||||
|
||||
; Return the list of general-productions, in order, gathered into runs of consecutive productions with the same highlight value.
|
||||
; The result is a list of runs:
|
||||
; (<highlight> <p> ... <p>),
|
||||
; where each <p> is:
|
||||
; (<general-production> <first> <last>),
|
||||
; where <first> is true if this is the first production and <last> is true if this is the last production.
|
||||
(defun gather-productions-by-highlights (general-productions)
|
||||
(when general-productions
|
||||
(let* ((first-production (first general-productions))
|
||||
(prior-runs-reverse nil)
|
||||
(current-highlight (general-production-highlight first-production))
|
||||
(current-run-productions-reverse (list (list first-production t nil))))
|
||||
(dolist (general-production (rest general-productions))
|
||||
(let ((highlight (general-production-highlight general-production))
|
||||
(p (list general-production nil nil)))
|
||||
(if (eq highlight current-highlight)
|
||||
(push p current-run-productions-reverse)
|
||||
(progn
|
||||
(push (cons current-highlight (nreverse current-run-productions-reverse)) prior-runs-reverse)
|
||||
(setq current-highlight highlight)
|
||||
(setq current-run-productions-reverse (list p))))))
|
||||
(setf (third (first current-run-productions-reverse)) t)
|
||||
(nreconc prior-runs-reverse (list (cons current-highlight (nreverse current-run-productions-reverse)))))))
|
||||
|
||||
|
||||
; Emit markup paragraphs for the grammar general rule.
|
||||
; If the rule is short enough (only one production), emit the rule on one line.
|
||||
(defun depict-general-rule (markup-stream general-rule)
|
||||
(depict-block-style (markup-stream ':grammar-rule)
|
||||
(let ((general-productions (general-rule-productions general-rule)))
|
||||
(assert-true general-productions)
|
||||
(if (cdr general-productions)
|
||||
(labels
|
||||
((emit-general-productions (general-productions first)
|
||||
(let ((general-production (first general-productions))
|
||||
(rest (rest general-productions)))
|
||||
(depict-general-production-rhs markup-stream general-production first (endp rest))
|
||||
(when rest
|
||||
(emit-general-productions rest nil)))))
|
||||
(depict-general-production-lhs markup-stream (general-rule-lhs general-rule))
|
||||
(emit-general-productions general-productions t))
|
||||
(depict-paragraph (markup-stream ':grammar-lhs-last)
|
||||
(depict-general-production markup-stream (first general-productions) :definition))))))
|
||||
; highlights is a list of keywords that may be used to highlight specific rules or productions. It should
|
||||
; be the same as the list of highlights passed to make-grammar.
|
||||
(defun depict-general-rule (markup-stream general-rule highlights)
|
||||
(let ((general-productions (general-rule-productions general-rule)))
|
||||
(assert-true general-productions)
|
||||
(let* ((production-runs (gather-productions-by-highlights general-productions))
|
||||
(rule-highlight (and (endp (rest production-runs))
|
||||
(check-highlight (first (first production-runs)) highlights markup-stream))))
|
||||
(depict-block-style (markup-stream rule-highlight t)
|
||||
(depict-block-style (markup-stream ':grammar-rule)
|
||||
(if (rest general-productions)
|
||||
(progn
|
||||
(depict-general-production-lhs markup-stream (general-rule-lhs general-rule))
|
||||
(dolist (production-run production-runs)
|
||||
(depict-block-style (markup-stream (check-highlight (first production-run) highlights markup-stream) t)
|
||||
(dolist (p (rest production-run))
|
||||
(apply #'depict-general-production-rhs markup-stream p)))))
|
||||
(depict-paragraph (markup-stream ':grammar-lhs-last)
|
||||
(depict-general-production markup-stream (first general-productions) :definition))))))))
|
||||
|
||||
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
@ -1046,6 +1086,7 @@
|
||||
(max-production-length nil :type integer :read-only t) ;Maximum number of grammar symbols in the rhs of a production
|
||||
(general-productions nil :type hash-table :read-only t);Hash table of production-name -> general-production
|
||||
(n-productions nil :type integer :read-only t) ;Number of productions in the grammar
|
||||
(highlights nil :type list :read-only t) ;List of style keywords for highlighting selected productions
|
||||
;The following fields are used for the parser.
|
||||
(items-hash nil :type (or null hash-table)) ;Hash table of (production . dot) -> item; nil for a cleaned grammar or a grammar without a parser
|
||||
(states nil :type list) ;List of LR(0) states (in order of state numbers)
|
||||
@ -1174,15 +1215,18 @@
|
||||
|
||||
; Intern attributed or generic nonterminals in the production's lhs and rhs. Replace
|
||||
; (:- <terminal> ... <terminal>) or (:-- (<grammar-symbol> ... <grammar-symbol>) <terminal> ... <terminal>)
|
||||
; sublists in the rhs with lookahead-constraints and put these, in order, after the third element of
|
||||
; sublists in the rhs with lookahead-constraints and put these, in order, after the fourth element of
|
||||
; the returned list. Also replace variant constraint symbols with variant-constraints.
|
||||
; The variant-constraint-names parameter should be a list of possible variant constraint symbols.
|
||||
; Return the resulting production source.
|
||||
(defun intern-production-source (grammar-parametrization variant-constraint-names production-source)
|
||||
(assert-type production-source (tuple (or user-nonterminal cons) (list (or user-grammar-symbol cons)) identifier))
|
||||
(defun intern-production-source (grammar-parametrization variant-constraint-names highlights production-source)
|
||||
(assert-type production-source (tuple (or user-nonterminal cons) (list (or user-grammar-symbol cons)) identifier t))
|
||||
(let ((production-lhs-source (first production-source))
|
||||
(production-rhs-source (second production-source))
|
||||
(production-name (third production-source)))
|
||||
(production-name (third production-source))
|
||||
(production-highlight (fourth production-source)))
|
||||
(unless (or (null production-highlight) (member production-highlight highlights :test #'eq))
|
||||
(error "Bad highlight in rule: ~S; allowed highlights are ~S" production-source highlights))
|
||||
(if (or (consp production-lhs-source) (some #'consp production-rhs-source) (intersection variant-constraint-names production-rhs-source))
|
||||
(multiple-value-bind (lhs-nonterminal lhs-arguments) (grammar-parametrization-intern grammar-parametrization production-lhs-source)
|
||||
(let ((rhs nil)
|
||||
@ -1205,7 +1249,7 @@
|
||||
(t
|
||||
(push (grammar-parametrization-intern grammar-parametrization component-source lhs-arguments) rhs)
|
||||
(incf pos))))
|
||||
(list* lhs-nonterminal (nreverse rhs) production-name (nreverse constraints))))
|
||||
(list* lhs-nonterminal (nreverse rhs) production-name production-highlight (nreverse constraints))))
|
||||
production-source)))
|
||||
|
||||
|
||||
@ -1213,7 +1257,8 @@
|
||||
; A grammar-source is a list of productions; each production is a list of:
|
||||
; a nonterminal A (the lhs);
|
||||
; a list of grammar symbols forming A's expansion (the rhs);
|
||||
; a production name.
|
||||
; a production name;
|
||||
; a highlight keyword or nil.
|
||||
; Nonterminals in the lhs and rhs can be parametrized; in this case such a nonterminal
|
||||
; is represented by a list whose first element is the name and the remaining elements are
|
||||
; the arguments or attributes. Any nonterminal argument in the rhs must also be an argument
|
||||
@ -1241,11 +1286,15 @@
|
||||
; excluded-nonterminals 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 &key variant-constraint-names variant-generator excluded-nonterminals)
|
||||
;
|
||||
; highlights is a list of keywords that may be used to highlight specific rules or productions. Each production that includes
|
||||
; a highlight as its fourth element will be rendered using the markup style specified by highlight.
|
||||
(defun make-grammar (grammar-parametrization start-symbol grammar-source &key variant-constraint-names variant-generator excluded-nonterminals highlights)
|
||||
(assert-type highlights (list keyword))
|
||||
(let ((variant-constraint-forbid-lists (mapcar #'list variant-constraint-names))
|
||||
(interned-grammar-source
|
||||
(mapcar #'(lambda (production-source)
|
||||
(intern-production-source grammar-parametrization variant-constraint-names production-source))
|
||||
(intern-production-source grammar-parametrization variant-constraint-names highlights production-source))
|
||||
grammar-source))
|
||||
(rules (make-hash-table :test #'eq))
|
||||
(terminals-hash (make-hash-table :test *grammar-symbol-=*))
|
||||
@ -1264,12 +1313,12 @@
|
||||
|
||||
;Create the starting production: *start-nonterminal* ==> start-symbol
|
||||
(setf (gethash *start-nonterminal* rules)
|
||||
(list (make-production *start-nonterminal* (list start-symbol) nil nil 1 0)))
|
||||
(list (make-production *start-nonterminal* (list start-symbol) nil nil nil 1 0)))
|
||||
|
||||
;Create the rest of the productions.
|
||||
(flet
|
||||
((create-production (lhs rhs constraints name)
|
||||
(let ((production (make-production lhs rhs constraints name (length rhs) (incf production-number))))
|
||||
((create-production (lhs rhs constraints name highlight)
|
||||
(let ((production (make-production lhs rhs constraints name highlight (length rhs) (incf production-number))))
|
||||
(push production (gethash lhs rules))
|
||||
(dolist (rhs-terminal (production-terminals production))
|
||||
(setf (gethash rhs-terminal terminals-hash) t))
|
||||
@ -1283,7 +1332,8 @@
|
||||
(let* ((production-lhs (first production-source))
|
||||
(production-rhs (second production-source))
|
||||
(production-name (third production-source))
|
||||
(production-constraints (cdddr production-source))
|
||||
(production-highlight (fourth production-source))
|
||||
(production-constraints (cddddr production-source))
|
||||
(lhs-arguments (general-grammar-symbol-arguments production-lhs)))
|
||||
(setq max-production-length (max max-production-length (length production-rhs)))
|
||||
(when (gethash production-name general-productions)
|
||||
@ -1301,16 +1351,17 @@
|
||||
(instantiate-general-grammar-symbol bound-argument-alist general-grammar-symbol))
|
||||
production-rhs)
|
||||
production-constraints
|
||||
production-name)
|
||||
production-name
|
||||
production-highlight)
|
||||
productions))))
|
||||
lhs-arguments)
|
||||
(when productions
|
||||
(setf (gethash production-name general-productions)
|
||||
(make-generic-production production-lhs production-rhs production-constraints production-name (nreverse productions)))))
|
||||
(make-generic-production production-lhs production-rhs production-constraints production-name production-highlight (nreverse productions)))))
|
||||
|
||||
(unless (nonterminal-excluded production-lhs)
|
||||
(setf (gethash production-name general-productions)
|
||||
(create-production production-lhs production-rhs production-constraints production-name)))))))
|
||||
(create-production production-lhs production-rhs production-constraints production-name production-highlight)))))))
|
||||
|
||||
|
||||
(when variant-generator
|
||||
@ -1384,7 +1435,8 @@
|
||||
:parameter-trees (make-hash-table :test *grammar-symbol-=*)
|
||||
:max-production-length max-production-length
|
||||
:general-productions general-productions
|
||||
:n-productions production-number)))
|
||||
:n-productions production-number
|
||||
:highlights highlights)))
|
||||
|
||||
;Compute the terminalsets in the terminal-terminalsets.
|
||||
(dotimes (n (length terminals))
|
||||
@ -1527,7 +1579,7 @@
|
||||
(depict-general-nonterminal markup-stream (gramar-user-start-symbol grammar) :reference))
|
||||
(dolist (nonterminal (grammar-nonterminals-list grammar))
|
||||
(unless (grammar-symbol-= nonterminal *start-nonterminal*)
|
||||
(depict-general-rule markup-stream (grammar-rule grammar nonterminal)))))
|
||||
(depict-general-rule markup-stream (grammar-rule grammar nonterminal) (grammar-highlights grammar)))))
|
||||
|
||||
|
||||
; Return a list of nontrivial sets of states with the same kernels.
|
||||
|
@ -450,6 +450,8 @@
|
||||
((:zeta 1) (:script "document.write(U_zeta)"))
|
||||
|
||||
;Block Styles
|
||||
(:js2 (div (class "js2")))
|
||||
(:es4 (div (class "es4")))
|
||||
(:body-text p)
|
||||
(:section-heading h2)
|
||||
(:subsection-heading h3)
|
||||
@ -509,9 +511,10 @@
|
||||
;;; HTML STREAMS
|
||||
|
||||
(defstruct (html-stream (:include markup-stream)
|
||||
(:constructor allocate-html-stream (env head tail level logical-position anchors))
|
||||
(:constructor allocate-html-stream (env head tail level logical-position enclosing-styles anchors))
|
||||
(:copier nil)
|
||||
(:predicate html-stream?))
|
||||
(enclosing-styles nil :type list :read-only t) ;A list of enclosing styles
|
||||
(anchors nil :type list :read-only t)) ;A mutable cons cell for accumulating anchors at the beginning of a paragraph
|
||||
; ;or nil if not inside a paragraph.
|
||||
|
||||
@ -522,9 +525,9 @@
|
||||
|
||||
|
||||
; Make a new, empty, open html-stream with the given definitions for its markup-env.
|
||||
(defun make-html-stream (markup-env level logical-position anchors)
|
||||
(defun make-html-stream (markup-env level logical-position enclosing-styles anchors)
|
||||
(let ((head (list nil)))
|
||||
(allocate-html-stream markup-env head head level logical-position anchors)))
|
||||
(allocate-html-stream markup-env head head level logical-position enclosing-styles anchors)))
|
||||
|
||||
|
||||
; Make a new, empty, open, top-level html-stream with the given definitions
|
||||
@ -533,7 +536,7 @@
|
||||
(let ((head (list nil))
|
||||
(markup-env (make-markup-env links)))
|
||||
(markup-env-define-alist markup-env html-definitions)
|
||||
(allocate-html-stream markup-env head head *markup-stream-top-level* nil nil)))
|
||||
(allocate-html-stream markup-env head head *markup-stream-top-level* nil nil nil)))
|
||||
|
||||
|
||||
; Return the approximate width of the html item; return t if it is a line break.
|
||||
@ -585,14 +588,23 @@
|
||||
|
||||
|
||||
|
||||
(defmethod depict-block-style-f ((html-stream html-stream) block-style emitter)
|
||||
(defmethod depict-block-style-f ((html-stream html-stream) block-style flatten emitter)
|
||||
(assert-true (<= (markup-stream-level html-stream) *markup-stream-paragraph-level*))
|
||||
(assert-true (and block-style (symbolp block-style)))
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream) *markup-stream-paragraph-level* nil nil)))
|
||||
(markup-stream-append1 inner-html-stream block-style)
|
||||
(prog1
|
||||
(funcall emitter inner-html-stream)
|
||||
(markup-stream-append1 html-stream (markup-stream-unexpanded-output inner-html-stream)))))
|
||||
(assert-true (symbolp block-style))
|
||||
(if (or (null block-style)
|
||||
(and flatten (member block-style (html-stream-enclosing-styles html-stream))))
|
||||
(funcall emitter html-stream)
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-paragraph-level*
|
||||
nil
|
||||
(cons block-style (html-stream-enclosing-styles html-stream))
|
||||
nil)))
|
||||
(markup-stream-append1 inner-html-stream block-style)
|
||||
(prog1
|
||||
(funcall emitter inner-html-stream)
|
||||
(let ((inner-output (markup-stream-unexpanded-output inner-html-stream)))
|
||||
(when (or (not flatten) (cdr inner-output))
|
||||
(markup-stream-append1 html-stream inner-output)))))))
|
||||
|
||||
|
||||
(defmethod depict-paragraph-f ((html-stream html-stream) paragraph-style emitter)
|
||||
@ -602,6 +614,7 @@
|
||||
(inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-content-level*
|
||||
(make-logical-position)
|
||||
(cons paragraph-style (html-stream-enclosing-styles html-stream))
|
||||
anchors)))
|
||||
(prog1
|
||||
(funcall emitter inner-html-stream)
|
||||
@ -616,6 +629,7 @@
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-content-level*
|
||||
(markup-stream-logical-position html-stream)
|
||||
(cons char-style (html-stream-enclosing-styles html-stream))
|
||||
(html-stream-anchors html-stream))))
|
||||
(markup-stream-append1 inner-html-stream char-style)
|
||||
(prog1
|
||||
@ -623,6 +637,11 @@
|
||||
(markup-stream-append1 html-stream (markup-stream-unexpanded-output inner-html-stream)))))
|
||||
|
||||
|
||||
(defmethod ensure-no-enclosing-style ((html-stream html-stream) style)
|
||||
(when (member style (html-stream-enclosing-styles html-stream))
|
||||
(cerror "Ignore" "Style ~S should not be in effect" style)))
|
||||
|
||||
|
||||
(defmethod depict-anchor ((html-stream html-stream) link-prefix link-name duplicate)
|
||||
(assert-true (= (markup-stream-level html-stream) *markup-stream-content-level*))
|
||||
(let* ((links (markup-env-links (html-stream-env html-stream)))
|
||||
@ -639,6 +658,7 @@
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-content-level*
|
||||
(markup-stream-logical-position html-stream)
|
||||
(html-stream-enclosing-styles html-stream)
|
||||
(html-stream-anchors html-stream))))
|
||||
(markup-stream-append1 inner-html-stream (list 'a (list 'href href)))
|
||||
(prog1
|
||||
|
@ -383,7 +383,7 @@
|
||||
|
||||
; Return the charset of all characters that appear as terminals in grammar-source.
|
||||
(defun grammar-singletons (grammar-source)
|
||||
(assert-type grammar-source (list (tuple t (list t) identifier)))
|
||||
(assert-type grammar-source (list (tuple t (list t) identifier t)))
|
||||
(let ((singletons 0))
|
||||
(labels
|
||||
((scan-for-singletons (list)
|
||||
@ -648,7 +648,7 @@
|
||||
(char-charset partition-name)
|
||||
(partition-charset (gethash partition-name (lexer-partitions lexer)))))
|
||||
(production-name (intern (format nil "~A-~D" production-prefix (incf production-number)))))
|
||||
(push (list nonterminal-source (list partition-name) production-name) productions)
|
||||
(push (list nonterminal-source (list partition-name) production-name nil) productions)
|
||||
(dolist (action (charclass-actions charclass))
|
||||
(let* ((lexer-action (cdr action))
|
||||
(body (if (characterp partition-name)
|
||||
|
@ -337,14 +337,16 @@
|
||||
|
||||
; markup-stream must be a variable that names a markup-stream that is currently
|
||||
; accepting paragraphs. Execute body with markup-stream bound to a markup-stream
|
||||
; to which the body can emit contents. The given block-style is applied to all
|
||||
; to which the body can emit contents. If non-null, the given block-style is applied to all
|
||||
; paragraphs emitted by body (in the HTML emitter only; RTF has no block styles).
|
||||
; If flatten is true, do not emit the style if it is already in effect from a surrounding block
|
||||
; or if its contents are empty.
|
||||
; Return the result value of body.
|
||||
(defmacro depict-block-style ((markup-stream block-style) &body body)
|
||||
`(depict-block-style-f ,markup-stream ,block-style
|
||||
(defmacro depict-block-style ((markup-stream block-style &optional flatten) &body body)
|
||||
`(depict-block-style-f ,markup-stream ,block-style ,flatten
|
||||
#'(lambda (,markup-stream) ,@body)))
|
||||
|
||||
(defgeneric depict-block-style-f (markup-stream block-style emitter))
|
||||
(defgeneric depict-block-style-f (markup-stream block-style flatten emitter))
|
||||
|
||||
|
||||
; markup-stream must be a variable that names a markup-stream that is currently
|
||||
@ -371,6 +373,11 @@
|
||||
(defgeneric depict-char-style-f (markup-stream char-style emitter))
|
||||
|
||||
|
||||
; Ensure that the given style is not currently in effect in the markup-stream.
|
||||
; RTF streams don't currently keep track of styles, so this function does nothing for RTF streams.
|
||||
(defgeneric ensure-no-enclosing-style (markup-stream style))
|
||||
|
||||
|
||||
; Depict an anchor. The concatenation of link-prefix and link-name must be a string
|
||||
; suitable for an anchor name.
|
||||
; If duplicate is true, allow duplicate calls for the same link-name, in which case only
|
||||
|
@ -757,8 +757,8 @@
|
||||
(markup-env-expand (markup-stream-env rtf-stream) (markup-stream-unexpanded-output rtf-stream) nil))
|
||||
|
||||
|
||||
(defmethod depict-block-style-f ((rtf-stream rtf-stream) block-style emitter)
|
||||
(declare (ignore block-style))
|
||||
(defmethod depict-block-style-f ((rtf-stream rtf-stream) block-style flatten emitter)
|
||||
(declare (ignore block-style flatten))
|
||||
(assert-true (= (markup-stream-level rtf-stream) *markup-stream-paragraph-level*))
|
||||
(funcall emitter rtf-stream))
|
||||
|
||||
@ -790,6 +790,10 @@
|
||||
(rtf-stream-append-or-inline-block rtf-stream (markup-stream-unexpanded-output inner-rtf-stream)))))
|
||||
|
||||
|
||||
(defmethod ensure-no-enclosing-style ((rtf-stream rtf-stream) style)
|
||||
(declare (ignore style)))
|
||||
|
||||
|
||||
(defmethod depict-anchor ((rtf-stream rtf-stream) link-prefix link-name duplicate)
|
||||
(declare (ignore link-prefix link-name duplicate))
|
||||
(assert-true (= (markup-stream-level rtf-stream) *markup-stream-content-level*)))
|
||||
|
@ -26,7 +26,7 @@
|
||||
(defvar *trace-variables* nil)
|
||||
|
||||
|
||||
#+mcl (dolist (indent-spec '((apply . 1) (funcall . 1) (production . 3) (rule . 2) (function . 1) (letexc . 1) (deftype . 1) (tuple . 1) (%text . 1)))
|
||||
#+mcl (dolist (indent-spec '((? . 1) (apply . 1) (funcall . 1) (production . 3) (rule . 2) (function . 1) (letexc . 1) (deftype . 1) (tuple . 1) (%text . 1)))
|
||||
(pushnew indent-spec ccl:*fred-special-indent-alist* :test #'equal))
|
||||
|
||||
|
||||
@ -426,6 +426,7 @@
|
||||
(defstruct (world (:constructor allocate-world)
|
||||
(:copier nil)
|
||||
(:predicate world?))
|
||||
(conditionals nil :type list) ;Assoc list of (conditional . highlight), where highlight can be a style keyword, nil (no style), or 'delete
|
||||
(package nil :type package) ;The package in which this world's identifiers are interned
|
||||
(n-type-names 0 :type integer) ;Number of type names defined so far
|
||||
(types-reverse nil :type (or null hash-table)) ;Hash table of (kind tags parameters) -> type; nil if invalid
|
||||
@ -577,6 +578,25 @@
|
||||
(and grammar-info (grammar-info-lexer grammar-info))))
|
||||
|
||||
|
||||
; Return a list of highlights allowed in this world.
|
||||
(defun world-highlights (world)
|
||||
(let ((highlights nil))
|
||||
(dolist (c (world-conditionals world))
|
||||
(let ((highlight (cdr c)))
|
||||
(unless (or (null highlight) (eq highlight 'delete))
|
||||
(pushnew highlight highlights))))
|
||||
(nreverse highlights)))
|
||||
|
||||
|
||||
; Return the highlight to which the given conditional maps.
|
||||
; Return 'delete if the conditional should be omitted.
|
||||
(defun resolve-conditional (world conditional)
|
||||
(let ((h (assoc conditional (world-conditionals world))))
|
||||
(if h
|
||||
(cdr h)
|
||||
(error "Bad conditional ~S" conditional))))
|
||||
|
||||
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; SYMBOLS
|
||||
|
||||
@ -2327,6 +2347,13 @@
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; COMMANDS
|
||||
|
||||
; (%highlight <highlight> <command> ... <command>)
|
||||
; Evaluate the given commands. <highlight> is a hint for printing.
|
||||
(defun scan-%highlight (world grammar-info-var highlight &rest commands)
|
||||
(declare (ignore highlight))
|
||||
(scan-commands world grammar-info-var commands))
|
||||
|
||||
|
||||
; (%... ...)
|
||||
; Ignore any command that starts with a %. These commands are hints for printing.
|
||||
(defun scan-% (world grammar-info-var &rest rest)
|
||||
@ -2415,6 +2442,7 @@
|
||||
|
||||
(defparameter *default-specials*
|
||||
'((:preprocess
|
||||
(? preprocess-?)
|
||||
(define preprocess-define)
|
||||
(action preprocess-action)
|
||||
(grammar preprocess-grammar)
|
||||
@ -2431,6 +2459,7 @@
|
||||
(set-of expand-set-of nil))
|
||||
|
||||
(:command
|
||||
(%highlight scan-%highlight depict-%highlight) ;For internal use only; use ? instead.
|
||||
(%section scan-% depict-%section)
|
||||
(%subsection scan-% depict-%subsection)
|
||||
(%text scan-% depict-%text)
|
||||
@ -2636,8 +2665,15 @@
|
||||
|
||||
|
||||
; Create a world with the given name and set up the built-in properties of its symbols.
|
||||
(defun init-world (name)
|
||||
; conditionals is an association list of (conditional . highlight), where conditional is a symbol
|
||||
; and highlight is either:
|
||||
; a style keyword: Use that style to highlight the contents of any (? conditional ...) commands
|
||||
; nil: Include the contents of any (? conditional ...) commands without highlighting them
|
||||
; delete: Don't include the contents of (? conditional ...) commands
|
||||
(defun init-world (name conditionals)
|
||||
(assert-type conditionals (list (cons symbol (or null keyword (eql delete)))))
|
||||
(let ((world (make-world name)))
|
||||
(setf (world-conditionals world) conditionals)
|
||||
(dolist (specials-list *default-specials*)
|
||||
(let ((property (car specials-list)))
|
||||
(dolist (special-spec (cdr specials-list))
|
||||
@ -2753,10 +2789,8 @@
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; EVALUATION
|
||||
|
||||
; Scan a command. Create types and variables in the world
|
||||
; but do not evaluate variables' types or values yet.
|
||||
; grammar-info-var is a cons cell whose car is either nil
|
||||
; or a grammar-info for the grammar currently being defined.
|
||||
; Scan a command. Create types and variables in the world but do not evaluate variables' types or values yet.
|
||||
; grammar-info-var is a cons cell whose car is either nil or a grammar-info for the grammar currently being defined.
|
||||
(defun scan-command (world grammar-info-var command)
|
||||
(handler-bind ((error #'(lambda (condition)
|
||||
(declare (ignore condition))
|
||||
@ -2769,6 +2803,12 @@
|
||||
(error "Bad command")))))
|
||||
|
||||
|
||||
; Scan a list of commands. See scan-command above.
|
||||
(defun scan-commands (world grammar-info-var commands)
|
||||
(dolist (command commands)
|
||||
(scan-command world grammar-info-var command)))
|
||||
|
||||
|
||||
; Compute the primitives' types from their type-exprs.
|
||||
(defun define-primitives (world)
|
||||
(each-world-external-symbol-with-property
|
||||
@ -2864,8 +2904,7 @@
|
||||
(assert-true (null (world-commands-source world)))
|
||||
(setf (world-commands-source world) commands)
|
||||
(let ((grammar-info-var (list nil)))
|
||||
(dolist (command commands)
|
||||
(scan-command world grammar-info-var command)))
|
||||
(scan-commands world grammar-info-var commands))
|
||||
(unite-types world)
|
||||
(setf (world-bottom-type world) (make-type world :bottom nil nil))
|
||||
(setf (world-void-type world) (make-type world :void nil nil))
|
||||
@ -2884,7 +2923,9 @@
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
;;; PREPROCESSING
|
||||
|
||||
(defstruct preprocessor-state
|
||||
(defstruct (preprocessor-state (:constructor make-preprocessor-state (world)))
|
||||
(world nil :type world :read-only t) ;The world into which preprocessed symbols are interned
|
||||
(highlight nil :type symbol) ;The current highlight style or nil if none
|
||||
(kind nil :type (member nil :grammar :lexer)) ;The kind of grammar being accumulated or nil if none
|
||||
(kind2 nil :type (member nil :lalr-1 :lr-1 :canonical-lr-1)) ;The kind of parser
|
||||
(name nil :type symbol) ;Name of the grammar being accumulated or nil if none
|
||||
@ -2914,7 +2955,8 @@
|
||||
(start-symbol (preprocessor-state-start-symbol preprocessor-state))
|
||||
(grammar-source (nreverse (preprocessor-state-grammar-source-reverse preprocessor-state)))
|
||||
(excluded-nonterminals-source (preprocessor-state-excluded-nonterminals-source preprocessor-state))
|
||||
(grammar-options (preprocessor-state-grammar-options preprocessor-state)))
|
||||
(grammar-options (preprocessor-state-grammar-options preprocessor-state))
|
||||
(highlights (world-highlights (preprocessor-state-world preprocessor-state))))
|
||||
(multiple-value-bind (grammar lexer extra-commands)
|
||||
(ecase kind
|
||||
(:grammar
|
||||
@ -2924,6 +2966,7 @@
|
||||
start-symbol
|
||||
grammar-source
|
||||
:excluded-nonterminals excluded-nonterminals-source
|
||||
:highlights highlights
|
||||
grammar-options)
|
||||
nil
|
||||
nil))
|
||||
@ -2937,6 +2980,7 @@
|
||||
start-symbol
|
||||
grammar-source
|
||||
:excluded-nonterminals excluded-nonterminals-source
|
||||
:highlights highlights
|
||||
grammar-options)
|
||||
(values (lexer-grammar lexer) lexer extra-commands))))
|
||||
(let ((grammar-info (make-grammar-info (preprocessor-state-name preprocessor-state) grammar lexer)))
|
||||
@ -2954,19 +2998,17 @@
|
||||
(append extra-commands (list '(clear-grammar)))))))))
|
||||
|
||||
|
||||
; Helper function for preprocess-source.
|
||||
; source is a list of preprocessor directives and commands. Preprocess these commands
|
||||
; and return the following results:
|
||||
; a list of preprocessed commands;
|
||||
; a list of grammar-infos extracted from preprocessor directives.
|
||||
(defun preprocess-source (world source)
|
||||
(let ((preprocessor-state (make-preprocessor-state)))
|
||||
(labels
|
||||
; using the given preprocessor-state and return the resulting list of commands.
|
||||
(defun preprocess-list (preprocessor-state source)
|
||||
(let ((world (preprocessor-state-world preprocessor-state)))
|
||||
(flet
|
||||
((preprocess-one (form)
|
||||
(when (consp form)
|
||||
(let ((first (car form)))
|
||||
(when (identifier? first)
|
||||
(let* ((symbol (world-intern world first))
|
||||
(action (symbol-preprocessor-function symbol)))
|
||||
(let ((action (symbol-preprocessor-function (world-intern world first))))
|
||||
(when action
|
||||
(handler-bind ((error #'(lambda (condition)
|
||||
(declare (ignore condition))
|
||||
@ -2974,19 +3016,33 @@
|
||||
(multiple-value-bind (preprocessed-form re-preprocess) (apply action preprocessor-state form)
|
||||
(return-from preprocess-one
|
||||
(if re-preprocess
|
||||
(mapcan #'preprocess-one preprocessed-form)
|
||||
(preprocess-list preprocessor-state preprocessed-form)
|
||||
preprocessed-form)))))))))
|
||||
(list form)))
|
||||
|
||||
(let* ((commands (mapcan #'preprocess-one source))
|
||||
(commands (nconc commands (preprocessor-state-finish-grammar preprocessor-state))))
|
||||
(values commands (nreverse (preprocessor-state-grammar-infos-reverse preprocessor-state)))))))
|
||||
(mapcan #'preprocess-one source))))
|
||||
|
||||
|
||||
; source is a list of preprocessor directives and commands. Preprocess these commands
|
||||
; and return the following results:
|
||||
; a list of preprocessed commands;
|
||||
; a list of grammar-infos extracted from preprocessor directives.
|
||||
(defun preprocess-source (world source)
|
||||
(let* ((preprocessor-state (make-preprocessor-state world))
|
||||
(commands (preprocess-list preprocessor-state source))
|
||||
(commands (nconc commands (preprocessor-state-finish-grammar preprocessor-state))))
|
||||
(values commands (nreverse (preprocessor-state-grammar-infos-reverse preprocessor-state)))))
|
||||
|
||||
|
||||
; Create a new world with the given name and preprocess and evaluate the given
|
||||
; source commands in it.
|
||||
(defun generate-world (name source)
|
||||
(let ((world (init-world name)))
|
||||
; conditionals is an association list of (conditional . highlight), where conditional is a symbol
|
||||
; and highlight is either:
|
||||
; a style keyword: Use that style to highlight the contents of any (? conditional ...) commands
|
||||
; nil: Include the contents of any (? conditional ...) commands without highlighting them
|
||||
; delete: Don't include the contents of (? conditional ...) commands
|
||||
(defun generate-world (name source &optional conditionals)
|
||||
(let ((world (init-world name conditionals)))
|
||||
(multiple-value-bind (commands grammar-infos) (preprocess-source world source)
|
||||
(dolist (grammar-info grammar-infos)
|
||||
(clear-actions (grammar-info-grammar grammar-info)))
|
||||
@ -2999,6 +3055,27 @@
|
||||
;;; PREPROCESSOR ACTIONS
|
||||
|
||||
|
||||
; (? <conditional> <command> ... <command>)
|
||||
; ==>
|
||||
; (%highlight <highlight> <command> ... <command>)
|
||||
; or
|
||||
; <empty>
|
||||
(defun preprocess-? (preprocessor-state command conditional &rest commands)
|
||||
(declare (ignore command))
|
||||
(let ((highlight (resolve-conditional (preprocessor-state-world preprocessor-state) conditional))
|
||||
(saved-highlight (preprocessor-state-highlight preprocessor-state)))
|
||||
(cond
|
||||
((eq highlight 'delete) (values nil nil))
|
||||
((eq highlight saved-highlight) (values commands t))
|
||||
(t (values
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setf (preprocessor-state-highlight preprocessor-state) highlight)
|
||||
(list (list* '%highlight highlight (preprocess-list preprocessor-state commands))))
|
||||
(setf (preprocessor-state-highlight preprocessor-state) saved-highlight))
|
||||
nil)))))
|
||||
|
||||
|
||||
; (define <name> <type> <value>)
|
||||
; ==>
|
||||
; (define <name> <type> <value> nil)
|
||||
@ -3123,7 +3200,7 @@
|
||||
; (production <lhs> <rhs> <name> (<action-spec-1> <body-1>) ... (<action-spec-n> <body-n>))
|
||||
; ==>
|
||||
; grammar:
|
||||
; (<lhs> <rhs> <name>)
|
||||
; (<lhs> <rhs> <name> <current-highlight>)
|
||||
; commands:
|
||||
; (%rule <lhs>)
|
||||
; (action <action-spec-1> <name> <body-1>)
|
||||
@ -3133,7 +3210,8 @@
|
||||
(declare (ignore command))
|
||||
(assert-type actions (list (tuple t t)))
|
||||
(preprocess-ensure-grammar preprocessor-state)
|
||||
(push (list lhs rhs name) (preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(push (list lhs rhs name (preprocessor-state-highlight preprocessor-state))
|
||||
(preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(values
|
||||
(cons (list '%rule lhs)
|
||||
(mapcar #'(lambda (action)
|
||||
@ -3149,9 +3227,9 @@
|
||||
; (production <lhs-m> <rhs-m> <name-m> (<action-spec-m-1> <body-m-1>) ... (<action-spec-m-n> <body-m-n>)))
|
||||
; ==>
|
||||
; grammar:
|
||||
; (<lhs-1> <rhs-1> <name-1>)
|
||||
; (<lhs-1> <rhs-1> <name-1> <current-highlight>)
|
||||
; ...
|
||||
; (<lhs-m> <rhs-m> <name-m>)
|
||||
; (<lhs-m> <rhs-m> <name-m> <current-highlight>)
|
||||
; commands:
|
||||
; (%rule <lhs-1>)
|
||||
; ...
|
||||
@ -3188,7 +3266,8 @@
|
||||
(actions (assert-type (cddddr production) (list (tuple t t)))))
|
||||
(unless (actions-match action-declarations actions)
|
||||
(error "Action name mismatch: ~S vs. ~S" action-declarations actions))
|
||||
(push (list lhs rhs name) (preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(push (list lhs rhs name (preprocessor-state-highlight preprocessor-state))
|
||||
(preprocessor-state-grammar-source-reverse preprocessor-state))
|
||||
(push (list '%rule lhs) commands-reverse)))
|
||||
(dotimes (i (length action-declarations))
|
||||
(let ((action-declaration (nth i action-declarations)))
|
||||
|
@ -113,11 +113,16 @@
|
||||
(error "Bad command: ~S" command)))))
|
||||
|
||||
|
||||
; Emit markup paragraphs for a list of commands.
|
||||
(defun depict-commands (markup-stream world depict-env commands)
|
||||
(dolist (command commands)
|
||||
(depict-command markup-stream world depict-env command)))
|
||||
|
||||
|
||||
; Emit markup paragraphs for the world's commands.
|
||||
(defun depict-world-commands (markup-stream world &key (visible-semantics t))
|
||||
(let ((depict-env (make-depict-env visible-semantics)))
|
||||
(dolist (command (world-commands-source world))
|
||||
(depict-command markup-stream world depict-env command))
|
||||
(depict-commands markup-stream world depict-env (world-commands-source world))
|
||||
(depict-clear-grammar markup-stream world depict-env)))
|
||||
|
||||
|
||||
@ -861,6 +866,14 @@
|
||||
,@body)))
|
||||
|
||||
|
||||
; (%highlight <highlight> <command> ... <command>)
|
||||
; Depict the commands highlighted with the <highlight> block style.
|
||||
(defun depict-%highlight (markup-stream world depict-env highlight &rest commands)
|
||||
(when commands
|
||||
(depict-block-style (markup-stream highlight t)
|
||||
(depict-commands markup-stream world depict-env commands))))
|
||||
|
||||
|
||||
; (%section "section-name")
|
||||
(defun depict-%section (markup-stream world depict-env section-name)
|
||||
(declare (ignore world))
|
||||
@ -936,7 +949,7 @@
|
||||
(when (some #'seen-nonterminal? rule-lhs-nonterminals)
|
||||
(warn "General rule for ~S listed before specific ones; use %rule to disambiguate" general-nonterminal))
|
||||
(when visible
|
||||
(depict-general-rule markup-stream general-rule))
|
||||
(depict-general-rule markup-stream general-rule (grammar-highlights grammar)))
|
||||
(dolist (nonterminal rule-lhs-nonterminals)
|
||||
(setf (gethash nonterminal seen-nonterminals) t))))))))))
|
||||
;******** May still have a problem when a specific rule precedes a general one.
|
||||
|
@ -218,7 +218,8 @@
|
||||
(lhs nil :type general-nonterminal :read-only t) ;The general-nonterminal on the left-hand side of this general-production
|
||||
(rhs nil :type list :read-only t) ;List of general grammar symbols to which that general-nonterminal expands
|
||||
(constraints nil :type list :read-only t) ;List of constraints applying to rhs, sorted by increasing pos values
|
||||
(name nil :read-only t)) ;This general-production's name that will be used to name the parse tree node
|
||||
(name nil :read-only t) ;This general-production's name that will be used to name the parse tree node
|
||||
(highlight nil :read-only t)) ;This general-production's markup style keyword or nil if default
|
||||
|
||||
|
||||
; If general-production is a generic-production, return its list of productions;
|
||||
@ -340,7 +341,7 @@
|
||||
;;; The evaluator is a lisp form that evaluates to a function f that takes one argument --
|
||||
;;; the old state of the parser's value stack -- and returns the new state of that stack.
|
||||
(defstruct (production (:include general-production (lhs nil :type nonterminal :read-only t))
|
||||
(:constructor make-production (lhs rhs constraints name rhs-length number))
|
||||
(:constructor make-production (lhs rhs constraints name highlight rhs-length number))
|
||||
(:copier nil) (:predicate production?))
|
||||
(rhs-length nil :type integer :read-only t) ;Number of grammar symbols in the rhs
|
||||
(number nil :type integer :read-only t) ;This production's serial number
|
||||
@ -385,7 +386,7 @@
|
||||
;;; A generic production is not a production and does not have a number or actions.
|
||||
|
||||
(defstruct (generic-production (:include general-production (lhs nil :type generic-nonterminal :read-only t))
|
||||
(:constructor make-generic-production (lhs rhs constraints name productions))
|
||||
(:constructor make-generic-production (lhs rhs constraints name highlight productions))
|
||||
(:copier nil)
|
||||
(:predicate generic-production?))
|
||||
(productions nil :type list :read-only t)) ;List of instantiations of this generic production
|
||||
@ -404,6 +405,7 @@
|
||||
(generic-production-rhs generic-production))
|
||||
(general-production-constraints generic-production)
|
||||
(generic-production-name generic-production)
|
||||
(generic-production-highlight generic-production)
|
||||
(remove-if #'(lambda (production)
|
||||
(not (general-nonterminal-is-instance? grammar-parametrization new-lhs (production-lhs production))))
|
||||
productions))
|
||||
@ -426,24 +428,62 @@
|
||||
(general-production-lhs (first (general-rule-productions general-rule))))
|
||||
|
||||
|
||||
; Return the given highlight. If it is nil, return nil and ensure that no other
|
||||
; highlight (from the list given by highlights) is currently in effect in the markup-stream.
|
||||
(defun check-highlight (highlight highlights markup-stream)
|
||||
(if highlight
|
||||
(assert-true (member highlight highlights))
|
||||
(dolist (h highlights)
|
||||
(ensure-no-enclosing-style markup-stream h)))
|
||||
highlight)
|
||||
|
||||
|
||||
; Return the list of general-productions, in order, gathered into runs of consecutive productions with the same highlight value.
|
||||
; The result is a list of runs:
|
||||
; (<highlight> <p> ... <p>),
|
||||
; where each <p> is:
|
||||
; (<general-production> <first> <last>),
|
||||
; where <first> is true if this is the first production and <last> is true if this is the last production.
|
||||
(defun gather-productions-by-highlights (general-productions)
|
||||
(when general-productions
|
||||
(let* ((first-production (first general-productions))
|
||||
(prior-runs-reverse nil)
|
||||
(current-highlight (general-production-highlight first-production))
|
||||
(current-run-productions-reverse (list (list first-production t nil))))
|
||||
(dolist (general-production (rest general-productions))
|
||||
(let ((highlight (general-production-highlight general-production))
|
||||
(p (list general-production nil nil)))
|
||||
(if (eq highlight current-highlight)
|
||||
(push p current-run-productions-reverse)
|
||||
(progn
|
||||
(push (cons current-highlight (nreverse current-run-productions-reverse)) prior-runs-reverse)
|
||||
(setq current-highlight highlight)
|
||||
(setq current-run-productions-reverse (list p))))))
|
||||
(setf (third (first current-run-productions-reverse)) t)
|
||||
(nreconc prior-runs-reverse (list (cons current-highlight (nreverse current-run-productions-reverse)))))))
|
||||
|
||||
|
||||
; Emit markup paragraphs for the grammar general rule.
|
||||
; If the rule is short enough (only one production), emit the rule on one line.
|
||||
(defun depict-general-rule (markup-stream general-rule)
|
||||
(depict-block-style (markup-stream ':grammar-rule)
|
||||
(let ((general-productions (general-rule-productions general-rule)))
|
||||
(assert-true general-productions)
|
||||
(if (cdr general-productions)
|
||||
(labels
|
||||
((emit-general-productions (general-productions first)
|
||||
(let ((general-production (first general-productions))
|
||||
(rest (rest general-productions)))
|
||||
(depict-general-production-rhs markup-stream general-production first (endp rest))
|
||||
(when rest
|
||||
(emit-general-productions rest nil)))))
|
||||
(depict-general-production-lhs markup-stream (general-rule-lhs general-rule))
|
||||
(emit-general-productions general-productions t))
|
||||
(depict-paragraph (markup-stream ':grammar-lhs-last)
|
||||
(depict-general-production markup-stream (first general-productions) :definition))))))
|
||||
; highlights is a list of keywords that may be used to highlight specific rules or productions. It should
|
||||
; be the same as the list of highlights passed to make-grammar.
|
||||
(defun depict-general-rule (markup-stream general-rule highlights)
|
||||
(let ((general-productions (general-rule-productions general-rule)))
|
||||
(assert-true general-productions)
|
||||
(let* ((production-runs (gather-productions-by-highlights general-productions))
|
||||
(rule-highlight (and (endp (rest production-runs))
|
||||
(check-highlight (first (first production-runs)) highlights markup-stream))))
|
||||
(depict-block-style (markup-stream rule-highlight t)
|
||||
(depict-block-style (markup-stream ':grammar-rule)
|
||||
(if (rest general-productions)
|
||||
(progn
|
||||
(depict-general-production-lhs markup-stream (general-rule-lhs general-rule))
|
||||
(dolist (production-run production-runs)
|
||||
(depict-block-style (markup-stream (check-highlight (first production-run) highlights markup-stream) t)
|
||||
(dolist (p (rest production-run))
|
||||
(apply #'depict-general-production-rhs markup-stream p)))))
|
||||
(depict-paragraph (markup-stream ':grammar-lhs-last)
|
||||
(depict-general-production markup-stream (first general-productions) :definition))))))))
|
||||
|
||||
|
||||
;;; ------------------------------------------------------------------------------------------------------
|
||||
@ -1046,6 +1086,7 @@
|
||||
(max-production-length nil :type integer :read-only t) ;Maximum number of grammar symbols in the rhs of a production
|
||||
(general-productions nil :type hash-table :read-only t);Hash table of production-name -> general-production
|
||||
(n-productions nil :type integer :read-only t) ;Number of productions in the grammar
|
||||
(highlights nil :type list :read-only t) ;List of style keywords for highlighting selected productions
|
||||
;The following fields are used for the parser.
|
||||
(items-hash nil :type (or null hash-table)) ;Hash table of (production . dot) -> item; nil for a cleaned grammar or a grammar without a parser
|
||||
(states nil :type list) ;List of LR(0) states (in order of state numbers)
|
||||
@ -1174,15 +1215,18 @@
|
||||
|
||||
; Intern attributed or generic nonterminals in the production's lhs and rhs. Replace
|
||||
; (:- <terminal> ... <terminal>) or (:-- (<grammar-symbol> ... <grammar-symbol>) <terminal> ... <terminal>)
|
||||
; sublists in the rhs with lookahead-constraints and put these, in order, after the third element of
|
||||
; sublists in the rhs with lookahead-constraints and put these, in order, after the fourth element of
|
||||
; the returned list. Also replace variant constraint symbols with variant-constraints.
|
||||
; The variant-constraint-names parameter should be a list of possible variant constraint symbols.
|
||||
; Return the resulting production source.
|
||||
(defun intern-production-source (grammar-parametrization variant-constraint-names production-source)
|
||||
(assert-type production-source (tuple (or user-nonterminal cons) (list (or user-grammar-symbol cons)) identifier))
|
||||
(defun intern-production-source (grammar-parametrization variant-constraint-names highlights production-source)
|
||||
(assert-type production-source (tuple (or user-nonterminal cons) (list (or user-grammar-symbol cons)) identifier t))
|
||||
(let ((production-lhs-source (first production-source))
|
||||
(production-rhs-source (second production-source))
|
||||
(production-name (third production-source)))
|
||||
(production-name (third production-source))
|
||||
(production-highlight (fourth production-source)))
|
||||
(unless (or (null production-highlight) (member production-highlight highlights :test #'eq))
|
||||
(error "Bad highlight in rule: ~S; allowed highlights are ~S" production-source highlights))
|
||||
(if (or (consp production-lhs-source) (some #'consp production-rhs-source) (intersection variant-constraint-names production-rhs-source))
|
||||
(multiple-value-bind (lhs-nonterminal lhs-arguments) (grammar-parametrization-intern grammar-parametrization production-lhs-source)
|
||||
(let ((rhs nil)
|
||||
@ -1205,7 +1249,7 @@
|
||||
(t
|
||||
(push (grammar-parametrization-intern grammar-parametrization component-source lhs-arguments) rhs)
|
||||
(incf pos))))
|
||||
(list* lhs-nonterminal (nreverse rhs) production-name (nreverse constraints))))
|
||||
(list* lhs-nonterminal (nreverse rhs) production-name production-highlight (nreverse constraints))))
|
||||
production-source)))
|
||||
|
||||
|
||||
@ -1213,7 +1257,8 @@
|
||||
; A grammar-source is a list of productions; each production is a list of:
|
||||
; a nonterminal A (the lhs);
|
||||
; a list of grammar symbols forming A's expansion (the rhs);
|
||||
; a production name.
|
||||
; a production name;
|
||||
; a highlight keyword or nil.
|
||||
; Nonterminals in the lhs and rhs can be parametrized; in this case such a nonterminal
|
||||
; is represented by a list whose first element is the name and the remaining elements are
|
||||
; the arguments or attributes. Any nonterminal argument in the rhs must also be an argument
|
||||
@ -1241,11 +1286,15 @@
|
||||
; excluded-nonterminals 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 &key variant-constraint-names variant-generator excluded-nonterminals)
|
||||
;
|
||||
; highlights is a list of keywords that may be used to highlight specific rules or productions. Each production that includes
|
||||
; a highlight as its fourth element will be rendered using the markup style specified by highlight.
|
||||
(defun make-grammar (grammar-parametrization start-symbol grammar-source &key variant-constraint-names variant-generator excluded-nonterminals highlights)
|
||||
(assert-type highlights (list keyword))
|
||||
(let ((variant-constraint-forbid-lists (mapcar #'list variant-constraint-names))
|
||||
(interned-grammar-source
|
||||
(mapcar #'(lambda (production-source)
|
||||
(intern-production-source grammar-parametrization variant-constraint-names production-source))
|
||||
(intern-production-source grammar-parametrization variant-constraint-names highlights production-source))
|
||||
grammar-source))
|
||||
(rules (make-hash-table :test #'eq))
|
||||
(terminals-hash (make-hash-table :test *grammar-symbol-=*))
|
||||
@ -1264,12 +1313,12 @@
|
||||
|
||||
;Create the starting production: *start-nonterminal* ==> start-symbol
|
||||
(setf (gethash *start-nonterminal* rules)
|
||||
(list (make-production *start-nonterminal* (list start-symbol) nil nil 1 0)))
|
||||
(list (make-production *start-nonterminal* (list start-symbol) nil nil nil 1 0)))
|
||||
|
||||
;Create the rest of the productions.
|
||||
(flet
|
||||
((create-production (lhs rhs constraints name)
|
||||
(let ((production (make-production lhs rhs constraints name (length rhs) (incf production-number))))
|
||||
((create-production (lhs rhs constraints name highlight)
|
||||
(let ((production (make-production lhs rhs constraints name highlight (length rhs) (incf production-number))))
|
||||
(push production (gethash lhs rules))
|
||||
(dolist (rhs-terminal (production-terminals production))
|
||||
(setf (gethash rhs-terminal terminals-hash) t))
|
||||
@ -1283,7 +1332,8 @@
|
||||
(let* ((production-lhs (first production-source))
|
||||
(production-rhs (second production-source))
|
||||
(production-name (third production-source))
|
||||
(production-constraints (cdddr production-source))
|
||||
(production-highlight (fourth production-source))
|
||||
(production-constraints (cddddr production-source))
|
||||
(lhs-arguments (general-grammar-symbol-arguments production-lhs)))
|
||||
(setq max-production-length (max max-production-length (length production-rhs)))
|
||||
(when (gethash production-name general-productions)
|
||||
@ -1301,16 +1351,17 @@
|
||||
(instantiate-general-grammar-symbol bound-argument-alist general-grammar-symbol))
|
||||
production-rhs)
|
||||
production-constraints
|
||||
production-name)
|
||||
production-name
|
||||
production-highlight)
|
||||
productions))))
|
||||
lhs-arguments)
|
||||
(when productions
|
||||
(setf (gethash production-name general-productions)
|
||||
(make-generic-production production-lhs production-rhs production-constraints production-name (nreverse productions)))))
|
||||
(make-generic-production production-lhs production-rhs production-constraints production-name production-highlight (nreverse productions)))))
|
||||
|
||||
(unless (nonterminal-excluded production-lhs)
|
||||
(setf (gethash production-name general-productions)
|
||||
(create-production production-lhs production-rhs production-constraints production-name)))))))
|
||||
(create-production production-lhs production-rhs production-constraints production-name production-highlight)))))))
|
||||
|
||||
|
||||
(when variant-generator
|
||||
@ -1384,7 +1435,8 @@
|
||||
:parameter-trees (make-hash-table :test *grammar-symbol-=*)
|
||||
:max-production-length max-production-length
|
||||
:general-productions general-productions
|
||||
:n-productions production-number)))
|
||||
:n-productions production-number
|
||||
:highlights highlights)))
|
||||
|
||||
;Compute the terminalsets in the terminal-terminalsets.
|
||||
(dotimes (n (length terminals))
|
||||
@ -1527,7 +1579,7 @@
|
||||
(depict-general-nonterminal markup-stream (gramar-user-start-symbol grammar) :reference))
|
||||
(dolist (nonterminal (grammar-nonterminals-list grammar))
|
||||
(unless (grammar-symbol-= nonterminal *start-nonterminal*)
|
||||
(depict-general-rule markup-stream (grammar-rule grammar nonterminal)))))
|
||||
(depict-general-rule markup-stream (grammar-rule grammar nonterminal) (grammar-highlights grammar)))))
|
||||
|
||||
|
||||
; Return a list of nontrivial sets of states with the same kernels.
|
||||
|
@ -450,6 +450,8 @@
|
||||
((:zeta 1) (:script "document.write(U_zeta)"))
|
||||
|
||||
;Block Styles
|
||||
(:js2 (div (class "js2")))
|
||||
(:es4 (div (class "es4")))
|
||||
(:body-text p)
|
||||
(:section-heading h2)
|
||||
(:subsection-heading h3)
|
||||
@ -509,9 +511,10 @@
|
||||
;;; HTML STREAMS
|
||||
|
||||
(defstruct (html-stream (:include markup-stream)
|
||||
(:constructor allocate-html-stream (env head tail level logical-position anchors))
|
||||
(:constructor allocate-html-stream (env head tail level logical-position enclosing-styles anchors))
|
||||
(:copier nil)
|
||||
(:predicate html-stream?))
|
||||
(enclosing-styles nil :type list :read-only t) ;A list of enclosing styles
|
||||
(anchors nil :type list :read-only t)) ;A mutable cons cell for accumulating anchors at the beginning of a paragraph
|
||||
; ;or nil if not inside a paragraph.
|
||||
|
||||
@ -522,9 +525,9 @@
|
||||
|
||||
|
||||
; Make a new, empty, open html-stream with the given definitions for its markup-env.
|
||||
(defun make-html-stream (markup-env level logical-position anchors)
|
||||
(defun make-html-stream (markup-env level logical-position enclosing-styles anchors)
|
||||
(let ((head (list nil)))
|
||||
(allocate-html-stream markup-env head head level logical-position anchors)))
|
||||
(allocate-html-stream markup-env head head level logical-position enclosing-styles anchors)))
|
||||
|
||||
|
||||
; Make a new, empty, open, top-level html-stream with the given definitions
|
||||
@ -533,7 +536,7 @@
|
||||
(let ((head (list nil))
|
||||
(markup-env (make-markup-env links)))
|
||||
(markup-env-define-alist markup-env html-definitions)
|
||||
(allocate-html-stream markup-env head head *markup-stream-top-level* nil nil)))
|
||||
(allocate-html-stream markup-env head head *markup-stream-top-level* nil nil nil)))
|
||||
|
||||
|
||||
; Return the approximate width of the html item; return t if it is a line break.
|
||||
@ -585,14 +588,23 @@
|
||||
|
||||
|
||||
|
||||
(defmethod depict-block-style-f ((html-stream html-stream) block-style emitter)
|
||||
(defmethod depict-block-style-f ((html-stream html-stream) block-style flatten emitter)
|
||||
(assert-true (<= (markup-stream-level html-stream) *markup-stream-paragraph-level*))
|
||||
(assert-true (and block-style (symbolp block-style)))
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream) *markup-stream-paragraph-level* nil nil)))
|
||||
(markup-stream-append1 inner-html-stream block-style)
|
||||
(prog1
|
||||
(funcall emitter inner-html-stream)
|
||||
(markup-stream-append1 html-stream (markup-stream-unexpanded-output inner-html-stream)))))
|
||||
(assert-true (symbolp block-style))
|
||||
(if (or (null block-style)
|
||||
(and flatten (member block-style (html-stream-enclosing-styles html-stream))))
|
||||
(funcall emitter html-stream)
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-paragraph-level*
|
||||
nil
|
||||
(cons block-style (html-stream-enclosing-styles html-stream))
|
||||
nil)))
|
||||
(markup-stream-append1 inner-html-stream block-style)
|
||||
(prog1
|
||||
(funcall emitter inner-html-stream)
|
||||
(let ((inner-output (markup-stream-unexpanded-output inner-html-stream)))
|
||||
(when (or (not flatten) (cdr inner-output))
|
||||
(markup-stream-append1 html-stream inner-output)))))))
|
||||
|
||||
|
||||
(defmethod depict-paragraph-f ((html-stream html-stream) paragraph-style emitter)
|
||||
@ -602,6 +614,7 @@
|
||||
(inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-content-level*
|
||||
(make-logical-position)
|
||||
(cons paragraph-style (html-stream-enclosing-styles html-stream))
|
||||
anchors)))
|
||||
(prog1
|
||||
(funcall emitter inner-html-stream)
|
||||
@ -616,6 +629,7 @@
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-content-level*
|
||||
(markup-stream-logical-position html-stream)
|
||||
(cons char-style (html-stream-enclosing-styles html-stream))
|
||||
(html-stream-anchors html-stream))))
|
||||
(markup-stream-append1 inner-html-stream char-style)
|
||||
(prog1
|
||||
@ -623,6 +637,11 @@
|
||||
(markup-stream-append1 html-stream (markup-stream-unexpanded-output inner-html-stream)))))
|
||||
|
||||
|
||||
(defmethod ensure-no-enclosing-style ((html-stream html-stream) style)
|
||||
(when (member style (html-stream-enclosing-styles html-stream))
|
||||
(cerror "Ignore" "Style ~S should not be in effect" style)))
|
||||
|
||||
|
||||
(defmethod depict-anchor ((html-stream html-stream) link-prefix link-name duplicate)
|
||||
(assert-true (= (markup-stream-level html-stream) *markup-stream-content-level*))
|
||||
(let* ((links (markup-env-links (html-stream-env html-stream)))
|
||||
@ -639,6 +658,7 @@
|
||||
(let ((inner-html-stream (make-html-stream (markup-stream-env html-stream)
|
||||
*markup-stream-content-level*
|
||||
(markup-stream-logical-position html-stream)
|
||||
(html-stream-enclosing-styles html-stream)
|
||||
(html-stream-anchors html-stream))))
|
||||
(markup-stream-append1 inner-html-stream (list 'a (list 'href href)))
|
||||
(prog1
|
||||
|
@ -383,7 +383,7 @@
|
||||
|
||||
; Return the charset of all characters that appear as terminals in grammar-source.
|
||||
(defun grammar-singletons (grammar-source)
|
||||
(assert-type grammar-source (list (tuple t (list t) identifier)))
|
||||
(assert-type grammar-source (list (tuple t (list t) identifier t)))
|
||||
(let ((singletons 0))
|
||||
(labels
|
||||
((scan-for-singletons (list)
|
||||
@ -648,7 +648,7 @@
|
||||
(char-charset partition-name)
|
||||
(partition-charset (gethash partition-name (lexer-partitions lexer)))))
|
||||
(production-name (intern (format nil "~A-~D" production-prefix (incf production-number)))))
|
||||
(push (list nonterminal-source (list partition-name) production-name) productions)
|
||||
(push (list nonterminal-source (list partition-name) production-name nil) productions)
|
||||
(dolist (action (charclass-actions charclass))
|
||||
(let* ((lexer-action (cdr action))
|
||||
(body (if (characterp partition-name)
|
||||
|
@ -337,14 +337,16 @@
|
||||
|
||||
; markup-stream must be a variable that names a markup-stream that is currently
|
||||
; accepting paragraphs. Execute body with markup-stream bound to a markup-stream
|
||||
; to which the body can emit contents. The given block-style is applied to all
|
||||
; to which the body can emit contents. If non-null, the given block-style is applied to all
|
||||
; paragraphs emitted by body (in the HTML emitter only; RTF has no block styles).
|
||||
; If flatten is true, do not emit the style if it is already in effect from a surrounding block
|
||||
; or if its contents are empty.
|
||||
; Return the result value of body.
|
||||
(defmacro depict-block-style ((markup-stream block-style) &body body)
|
||||
`(depict-block-style-f ,markup-stream ,block-style
|
||||
(defmacro depict-block-style ((markup-stream block-style &optional flatten) &body body)
|
||||
`(depict-block-style-f ,markup-stream ,block-style ,flatten
|
||||
#'(lambda (,markup-stream) ,@body)))
|
||||
|
||||
(defgeneric depict-block-style-f (markup-stream block-style emitter))
|
||||
(defgeneric depict-block-style-f (markup-stream block-style flatten emitter))
|
||||
|
||||
|
||||
; markup-stream must be a variable that names a markup-stream that is currently
|
||||
@ -371,6 +373,11 @@
|
||||
(defgeneric depict-char-style-f (markup-stream char-style emitter))
|
||||
|
||||
|
||||
; Ensure that the given style is not currently in effect in the markup-stream.
|
||||
; RTF streams don't currently keep track of styles, so this function does nothing for RTF streams.
|
||||
(defgeneric ensure-no-enclosing-style (markup-stream style))
|
||||
|
||||
|
||||
; Depict an anchor. The concatenation of link-prefix and link-name must be a string
|
||||
; suitable for an anchor name.
|
||||
; If duplicate is true, allow duplicate calls for the same link-name, in which case only
|
||||
|
@ -757,8 +757,8 @@
|
||||
(markup-env-expand (markup-stream-env rtf-stream) (markup-stream-unexpanded-output rtf-stream) nil))
|
||||
|
||||
|
||||
(defmethod depict-block-style-f ((rtf-stream rtf-stream) block-style emitter)
|
||||
(declare (ignore block-style))
|
||||
(defmethod depict-block-style-f ((rtf-stream rtf-stream) block-style flatten emitter)
|
||||
(declare (ignore block-style flatten))
|
||||
(assert-true (= (markup-stream-level rtf-stream) *markup-stream-paragraph-level*))
|
||||
(funcall emitter rtf-stream))
|
||||
|
||||
@ -790,6 +790,10 @@
|
||||
(rtf-stream-append-or-inline-block rtf-stream (markup-stream-unexpanded-output inner-rtf-stream)))))
|
||||
|
||||
|
||||
(defmethod ensure-no-enclosing-style ((rtf-stream rtf-stream) style)
|
||||
(declare (ignore style)))
|
||||
|
||||
|
||||
(defmethod depict-anchor ((rtf-stream rtf-stream) link-prefix link-name duplicate)
|
||||
(declare (ignore link-prefix link-name duplicate))
|
||||
(assert-true (= (markup-stream-level rtf-stream) *markup-stream-content-level*)))
|
||||
|
Loading…
x
Reference in New Issue
Block a user