;;; semantic-grammar.wy -- LALR grammar of Semantic input grammars ;; ;; Copyright (C) 2002, 2003, 2004 David Ponce ;; ;; Author: David Ponce ;; Maintainer: David Ponce ;; Created: 26 Aug 2002 ;; Keywords: syntax ;; X-RCS: $Id: semantic-grammar.wy,v 1.16 2005/09/30 20:20:27 zappo Exp $ ;; ;; This file is not part of GNU Emacs. ;; ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License as ;; published by the Free Software Foundation; either version 2, or (at ;; your option) any later version. ;; ;; This software is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;; General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to the ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. %{ ;; Current parsed nonterminal name. (defvar semantic-grammar-wy--nterm nil) ;; Index of rule in a nonterminal clause. (defvar semantic-grammar-wy--rindx nil) } ;;%package semantic-grammar-wy %languagemode wy-mode ;; Main %start grammar ;; Reparse %start prologue epilogue declaration nonterminal rule ;; EXPANDFULL %start put_names put_values use_names ;; Keywords %type %keyword DEFAULT-PREC "%default-prec" %keyword NO-DEFAULT-PREC "%no-default-prec" %keyword KEYWORD "%keyword" %keyword LANGUAGEMODE "%languagemode" %keyword LEFT "%left" %keyword NONASSOC "%nonassoc" %keyword PACKAGE "%package" %keyword PREC "%prec" %keyword PUT "%put" %keyword QUOTEMODE "%quotemode" %keyword RIGHT "%right" %keyword SCOPESTART "%scopestart" %keyword START "%start" %keyword TOKEN "%token" %keyword TYPE "%type" %keyword USE-MACROS "%use-macros" ;; Literals %type %token STRING %type syntax ":?\\(\\sw\\|\\s_\\)+" %token SYMBOL %token PERCENT_PERCENT "\\`%%\\'" %type syntax semantic-grammar-lex-c-char-re %token CHARACTER %type matchdatatype sexp syntax "\\s'\\s-*(" %token PREFIXED_LIST %type matchdatatype sexp syntax "\\=" %token SEXP ;; Don't generate these analyzers which needs special handling code. %token PROLOGUE "%{...%}" %token EPILOGUE "%%...EOF" ;; Blocks & Parenthesis %type %token PAREN_BLOCK "(LPAREN RPAREN)" %token BRACE_BLOCK "(LBRACE RBRACE)" %token LPAREN "(" %token RPAREN ")" %token LBRACE "{" %token RBRACE "}" ;; Punctuations %type %token COLON ":" %token SEMI ";" %token OR "|" %token LT "<" %token GT ">" %% grammar: prologue | epilogue | declaration | nonterminal | PERCENT_PERCENT ; ;;; Prologue/Epilogue ;; prologue: PROLOGUE (CODE-TAG "prologue" nil) ; epilogue: EPILOGUE (CODE-TAG "epilogue" nil) ; ;;; Declarations ;; declaration: decl (eval $1) ; decl: default_prec_decl | no_default_prec_decl | languagemode_decl | package_decl | precedence_decl | put_decl | quotemode_decl | scopestart_decl | start_decl | keyword_decl | token_decl | type_decl | use_macros_decl ; default_prec_decl: DEFAULT-PREC `(TAG "default-prec" 'assoc :value '("t")) ; no_default_prec_decl: NO-DEFAULT-PREC `(TAG "default-prec" 'assoc :value '("nil")) ; languagemode_decl: LANGUAGEMODE symbols `(TAG ',(car $2) 'languagemode :rest ',(cdr $2)) ; package_decl: PACKAGE SYMBOL `(PACKAGE-TAG ',$2 nil) ; precedence_decl: associativity token_type_opt items `(TAG ',$1 'assoc :type ',$2 :value ',$3) ; associativity: LEFT (progn "left") | RIGHT (progn "right") | NONASSOC (progn "nonassoc") ; put_decl: PUT put_name put_value `(TAG ',$2 'put :value ',(list $3)) | PUT put_name put_value_list `(TAG ',$2 'put :value ',$3) | PUT put_name_list put_value `(TAG ',(car $2) 'put :rest ',(cdr $2) :value ',(list $3)) | PUT put_name_list put_value_list `(TAG ',(car $2) 'put :rest ',(cdr $2) :value ',$3) ; put_name_list: BRACE_BLOCK (mapcar 'semantic-tag-name (EXPANDFULL $1 put_names)) ; put_names: LBRACE () | RBRACE () | put_name ;; Must return a list of Semantic tags to EXPANDFULL! (TAG $1 'put-name) ; put_name: SYMBOL | token_type ; put_value_list: BRACE_BLOCK (mapcar 'semantic-tag-code-detail (EXPANDFULL $1 put_values)) ; put_values: LBRACE () | RBRACE () | put_value ;; Must return a list of Semantic tags to EXPANDFULL! (CODE-TAG "put-value" $1) ; put_value: SYMBOL any_value (cons $1 $2) ; scopestart_decl: SCOPESTART SYMBOL `(TAG ',$2 'scopestart) ; quotemode_decl: QUOTEMODE SYMBOL `(TAG ',$2 'quotemode) ; start_decl: START symbols `(TAG ',(car $2) 'start :rest ',(cdr $2)) ; keyword_decl: KEYWORD SYMBOL string_value `(TAG ',$2 'keyword :value ',$3) ; token_decl: TOKEN token_type_opt SYMBOL string_value `(TAG ',$3 ',(if $2 'token 'keyword) :type ',$2 :value ',$4) | TOKEN token_type_opt symbols `(TAG ',(car $3) 'token :type ',$2 :rest ',(cdr $3)) ; token_type_opt: ;; EMPTY | token_type ; token_type: LT SYMBOL GT (progn $2) ; type_decl: TYPE token_type plist_opt `(TAG ',$2 'type :value ',$3) ; plist_opt: ;;EMPTY | plist ; plist: plist put_value (append (list $2) $1) | put_value (list $1) ; use_name_list: BRACE_BLOCK (mapcar 'semantic-tag-name (EXPANDFULL $1 use_names)) ; use_names: LBRACE () | RBRACE () | SYMBOL ;; Must return a list of Semantic tags to EXPANDFULL! (TAG $1 'use-name) ; use_macros_decl: USE-MACROS SYMBOL use_name_list `(TAG "macro" 'macro :type ',$2 :value ',$3) ; string_value: STRING (read $1) ; ;; Return a Lisp readable form any_value: SYMBOL | STRING | PAREN_BLOCK | PREFIXED_LIST | SEXP ; symbols: lifo_symbols (nreverse $1) ; lifo_symbols: lifo_symbols SYMBOL (cons $2 $1) | SYMBOL (list $1) ; ;;; Grammar rules ;; nonterminal: SYMBOL (setq semantic-grammar-wy--nterm $1 semantic-grammar-wy--rindx 0) COLON rules SEMI (TAG $1 'nonterminal :children $4) ; rules: lifo_rules (apply 'nconc (nreverse $1)) ; lifo_rules: lifo_rules OR rule (cons $3 $1) | rule (list $1) ; rule: rhs (let* ((nterm semantic-grammar-wy--nterm) (rindx semantic-grammar-wy--rindx) (rhs $1) comps prec action elt) (setq semantic-grammar-wy--rindx (1+ semantic-grammar-wy--rindx)) (while rhs (setq elt (car rhs) rhs (cdr rhs)) (cond ;; precedence level ((vectorp elt) (if prec (error "duplicate %%prec in `%s:%d' rule" nterm rindx)) (setq prec (aref elt 0))) ;; action ((consp elt) ;; don't forget that rhs items are in reverse order, so ;; the end-of-rule semantic action is the first item. (if (or action comps) ;; a mid-rule action (setq comps (cons elt comps) ;; keep rule and action index synchronized semantic-grammar-wy--rindx (1+ semantic-grammar-wy--rindx)) ;; the end-of-rule action (setq action (car elt)))) ;; item (t (setq comps (cons elt comps))))) (EXPANDTAG (TAG (format "%s:%d" nterm rindx) 'rule :type (if comps "group" "empty") :value comps :prec prec :expr action))) ; rhs: ;; EMPTY | rhs item (cons $2 $1) | rhs action (cons (list $2) $1) | rhs PREC item (cons (vector $3) $1) ; action: PAREN_BLOCK | PREFIXED_LIST | BRACE_BLOCK (format "(progn\n%s)" (let ((s $1)) (if (string-match "^{[\r\n\t ]*" s) (setq s (substring s (match-end 0)))) (if (string-match "[\r\n\t ]*}$" s) (setq s (substring s 0 (match-beginning 0)))) s)) ; items: lifo_items (nreverse $1) ; lifo_items: lifo_items item (cons $2 $1) | item (list $1) ; item: SYMBOL | CHARACTER ; %% (define-lex semantic-grammar-lexer "Lexical analyzer that handles Semantic grammar buffers. It ignores whitespaces, newlines and comments." semantic-lex-ignore-newline semantic-lex-ignore-whitespace ;; Must detect prologue/epilogue before other symbols/keywords! semantic-grammar-lex-prologue semantic-grammar-lex-epilogue semantic-grammar-wy---keyword-analyzer semantic-grammar-wy---regexp-analyzer semantic-grammar-wy---regexp-analyzer semantic-grammar-wy---sexp-analyzer ;; Must detect comments after strings because `comment-start-skip' ;; regexp match semicolons inside strings! semantic-lex-ignore-comments ;; Must detect prefixed list before punctuation because prefix chars ;; are also punctuations! semantic-grammar-wy---sexp-analyzer ;; Must detect punctuations after comments because the semicolon can ;; be a punctuation or a comment start! semantic-grammar-wy---string-analyzer semantic-grammar-wy---block-analyzer semantic-grammar-wy---sexp-analyzer ) ;;; semantic-grammar.wy ends here