From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.devel Subject: Re: asking for advice for changing the cfengine.el progmode to support CFEngine 3.x Date: Tue, 21 Jun 2011 10:59:55 -0400 Message-ID: References: <87mxhgl44t.fsf@lifelogs.com> <87r56oz146.fsf@lifelogs.com> NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: dough.gmane.org 1308668673 19292 80.91.229.12 (21 Jun 2011 15:04:33 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Tue, 21 Jun 2011 15:04:33 +0000 (UTC) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Jun 21 17:04:29 2011 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([140.186.70.17]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1QZ2VA-0004W7-7E for ged-emacs-devel@m.gmane.org; Tue, 21 Jun 2011 17:04:28 +0200 Original-Received: from localhost ([::1]:42229 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZ2V9-000747-Fr for ged-emacs-devel@m.gmane.org; Tue, 21 Jun 2011 11:04:27 -0400 Original-Received: from eggs.gnu.org ([140.186.70.92]:39869) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZ2RR-0006B5-1W for emacs-devel@gnu.org; Tue, 21 Jun 2011 11:01:03 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QZ2RK-0001Tl-AO for emacs-devel@gnu.org; Tue, 21 Jun 2011 11:00:36 -0400 Original-Received: from ironport2-out.teksavvy.com ([206.248.154.181]:52447 helo=ironport2-out.pppoe.ca) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZ2RK-0001Td-2b for emacs-devel@gnu.org; Tue, 21 Jun 2011 11:00:30 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Av0EAOCwAE5FxL0s/2dsb2JhbABUpnB4iHPABoYqBJ1khCQ X-IronPort-AV: E=Sophos;i="4.65,401,1304308800"; d="scan'208";a="116776561" Original-Received: from 69-196-189-44.dsl.teksavvy.com (HELO ceviche.home) ([69.196.189.44]) by ironport2-out.pppoe.ca with ESMTP/TLS/ADH-AES256-SHA; 21 Jun 2011 11:00:25 -0400 Original-Received: by ceviche.home (Postfix, from userid 20848) id 24DD2660F1; Tue, 21 Jun 2011 11:59:55 -0300 (ART) In-Reply-To: <87r56oz146.fsf@lifelogs.com> (Ted Zlatanov's message of "Mon, 20 Jun 2011 15:42:01 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 206.248.154.181 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:140780 Archived-At: > SMIE is very new so I am concerned that relying on it will block Emacs > users that haven't upgraded. It's in Emacs-23.3. > Can it be distributed with my library? It's Free Software, so of course you can. > It's also fairly hard to specify an operator precedence grammar for > CFEngine using SMIE. OPG are very limited, indeed, so they're difficult to use for most languages. > I tried it and ended up uncertain how to debug the parse tree of the > current buffer or where my grammar's error lay. The patch below will at least give you better feedback for the immediate problem in your grammar. > See below. Perhaps I'm just too accustomed to LALR parsers, but they > seem easier and less ambiguous. Very likely. With SMIE you shouldn't try to parse the language in an exact manner, but think about parsing the minimum needed to indent properly ;-) Here are some concrete comments that I hope will help you. > (defconst cfengine3-smie-bnf-table > '((classname) > (class_condition (class_condition "&&" class_condition) > (class_condition "||" class_condition) > (class_condition "." class_condition) > ("!" class_condition) > (classname)) > (bundle_parameters (bundle_parameters "," bundle_parameters) > (function_parameter)) Looks fine. > (bundle_name (bundle) > (bundle bundle_parameters)) The second line above is outside the scope of OPG: you can't have adjacent non-terminals in your grammar. > (bundle_line ("bundle" bundle_type bundle_name)) Same here. Looking at your example, I would recommend you treat "bundle" as an associative separator, as in (bundles (bundles "bundle" bundles)) This will surely strike you as really wrong, but OPG don't handle "terminator" tokens or "start" tokens nearly as well as separator tokens. > (promises (promise ";" promise) (promise)) > (bundle_section (section ":" "\n" promises) > (class_condition "::" "\n" promises)) Adjacent terminals are allowed in OPG, but they tend to work somewhat poorly, so I'd recommend to try and avoid them. > (bundle_body (bundle_section) (bundle_section "\n" bundle_section)) I'm surprised to see \n here (and in the previous rule). Are newlines really significant in cfengine's syntax? > (bundle_block (bundle_line "{" bundle_body "}")))) Better leave {...} as an expression of its own, so that { is an opener and } is a closer. I.e. let "bundle" be followed by a sequence of . That means that bundle edit_line block_append_if_no_line(data) { insert_lines: any:: "$(data)" insert_type => "preserve_block"; } will be parsed as "bundle" followed by 4 (one of them being "(data)"), which is structurally incorrect (IIUC "(data)" is actually structurally a child of "block_append_if_no_line" rather than of "bundle"), but we can hope that it won't matter for indentation. > (defvar cfengine3-smie-grammar > (smie-prec2->grammar > (smie-merge-prec2s > (smie-bnf->prec2 cfengine3-smie-bnf-table > '((assoc "\n" ";"))) > (smie-precs->prec2 cfengine3-operator-table)))) You actually want to pass cfengine3-operator-table to smie-bnf->prec2 (as second parameter) because it's needed to disambiguate the BNF grammar. Stefan === modified file 'lisp/emacs-lisp/smie.el' --- lisp/emacs-lisp/smie.el 2011-06-17 01:46:30 +0000 +++ lisp/emacs-lisp/smie.el 2011-06-21 14:35:41 +0000 @@ -265,14 +265,18 @@ ;; the trouble, and it lets the writer of the BNF ;; be a bit more sloppy by skipping uninteresting base ;; cases which are terminals but not OPs. - (assert (not (member (cadr rhs) nts))) + (when (member (cadr rhs) nts) + (error "Adjacent non-terminals: %s %s" + (car rhs) (cadr rhs))) (pushnew (cadr rhs) first-ops))) (let ((shr (reverse rhs))) (if (not (member (car shr) nts)) (pushnew (car shr) last-ops) (pushnew (car shr) last-nts) (when (consp (cdr shr)) - (assert (not (member (cadr shr) nts))) + (when (member (cadr rhs) nts) + (error "Adjacent non-terminals: %s %s" + (cadr rhs) (car rhs))) (pushnew (cadr shr) last-ops))))) (push (cons nt first-ops) first-ops-table) (push (cons nt last-ops) last-ops-table)