[lisp-snmp] Patch to asn.1 to change from parsergen to a modified cl-yacc
Brought to you by:
binghe
From: John F. <jf...@ms...> - 2009-02-06 10:26:29
|
And if anybody is interested in converting from parsergen syntax to cl-yacc syntax, here are some helper functions (defun defparser-production-to-yacc (grammar-symbols forms) (cond ((not (and forms (or (not (listp forms)) (some 'identity forms)))) nil) (t (labels ((make-var (i) (intern (format nil "$~D" i))) (vars () (loop for i from 1 for x in grammar-symbols collect (make-var i))) (used-vars () (remove-duplicates (loop for sym in (alexandria:flatten forms) when (and (symbolp sym) (eql #\$ (elt (symbol-name sym) 0)) (ignore-errors (parse-integer (symbol-name sym) :start 1))) collect (make-var (parse-integer (symbol-name sym) :start 1))) :test 'eql))) (let ((unused-vars (set-difference (vars) (used-vars)))) (list `#'(lambda(,@(vars)) ,@(when unused-vars (list `(declare (ignore ,@unused-vars)))) ,forms))))))) (defun defparser-to-yacc (rules) (let (grouped-rules) (loop for rule in rules do (destructuring-bind ((non-terminal &rest grammar-symbols) &optional forms) rule (assert non-terminal) (push (append grammar-symbols (defparser-production-to-yacc grammar-symbols forms)) (sys:cdr-assoc non-terminal grouped-rules)))) (loop for (name . alternatives) in (nreverse grouped-rules) collect `(,name ,@(reverse alternatives))))) |