Hi,
When I try to call PARSE-SCHEMA in ACL, I get this error --
attempt to call the undefined function (SETF CXML-RNG::GRAMMAR-START) with args: #S(CXML-RNG::DEFINITION :NAME :START :COMBINE-METHOD NIL :HEAD-P NIL :REDEFINITION NIL :CHILD ...) #S(CXML-RNG::GRAMMAR :START NIL :PARENT NIL :DEFINITIONS #<EQUAL hash-table with 0 entries @ #x13904c62>). [Condition of type UNDEFINED-FUNCTION]
This happens because GRAMMAR is defined after PARSE-SCHEMA in parse.lisp. Same issue with the DEFN-CHILD accessor for DEFINITION.
If I move the definition of PARSE-SCHEMA to the end of the file, for example, the issue is fixed.
Chaitanya
Another warning while compiling the package --
; While compiling (:INTERNAL MAKE-RNG-LEXER 0): Warning: RNG-ERROR should be given at least 2 arguments. It was given 1 argument. Problem detected when processing (RNG-ERROR "too many colons") inside (WHEN (FIND #: LNAME) (RNG-ERROR "too many colons")) inside (LET* ((POS #) (PREFIX #) (LNAME #)) (WHEN (FIND #: LNAME) (RNG-ERROR "too many colons")) ..)
The problem is in line 202 of compact.lisp.
Chaitanya
I have also attached a patch for this one. Looking at the way RNG-ERROR was called elsewhere in this file, I think this should be correct.
Also, the other problem needs to be fixed too...
Chaitanya Gupta wrote:
Another warning while compiling the package --
; While compiling (:INTERNAL MAKE-RNG-LEXER 0): Warning: RNG-ERROR should be given at least 2 arguments. It was given 1 argument. Problem detected when processing (RNG-ERROR "too many colons") inside (WHEN (FIND #: LNAME) (RNG-ERROR "too many colons")) inside (LET* ((POS #) (PREFIX #) (LNAME #)) (WHEN (FIND #: LNAME) (RNG-ERROR "too many colons")) ..)
The problem is in line 202 of compact.lisp.
Chaitanya
diff --git a/compact.lisp b/compact.lisp index 9dd4a40..c7f5557 100644 --- a/compact.lisp +++ b/compact.lisp @@ -199,7 +199,7 @@ (prefix (subseq cxml-clex:bag 0 pos)) (lname (subseq cxml-clex:bag (1+ pos )))) (when (find #: lname) - (rng-error "too many colons")) + (rng-error nil "too many colons")) (unless (and (nc-name-p prefix)) (rng-error nil "not an ncname: ~A" prefix)) (let ((ch (cxml-clex::getch)))
Quoting Chaitanya Gupta (mail@chaitanyagupta.com):
This happens because GRAMMAR is defined after PARSE-SCHEMA in parse.lisp. Same issue with the DEFN-CHILD accessor for DEFINITION.
Okay... Allegro uses defsetf instead of setf functions for the slots, which is legitimate. So that's a bug in cxml-rng. (And xuriella has the same problem.)
Do you have a patch for me that I can just apply?
Thanks, d.
David Lichteblau wrote:
Do you have a patch for me that I can just apply?
Attached output of git diff. Note that I just moved PARSE-SCHEMA towards the end of file. I am not sure whether it follows your style conventions.
Chaitanya
diff --git a/parse.lisp b/parse.lisp index 3bcc720..d6aa5dd 100644 --- a/parse.lisp +++ b/parse.lisp @@ -198,84 +198,6 @@ (klacks:make-tapping-source upstream handler)) upstream)))
-(defun parse-schema (input &key entity-resolver (process-dtd-compatibility t)) - "@arg[input]{a string, pathname, stream, or xstream} - @arg[entity-resolver]{a function of two arguments, or NIL} - @arg[process-dtd-compatibility]{a boolean} - @return{a parsed @class{schema}} - @short{This function parses a Relax NG schema file in XML syntax} - and returns a parsed representation of that schema. - - @code{input} can be any stream designator as understood by - @code{cxml:make-source}. - - Note that namestrings are not valid arguments, - because they would be interpreted as XML source code. Use pathnames - instead. - - @code{entity-resolver} can be passed as a function of two arguments. - It is invoked for every entity referenced by the - document with the entity's Public ID (a rod) and System ID (an - URI object) as arguments. The function may either return - nil, CXML will then try to resolve the entity as usual. - Alternatively it may return a Common Lisp stream specialized on - @code{(unsigned-byte 8)} which will be used instead. - - If @code{process-dtd-compatibility} is true, the schema will be checked - for @em{compatibility} with Relax NG DTD Compatibility, and default values - will be recorded. (Without @code{process-dtd-compatibility}, the schema - will not be checked @em{compatibility}, and annotations for - DTD Compatibility will be ignored like any other foreign element.) - - @see{parse-compact} - @see{make-validator}" - (when *validate-grammar* - (unless *relax-ng-grammar* - (let* ((*validate-grammar* nil) - (d (slot-value (asdf:find-system :cxml-rng) - 'asdf::relative-pathname))) - #+(or) (parse-compact (merge-pathnames "rng.rnc" d)) - (setf *relax-ng-grammar* - (parse-schema (merge-pathnames "rng.rng" d))) - (setf *compatibility-grammar* - (parse-schema (merge-pathnames "compatibility.rng" d)))))) - (let ((*process-dtd-compatibility* process-dtd-compatibility)) - (klacks:with-open-source (source (make-schema-source input)) - (invoke-with-klacks-handler - (lambda () - (klacks:find-event source :start-element) - (let* ((*datatype-library* "") - (*namespace-uri* "") - (*entity-resolver* entity-resolver) - (*external-href-stack* '()) - (*include-uri-stack* '()) - (*grammar* (make-grammar nil)) - (start (p/pattern source))) - (unless start - (rng-error nil "empty grammar")) - (setf (grammar-start *grammar*) - (make-definition :name :start :child start)) - (check-pattern-definitions source *grammar*) - (check-recursion start 0) - (multiple-value-bind (new-start defns) - (finalize-definitions start) - (setf start (fold-not-allowed new-start)) - (dolist (defn defns) - (setf (defn-child defn) (fold-not-allowed (defn-child defn)))) - (setf start (fold-empty start)) - (dolist (defn defns) - (setf (defn-child defn) (fold-empty (defn-child defn))))) - (multiple-value-bind (new-start defns) - (finalize-definitions start) - (check-start-restrictions new-start) - (dolist (defn defns) - (check-restrictions (defn-child defn))) - (let ((schema (make-schema new-start defns))) - (when *process-dtd-compatibility* - (check-schema-compatibility schema defns)) - schema)))) - source)))) -
;;;; pattern structures
@@ -2183,3 +2105,84 @@ (assert (null *in-element*)) (let ((*in-element* pattern)) (check-pattern-compatibility (pattern-child pattern)))) + + +;;; Parser + +(defun parse-schema (input &key entity-resolver (process-dtd-compatibility t)) + "@arg[input]{a string, pathname, stream, or xstream} + @arg[entity-resolver]{a function of two arguments, or NIL} + @arg[process-dtd-compatibility]{a boolean} + @return{a parsed @class{schema}} + @short{This function parses a Relax NG schema file in XML syntax} + and returns a parsed representation of that schema. + + @code{input} can be any stream designator as understood by + @code{cxml:make-source}. + + Note that namestrings are not valid arguments, + because they would be interpreted as XML source code. Use pathnames + instead. + + @code{entity-resolver} can be passed as a function of two arguments. + It is invoked for every entity referenced by the + document with the entity's Public ID (a rod) and System ID (an + URI object) as arguments. The function may either return + nil, CXML will then try to resolve the entity as usual. + Alternatively it may return a Common Lisp stream specialized on + @code{(unsigned-byte 8)} which will be used instead. + + If @code{process-dtd-compatibility} is true, the schema will be checked + for @em{compatibility} with Relax NG DTD Compatibility, and default values + will be recorded. (Without @code{process-dtd-compatibility}, the schema + will not be checked @em{compatibility}, and annotations for + DTD Compatibility will be ignored like any other foreign element.) + + @see{parse-compact} + @see{make-validator}" + (when *validate-grammar* + (unless *relax-ng-grammar* + (let* ((*validate-grammar* nil) + (d (slot-value (asdf:find-system :cxml-rng) + 'asdf::relative-pathname))) + #+(or) (parse-compact (merge-pathnames "rng.rnc" d)) + (setf *relax-ng-grammar* + (parse-schema (merge-pathnames "rng.rng" d))) + (setf *compatibility-grammar* + (parse-schema (merge-pathnames "compatibility.rng" d)))))) + (let ((*process-dtd-compatibility* process-dtd-compatibility)) + (klacks:with-open-source (source (make-schema-source input)) + (invoke-with-klacks-handler + (lambda () + (klacks:find-event source :start-element) + (let* ((*datatype-library* "") + (*namespace-uri* "") + (*entity-resolver* entity-resolver) + (*external-href-stack* '()) + (*include-uri-stack* '()) + (*grammar* (make-grammar nil)) + (start (p/pattern source))) + (unless start + (rng-error nil "empty grammar")) + (setf (grammar-start *grammar*) + (make-definition :name :start :child start)) + (check-pattern-definitions source *grammar*) + (check-recursion start 0) + (multiple-value-bind (new-start defns) + (finalize-definitions start) + (setf start (fold-not-allowed new-start)) + (dolist (defn defns) + (setf (defn-child defn) (fold-not-allowed (defn-child defn)))) + (setf start (fold-empty start)) + (dolist (defn defns) + (setf (defn-child defn) (fold-empty (defn-child defn))))) + (multiple-value-bind (new-start defns) + (finalize-definitions start) + (check-start-restrictions new-start) + (dolist (defn defns) + (check-restrictions (defn-child defn))) + (let ((schema (make-schema new-start defns))) + (when *process-dtd-compatibility* + (check-schema-compatibility schema defns)) + schema)))) + source))))