Anonymous avatar Anonymous committed d7c5549

semantic 1.4

Comments (0)

Files changed (30)

+2002-08-05  Andy Piper  <andy@xemacs.org>
+
+	* update to semantic 1.4.
+
 2002-07-16  Adrian Aichner  <adrian@xemacs.org>
 
 	* .cvsignore: Add generated .info* and .html files.
 # Boston, MA 02111-1307, USA.
 
 VERSION = 1.12
-AUTHOR_VERSION = 1.4beta8
+AUTHOR_VERSION = 1.4
 MAINTAINER = Eric M. Ludlam <zappo@gnu.org>
 PACKAGE = semantic
 PKG_TYPE = regular
-REQUIRES = eieio xemacs-base xemacs-devel edit-utils speedbar texinfo
+REQUIRES = eieio xemacs-base xemacs-devel edit-utils speedbar texinfo \
+	fsf-compat cc-mode
 CATEGORY = standard
 
 ELCS = document-vars.elc document.elc semantic-bnf.elc semantic-c.elc \
 	semantic-ctxt.elc semantic-el.elc semantic-imenu.elc semantic-make.elc \
 	semantic-sb.elc semantic-util.elc semantic.elc sformat.elc working.elc \
 	senator.elc semantic-java.elc semantic-scm.elc semanticdb.elc \
-	semantic-load.elc senator-isearch.elc semantic-texi.elc
+	semantic-load.elc senator-isearch.elc semantic-util-modes.elc \
+	semantic-texi.elc semantic-cb.elc semantic-ia-sb.elc semantic-ia.elc \
+	semantic-analyze.elc
+
 EXTRA_SOURCES = semantic-util.el
 
 INFO_FILES = $(PACKAGE).info*
-# C & C++ BNF language specification
+# C/C++ BNF language specification
 #
-# Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
+# Copyright (C) 1999, 2000, 2001, 2002 Eric M. Ludlam
 #
 # Author: Eric M. Ludlam <zappo@gnu.org>
 # X-RCS: $Id$
 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 # Boston, MA 02111-1307, USA.
 #
-# $Log$
-# Revision 1.37  2001/06/03 14:01:13  zappo
-# Multi-inheritance for classes.
-# Structs like classes for C++.
-# No ; on name spaces.
-# Throws for methods.
-# (Bugs & patches from "Jesper Nordenberg" <mayhem@home.se>
-# and Norbert Lindlbauer <Norbert_Lindlbauer@betaresearch.de>)
-#
-# Revision 1.36  2001/05/25 01:12:10  zappo
-# (expression): Added string.
-#
-# Revision 1.35  2001/05/09 03:25:17  zappo
-# Added inline method support.
-# Store protection elements
-# Change enum parts to be integer variables.
-#
-# Revision 1.34  2001/05/01 16:52:40  zappo
-# Revamped lots of summary strings.
-# Added `type' as a possible expansion in classsubparts.
-#
-# Revision 1.33  2001/04/21 14:37:55  zappo
-# Spelling error for integer.
-#
-# Revision 1.32  2001/04/13 02:24:45  zappo
-# Added built in types (void, char, etc) and summaries.
-#
-# Revision 1.31  2001/04/07 02:43:48  zappo
-# Added name spaces, and references.
-#
-# Revision 1.30  2001/03/10 16:18:15  zappo
-# Added lots of summaries to %tokens.
-# variables and functions now share declmod and typedecl start
-# match, and then get recombobulated later.  Prevents massive
-# reparsing.
-#
-# Revision 1.29  2001/02/24 15:24:24  zappo
-# Added a few optimizations for structure parts.
-# Used some %tokens in a few spots where I wasn't using them before.
-#
-# Revision 1.28  2001/02/20 20:36:19  zappo
-# Removed unused %put calls.
-#
-# Revision 1.27  2001/02/09 19:49:26  zappo
-# Added paren testing to argument lists.
-#
-# Revision 1.26  2001/02/09 11:47:32  zappo
-# Added type separation characters.
-# Added all constituents of DECLMOD into their own tokens.
-# Created a rule to create a list of declmods.
-#
-# Revision 1.25  2001/02/02 04:14:53  zappo
-# Added c++ to the list of language modes.
-# Added lots of operator symbol tokens.
-# Added DECLMOD symbol w/ complex regexp.
-# Added CLASS, OPERATOR, PUBLIC, PRIVATE, and PROTECTED token keywords.
-# Support parsing of a class.
-# Add class bit parsing for functions.
-# Add destructor bit parsing for functions.
-# Allow operator symbols for methods.
-# Added parent and destructor fields to extra-spec for functions.
-# The function rule now returns a function or prototype.
-#
-# Revision 1.24  2001/01/31 15:26:10  zappo
-# Added `codeblock' rule and `%scopestart'.
-#
-# Revision 1.23  2001/01/24 21:08:41  zappo
-# Added support for new token formats that use ASSOC.
-#
-# Revision 1.22  2001/01/06 14:35:40  zappo
-# Put `type' `t' onto some tokens.
-# Struct and enums now match the braces, and return nil.
-# Enum parts now have a token type of 'enum.
-# Added ... to fuction arg lists.
-# Match parens for arg lists.
-#
-# [...]
-#
-# Revision 1.1  1999/05/17 17:28:30  zappo
-# Initial revision
-#
 
 %start         declaration
 %scopestart    codeblock
 %(setq semantic-expand-nonterminal 'semantic-expand-c-nonterminal
        semantic-flex-extensions semantic-flex-c-extensions
        semantic-dependency-include-path semantic-default-c-path
+       semantic-orphaned-member-metaparent-type "struct"
+       semantic-symbol->name-assoc-list
+        '((type     . "Types")
+	  (variable . "Variables")
+	  (function . "Functions")
+	  (include  . "Includes"))
+       semantic-symbol->name-assoc-list-for-type-parts
+        '((type     . "Types")
+	  (variable . "Attributes")
+	  (function . "Methods")
+	  (label    . "Labels")
+	  )
        imenu-create-index-function 'semantic-create-imenu-index
        semantic-type-relation-separator-character '("." "->")
        semantic-command-separation-character ";"
        document-comment-start "/*"
        document-comment-line-prefix " *"
        document-comment-end " */"
+       ;; Semantic navigation inside 'type children
+       senator-step-at-token-ids '(function variable)
        )%
 
 %token INCLUDE "include"
 %put CONST summary "Declaration Modifier: const <type> <name> ..."
 %token VOLATILE "volatile"
 %put VOLATILE summary "Declaration Modifier: volatile <type> <name> ..."
+%token REGISTER "register"
+%put REGISTER summary "Declaration Modifier: register <type> <name> ..."
 %token SIGNED "signed"
 %put SIGNED summary "Numeric Type Modifier: signed <numeric type> <name> ..."
 %token UNSIGNED "unsigned"
 %put UNSIGNED summary "Numeric Type Modifier: unsigned <numeric type> <name> ..."
 
 %token INLINE "inline"
-%put INLINE "Function Modifier: inline <return  type> <name>(...) {...};"
+%put INLINE summary "Function Modifier: inline <return  type> <name>(...) {...};"
 %token VIRTUAL "virtual"
 %put VIRTUAL summary "Method Modifier: virtual <type> <name>(...) ..."
+%token MUTABLE "mutable"
+%put MUTABLE summary "Member Declaration Modifier: mutable <type> <name> ..."
 
 %token STRUCT "struct"
 %put STRUCT summary "Structure Type Declaration: struct [name] { ... };"
 %put CLASS summary "Class Declaration: class <name>[:parents] { ... };"
 %token NAMESPACE "namespace"
 %put NAMESPACE summary "Namespace Declaration: namespace <name> { ... };"
+%token USING "using"
+%put USING summary "using <namespace>;"
+
+# Despite this, this parser can find templates by ignoring the TEMPLATE
+# keyword, and finding the class/method being templateized.
+%token TEMPLATE "template"
+%put TEMPLATE summary "template <class TYPE ...> TYPE_OR_FUNCTION"
 
 %token THROW "throw"
 %put THROW summary "<type> <methoddef> (<method args>) throw (<exception>) ..."
+%token REENTRANT "reentrant"
+%put REENTRANT summary "<type> <methoddef> (<method args>) reentrant ..."
 
 # Leave these alone for now.
 %token OPERATOR "operator"
 %token PUBLIC "public"
 %token PRIVATE "private"
 %token PROTECTED "protected"
-
+%token FRIEND "friend"
 
 # These aren't used for parsing, but is a useful place to describe the keywords.
 %token IF "if"
 %token DOUBLE "double"
 %put DOUBLE summary "Primitive floating-point type (double-precision 64-bit IEEE 754)"
 
+%token UNDERP "_P"
+%token UNDERUNDERP "__P"
+%put UNDERP summary "Common macro to eliminate prototype compatibility on some compilers"
+%put UNDERUNDERP summary "Common macro to eliminate prototype compatibility on some compilers"
+
 declaration : macro
 	    | type
 	    | var-or-fun
 	    | define
+	    | extern-c
+	    | template
+	    | using
 	    ;
 
 codeblock : define
-	  | var-or-fun
+	  | codeblock-var-or-fun
 	  | type # type is less likely to be used here.
 	  ;
 
+extern-c-contents: open-paren
+		   ( nil )
+		 | bovine-toplevel
+		 | close-paren
+		   ( nil )
+		 ;
+
+extern-c: EXTERN string "\"C\"" semantic-list
+	# Extern C commands which contain a list need to have the
+	# entries of the list extracted, and spliced into the main
+	# list of entries.  This must be done via the function
+	# that expands singular nonterminals, such as int x,y;
+	  ( extern (EXPANDFULL $3 extern-c-contents) )
+	| EXTERN string "\"C\""
+	# A plain extern "C" call should add something to the token,
+	# but just strip it from the buffer here for now.
+	  ( nil )
+	;
+
 macro : HASH macro-or-include
 	( ,$2 )
       ;
 
-macro-or-include : DEFINE symbol opt-expression
+macro-or-include : DEFINE symbol opt-define-arglist opt-expression
 		   ( $2 variable nil $3
 			(ASSOC const t)
 			nil
 			)
-		 | INCLUDE LESS filename GREATER
-		   ( ,$3 include t nil )
+		 | INCLUDE system-include
+		   ( (substring $2 1 (1- (length $2)))  include t nil )
 		 | INCLUDE string
 		   ( (read $2) include nil nil )
 		 ;
 
+opt-define-arglist : semantic-list
+		     ( nil )
+		   | EMPTY
+		   ;
+
 # This is used in struct parts.
 define : HASH DEFINE symbol opt-expression
 	 ( $2 variable nil $3
 	      )
        ;
 
-filename : symbol PERIOD symbol
-	   ( (concat $1 $2 $3) )
-         | symbol DIVIDE filename
-	   ( (concat $1 $2 (car $3)) )
-	 ;
-
 # In C++, structures can have the same things as classes.
 # So delete this somday in the figure.
 #
 #	       # sometimes there are defines in structs.
 #	       ;
 
-classparts : semantic-list
+unionparts : semantic-list
 	     (EXPANDFULL $1 classsubparts)
-	    ;
+	   ;
+
+opt-symbol : symbol
+	   | EMPTY
+	   ;
 
 classsubparts : open-paren "{"
 		( nil )
 	      | close-paren "}"
 		( nil )
-	      | opt-class-protection COLON
+	      | class-protection opt-symbol COLON
+	      # For QT, they may put a `slot' keyword between the protection
+	      # and the COLON.
 		( ,$1 label )
 	      | var-or-fun
 	      | type
 	      | define	      
 		( ,$1 protection )
-	      # In C++, this label in a classsubpart represents
-	      # PUBLIC or PRIVATE bits.  Ignore them for now.
+	      | template
 	      | EMPTY
 	      ;
 
-opt-class-parents : COLON class-parents
+opt-class-parents : COLON class-parents opt-template-specifier
 		    ( $2 )
 		  | EMPTY
 		    ( )
 		  ;
 
-class-parents : opt-class-protection symbol COMA class-parents
-		( ,(cons $2 $4 ) )
-	      | opt-class-protection symbol
-		( $2 )
+class-parents : opt-class-protection opt-class-declmods
+		symbol COMA class-parents
+		( ,(cons $3 $5 ) )
+	      | opt-class-protection opt-class-declmods symbol
+		( $3 )
 	      ;
 
-opt-class-protection : PUBLIC
-		     | PRIVATE
-		     | PROTECTED
+opt-class-declmods : class-declmods opt-class-declmods
+		     ( nil )
+		   | EMPTY
+		   ;
+
+class-declmods : VIRTUAL
+	       ;
+
+class-protection: PUBLIC
+		| PRIVATE
+		| PROTECTED
+		;
+
+opt-class-protection : class-protection
+		       ( ,$1 )
+		     | EMPTY
 		     ;
 
 namespaceparts : semantic-list
 		  | type
                   | var-or-fun
 		  | define
-		  | opt-class-protection COLON
+		  | class-protection COLON
 		    ( $1 protection )
 		  # In C++, this label in a classsubpart represents
 		  # PUBLIC or PRIVATE bits.  Ignore them for now.
+		  | template
+		  | using
 		  | EMPTY
 		  ;
 
 	       ( nil )
 	     | close-paren "}"
 	       ( nil )
+	     | COMA
+	       ( nil )
 	     ;
 
 opt-name : symbol
 	 | EMPTY
-	   ( nil )
+	   ( "" )
          ;
 
-typesimple : struct-or-class opt-name opt-class-parents classparts
-	     ( ,$2 type ,$1 $4 ,$3 nil nil )
-	   | UNION opt-name structparts
+typesimple : struct-or-class opt-name opt-template-specifier
+	     opt-class-parents semantic-list
+	     ( ,$2 type ,$1 
+		   (let ((semantic-c-classname (cons (car ,$2) (car ,$1))))
+		       (EXPANDFULL $5 classsubparts))
+		   $4
+		   (ASSOC 'template-specifier $3)
+		   nil )
+	   | struct-or-class opt-name opt-template-specifier opt-class-parents
+	     ( ,$2 type ,$1 nil $4 
+		   (ASSOC 'template-specifier $3)
+		    nil )
+	   | UNION opt-name unionparts
 	     ( ,$2 type $1 $3 nil nil nil )
 	   | ENUM opt-name enumparts
 	     ( ,$2 type $1 $3 nil nil nil )	
-           | TYPEDEF typeform symbol
+           | TYPEDEF typeformbase typedef-symbol-list
+	   ## We put the type this typedef renames into PARENT
+	   ## but will move it in the expand function.
 	     ( $3 type $1 nil $2 nil nil )
            ;
 
+typedef-symbol-list : typedefname COMA typedef-symbol-list
+		      ( ,(cons $1 $3) )
+		    | typedefname
+		      ( $1 )
+		    ;
+
+typedefname : opt-stars symbol opt-bits opt-array
+	      ( $1 $2 )
+	    ;
+
 struct-or-class: STRUCT
 	       | CLASS
 	       ;
        ( $2 type $1 $3 nil nil nil )
      ;
 
-opt-stars : STAR opt-stars
-	    ( (1+ (car $2)) )
+# Using is vaguely like an include statement in the named portions
+# of the code.  We should probably specify a new token type for this.
+using : USING typeformbase SEMICOLON
+	( nil )
+      | USING symbol COLON COLONG typeformbase SEMICOLON;
+      ;
+
+template : TEMPLATE template-specifier opt-friend template-definition
+	   ( ,(semantic-c-reconstitute-template $4 ,$2) )
+	 ;
+
+opt-friend : FRIEND
+	   | EMPTY
+	   ;
+
+opt-template-specifier : template-specifier
+			 ( ,$1 )
+		       | EMPTY
+			 ()
+		       ;
+
+template-specifier : LESS template-specifier-types GREATER
+		     ( ,$2 )
+		   ;
+
+template-specifier-types : template-var template-specifier-type-list
+			   ( ,(cons ,$1 ,$2 ) )
+			 | EMPTY
+			 ;
+
+template-specifier-type-list : COMA template-specifier-types
+			       ( ,$2 )
+			     | EMPTY
+			       ( )
+			     ;
+
+template-var : template-type opt-stars opt-template-equal
+	       ( ,(cons (concat (car $1) (make-string (car ,$2) ?*))
+			      (cdr $1)))
+	     ;
+
+opt-template-equal : EQUAL symbol LESS template-specifier-types GREATER
+		     ( $2 )
+		   | EMPTY
+		   ;
+
+template-type : CLASS symbol
+		( $2 type "class" nil nil)
+	      | STRUCT symbol
+		( $2 type "struct" nil nil)
+	      | builtintype
+		( ,$1 type nil nil nil)
+	      | symbol
+		( $1 type nil nil nil)
+	      ;
+
+template-definition : type
+		      ( ,$1 )
+		    | var-or-fun
+		      ( ,$1 )
+		    ;
+
+opt-stars :  STAR opt-starmod opt-stars
+	    ( (1+ (car $3)) )
 	  | EMPTY
 	    ( 0 )
           ;
 
+opt-starmod : STARMOD opt-starmod
+	      ( ,(cons (,car ,$1) $2) )
+	    | EMPTY
+	      ()
+	    ;
+
+STARMOD : CONST
+	;
+
 declmods : DECLMOD declmods
 	   ( ,(cons ,(car ,$1) $2 ) )
 	 | DECLMOD
 	| VOLATILE
 	| SIGNED
 	| UNSIGNED
-	| VIRTUAL
 	| INLINE
+	| REGISTER
+	| FRIEND
+	| METADECLMOD
 	;
 
-# Don't deal with the stars or reference just yet.
-typeform : typeformbase opt-stars opt-ref
-	   ( ,$1 )
-	 ;
+metadeclmod : METADECLMOD
+	      ()
+	    | EMPTY
+	      ()
+	    ;
+
+METADECLMOD : VIRTUAL
+	    | MUTABLE
+	    ;
 
 # C++: A type can be modified into a reference by "&"
 opt-ref : AMPERSAND
+	  ( 1 )
 	| EMPTY
+	  ( 0 )
 	;
 
 typeformbase : typesimple
 	       ( $2 type $1 )
 	     | builtintype
 	       ( ,$1 )
+	     | symbol template-specifier
+	       ( $1 type "class" )
+	     | symbol COLON COLON typeformclassbase
+	       ( (concat $1 "::" (car $4) ) )
 	     | symbol
 	       ( $1 )
 	     ;
 
+typeformclassbase : symbol COLON COLON typeformclassbase
+		    ( (concat $1 "::" (car $4)) )
+		  | symbol
+		    ( $1 )
+		  ;
+
 builtintype : VOID
 	    | CHAR
 	    | SHORT
 	    | DOUBLE
 	    ;
 
-var-or-fun : declmods typeform var-or-func-decl
-	     ( ,(semantic-c-reconstitute-token ,$3 $1 $2 ) )
+codeblock-var-or-fun : declmods typeformbase metadeclmod
+		       opt-ref var-or-func-decl
+		       ( ,(semantic-c-reconstitute-token ,$5 $1 $2 ) )
+		     ;
+
+var-or-fun : codeblock-var-or-fun
+	     ( ,$1 )
 	   # it is possible for a function to not have a type, and
 	   # it is then assumed to be an int.  How annoying.
+	   # In C++, this could be a constructor or a destructor.
+	   # Even more annoying.  Only ever do this for regular
+	   # top-level items.  Ignore this problem in code blocks
+	   # so that we don't have to deal with regular code
+	   # being erroneously converted into types.
 	   | declmods var-or-func-decl
 	     ( ,(semantic-c-reconstitute-token ,$2 $1 nil ) )
 	   ;
 
-var-or-func-decl : opt-class opt-destructor functionname arg-list 
-		   opt-throw
-		   fun-or-proto-end
-		   ( ,$3 'function 
-			 ;; Extra stuff goes in here.
-			 ;; Continue with the stuff we found in
-			 ;; this definition
-			$1 $2 $4 $5)
-		 | varnamelist  SEMICOLON
-		   ( $1 'variable )
+var-or-func-decl : func-decl
+		   ( ,$1 )
+		 | var-decl
+		   ( ,$1 )
 		 ;
 
+func-decl : opt-stars opt-class opt-destructor functionname
+	    opt-template-specifier
+	    opt-under-p 
+	    arg-list
+	    opt-post-fcn-modifiers
+	    opt-throw
+	    opt-initializers
+	    fun-or-proto-end
+	    ( ,$4 'function 
+		  ;; Extra stuff goes in here.
+		  ;; Continue with the stuff we found in
+		  ;; this definition
+		  $2 $3 $7 $9 $8 ,$1 ,$11)
+	  ;
+
+var-decl :  varnamelist  SEMICOLON
+	   ( $1 'variable )
+	 ;
+
+opt-under-p : UNDERP
+	      (nil)
+	    | UNDERUNDERP
+	      (nil)
+	    | EMPTY
+	    ;
+
+opt-initializers: COLON symbol semantic-list opt-initializers
+		| COMA symbol semantic-list opt-initializers
+		| EMPTY
+		;
+
+opt-post-fcn-modifiers : post-fcn-modifiers opt-post-fcn-modifiers
+			 ( ,(cons ,$1 $2) )
+		       | EMPTY
+			 ( nil )
+		       ;
+
+post-fcn-modifiers : REENTRANT
+		   | CONST
+		   ;
+
 opt-throw : THROW semantic-list
 	     ( EXPAND $2 throw-exception-list )
 	   | EMPTY
 
 # Is this true?  I don't actually know.
 throw-exception-list : symbol COMA throw-exception-list
-			( ,(cons $1 $3) )
-		      | symbol close-paren ")"
-			( $1 )
+		       ( ,(cons $1 $3) )
+		     | symbol close-paren ")"
+		       ( $1 )
 		     | open-paren "(" throw-exception-list
-			( ,$2 )
-		      ;
+		       ( ,$2 )
+		     | close-paren ")"
+		       (  )
+		     ;
 
-opt-bits : COLON symbol
+opt-bits : COLON number
 	   ( $2 )
 	 | EMPTY
 	   ( nil )
 	;
 
 # I should store more in this def, but leave it simple for now.
-variablearg : declmods typeform varname
-	      ( (car $3) variable $2 nil
+variablearg : declmods typeformbase opt-ref variablearg-opt-name
+	      ( (list $4) variable $2 nil
 		 (ASSOC const (if (member "const" $1) t nil)
-			typemodifiers (delete "const" $1))
+			typemodifiers (delete "const" $1)
+			reference (car ,$3)
+			)
 		 nil
 		 )
 	    ;
 
+variablearg-opt-name: varname
+		      ( ,$1)
+		    | EMPTY
+		      ( ""  0 nil nil nil )
+		    ;
+
 varnamelist : varname COMA varnamelist
 	      ( ,(cons $1 $3) )
             | varname
 		 ( nil )
 	       ;
 
-arg-list : symbol "\\<__?P\\>" semantic-list
-	   (EXPAND $2 arg-list-p)
-	 | semantic-list "^(" knr-arguments
+arg-list : semantic-list "^(" knr-arguments
 	   ( ,$2 )
 	 | semantic-list "^("
 	   (EXPANDFULL $1 arg-sub-list)
+	 | semantic-list "^(void)$"
+	   ( )
 	 ;
 
 knr-arguments : variablearg SEMICOLON knr-arguments
-		( ,(cons $1 $3) )
+		( ,(cons (car (semantic-expand-c-nonterminal ,$1) ) ,$3) )
 	      | variablearg SEMICOLON
-		( $1 )
+		( (car (semantic-expand-c-nonterminal ,$1)) )
 	      ;
 
-arg-list-p : open-paren "(" semantic-list close-paren ")"
-	     (EXPANDFULL $2 arg-sub-list)
-	   ;
-
 arg-sub-list : variablearg
 	       ( ,$1 )
 	     | PERIOD PERIOD PERIOD close-paren ")"
 	       ( "..." )
+	     | COMA
+	       ( nil )
 	     | open-paren "("
 	       ( nil )
 	     | close-paren ")"
 	      ( ">=" )
 	    | BANG EQUAL
 	      ( "!=" )
+	    | MINUS GREATER
+	      ( "->" )
 	    | LESS
 	    | GREATER
 	    | STAR
 	    | MINUS
 	    | DIVIDE
 	    | EQUAL
+	    | BANG
 	    ;
 
 functionname : OPERATOR operatorsym
 		  ( t )
 		| semantic-list
 		  ( nil )
+		# Here is an anoying feature of C++ pure virtual methods
+		| EQUAL number "^0$" SEMICOLON
+		  ( 'pure-virtual )
 		;
 
 opt-expression : expression
 	       | EMPTY ( nil )
 	       ;
 
+type-cast : semantic-list
+	    ( EXPAND $1 type-cast-list )
+	  ;
+
+type-cast-list : open-paren typeformbase close-paren
+	       ;
+
+function-call: symbol semantic-list
+             ;
+
 # Use expression for parsing only.  Don't actually return anything
 # for now.  Hopefully we can fix this later.
-expression : symbol
-	     ( )
-           | punctuation "[!*&~]" symbol
-	     ( )
+expression : number
+	     ( (identity start) (identity end) )
+	   | function-call
+	     ( (identity start) (identity end) )
+	   | symbol
+	     ( (identity start) (identity end) )
 	   | string
-	     ( )
-           | semantic-list
-	     ( )
-	   # | expression "+-*/%^|&" expression
-	   # ( nil )
+	     ( (identity start) (identity end))
+           | type-cast expression  # A cast to some other type
+	     ( (identity start) (identity end) )
+	   | semantic-list
+	     ( (identity start) (identity end) )
+	   | punctuation "[-+*/%^|&]" expression
+	     ( (identity start) (identity end) )
 	   ;
 ;;; Code:
 (provide 'document-vars)
 
+(eval-when-compile
+  ;; Emacs 21
+  (condition-case nil
+      (require 'newcomment)
+    (error nil))
+  )
+
+(defvar document-comment-start nil
+  "Comment start string.")
+
+(defvar document-comment-line-prefix nil
+  "Comment prefix string.  Used at the beginning of each line.")
+
+(defvar document-comment-end nil
+  "Comment end string.")
+
 (defcustom document-copyright-notice-file nil
   "*A file name containing a copyright notice.
 It will be reformatted in the header to have the correct prefix character.
 ;;; document.el --- Use the bovinator to aid in generating documentation.
 
-;;; Copyright (C) 2000, 2001 Eric M. Ludlam
+;;; Copyright (C) 2000, 2001, 2002 Eric M. Ludlam
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Keywords: doc
 ;; can not insert foriegn tokens.
 
 (require 'sformat)
+;; This contains most variable settings for auto-comment generation.
 (require 'document-vars)
 
 ;;; Code:
   :group 'document
   :type 'string)
 
-(defvar document-comment-start nil
-  "Comment start string.")
-
-(defvar document-comment-line-prefix nil
-  "Comment prefix string.  Used at the beginning of each line.")
-
-(defvar document-comment-end nil
-  "Comment end string.")
-
 (defvar document-runflags nil
   "Flags collected while updating a comment.
 This is used to create a history element.")
 
-;; This contains most variable settings for auto-comment generation.
-(require 'document-vars)
-
 ;;; Status tracking
 ;;
 (defvar document-current-output-file nil
 	(document-insert-function-comment-new nonterm))
       (message "Done..."))
      (t
-      (error "Type %s is not yet managed by document `document-inline'" tt)))))
+      (error "Type %S is not yet managed by document `document-inline'" tt)))))
 
 (defun document-update-comment (nonterm)
   "Update an existing comment for NONTERM."
 	(if p (insert (format (cdr p) (cdr (car document-runflags))))))
       (setq document-runflags (cdr document-runflags)))))
 
+(defun document-argument-name (arg)
+  "Return a string representing the argument ARGs name.
+Arguments can be semantic tokens, or strings."
+  (cond ((semantic-token-p arg)
+	 (semantic-token-name arg))
+	((stringp arg)
+	 arg)
+	(t (format "%s" arg))))
+
 (defun document-update-paramlist (nonterm comment)
   "Update NONTERM's comment found in the flex token COMMENT."
   (let ((endpos 0) st en (il nil)
 	;; are the same.
 	(let ((tl l) (stop nil))
 	  (while (and tl (not stop))
-	    (if (not (assoc (semantic-token-name (car tl)) il))
+	    (if (not (assoc (document-argument-name (car tl)) il))
 		(setq stop t))
 	    (setq tl (cdr tl)))
 	  (if (not stop)
 		(cs1 nil)
 		(num 0))
 	    (while ntl
-	      (if (not (assoc (semantic-token-name (car ntl)) il))
+	      (if (not (assoc (document-argument-name (car ntl)) il))
 		  (progn
 		    (setq num (1+ num))
 		    (setq cs1 (concat cs1 (if cs1 ", ")
-				      (semantic-token-name (car ntl))))))
+				      (document-argument-name (car ntl))))))
 	      (setq ntl (cdr ntl)))
 	    (if cs1
 		(if (= num 1)
       (setq string (document-texify-elisp-docstring string)))
   ;; Else, other languages are simpler.  Also, might as well
   ;; run the elisp version through also.
-  (let ((case-fold-search nil))
+  (let ((case-fold-search nil)
+	(start 0))
     (while (string-match
 	    "\\(^\\|[^{]\\)\\<\\([A-Z0-9_-]+\\)\\>\\($\\|[^}]\\)"
-	    string)
+	    string start)
       (setq string (concat (substring string 0 (match-beginning 2))
 			   "@var{"
 			   (match-string 2 string)
 			   "}"
-			   (substring string (match-end 2)))))
+			   (substring string (match-end 2)))
+	    start (match-end 2)))
     )
   string)
 
 
 %(progn
    (setq
+    ;; Java numbers
+    semantic-number-expression semantic-java-number-regexp
     ;; Java is case sensitive
     semantic-case-fold nil
     ;; special handling of multiple variable declarations/statement
     ;; Semantic navigation inside 'type children
     senator-step-at-token-ids '(function variable)
     )
-   ;; Needed by `semantic-find-doc-snarf-comment'.
-   (set (make-local-variable 'block-comment-end) "\\s-*\\*/")
    )%
 
 %token ABSTRACT     "abstract"
 # - `with-ref' (optional) if non-nil indicates that the tag is
 #   followed by a reference like in "@see <reference>".
 
-%token AUTHOR      "author"
-%put   AUTHOR      javadoc (seq 1 usage (type))
-%token VERSION     "version"
-%put   VERSION     javadoc (seq 2 usage (type)) 
-%token PARAM       "param"
-%put   PARAM       javadoc (seq 3 usage (function) with-name t) 
-#%token RETURN      "return"
-%put   RETURN      javadoc (seq 4 usage (function)) 
-%token EXCEPTION   "exception"
-%put   EXCEPTION   javadoc (seq 5 usage (function) with-name t) 
-#%token THROWS      "throws"
-%put   THROWS      javadoc (seq 6 usage (function) with-name t) 
-%token SEE         "see"
-%put   SEE         javadoc (seq 7 usage (type function variable) opt t with-ref t) 
-%token SINCE       "since"
-%put   SINCE       javadoc (seq 8 usage (type function variable) opt t) 
-%token SERIAL      "serial"
-%put   SERIAL      javadoc (seq 9 usage (variable) opt t) 
-%token SERIALDATA  "serialData"
-%put   SERIALDATA  javadoc (seq 10 usage (function) opt t) 
-%token SERIALFIELD "serialField"
-%put   SERIALFIELD javadoc (seq 11 usage (variable) opt t) 
-%token DEPRECATED  "deprecated"
-%put   DEPRECATED  javadoc (seq 12 usage (type function variable) opt t) 
+%token _AUTHOR      "@author"
+%put   _AUTHOR      javadoc (seq 1 usage (type))
+%token _VERSION     "@version"
+%put   _VERSION     javadoc (seq 2 usage (type)) 
+%token _PARAM       "@param"
+%put   _PARAM       javadoc (seq 3 usage (function) with-name t) 
+%token _RETURN      "@return"
+%put   _RETURN      javadoc (seq 4 usage (function)) 
+%token _EXCEPTION   "@exception"
+%put   _EXCEPTION   javadoc (seq 5 usage (function) with-name t) 
+%token _THROWS      "@throws"
+%put   _THROWS      javadoc (seq 6 usage (function) with-name t) 
+%token _SEE         "@see"
+%put   _SEE         javadoc (seq 7 usage (type function variable) opt t with-ref t) 
+%token _SINCE       "@since"
+%put   _SINCE       javadoc (seq 8 usage (type function variable) opt t) 
+%token _SERIAL      "@serial"
+%put   _SERIAL      javadoc (seq 9 usage (variable) opt t) 
+%token _SERIALDATA  "@serialData"
+%put   _SERIALDATA  javadoc (seq 10 usage (function) opt t) 
+%token _SERIALFIELD "@serialField"
+%put   _SERIALFIELD javadoc (seq 11 usage (variable) opt t) 
+%token _DEPRECATED  "@deprecated"
+%put   _DEPRECATED  javadoc (seq 12 usage (type function variable) opt t) 
 
 # --------
 # Grammar
                 | type_declaration
                 ;
   
-number : symbol "[0-9]" punctuation "\\." symbol "[0-9Ee]"
-         punctuation "[-+]" symbol "[0-9fFdD]"
-       | symbol "[0-9]" punctuation "\\." symbol "[0-9EefFdD]"
-       | symbol "[0-9fFdD]"
-       ;
-  
 literal : number
         | qualified_name
         | string
 # Simple BNF notation for Makefiles.
 #
-# Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
+# Copyright (C) 1999, 2000, 2001, 2002 Eric M. Ludlam
 #
 # Author: Eric M. Ludlam <zappo@gnu.org>
 # X-RCS: $Id$
 # Boston, MA 02111-1307, USA.
 #
 # $Log$
+# Revision 1.13  2002/05/07 01:31:15  zappo
+# Merged from v1_4 branch.
+#
+# Revision 1.12.2.2  2002/02/19 21:35:09  zappo
+# (setup): Enable whitespace
+# (BACKSLASH): New token
+# (variable rule conditional targets include): Use whitespace where needed.
+# (targets): Enable subtarget groupings w/ mixed variables.
+# (target sub-target): New rules
+# (element-list, element, sub-element): New rules
+# (elements): Enable mixed groupings.
+# (opt-whitespace): New rule.
+#
+# Revision 1.12.2.1  2002/02/10 18:06:04  zappo
+# (semantic-flex-syntax-modifications): Remove tab.
+# (conditional): Return explicit nils.
+#
+# Revision 1.12  2001/12/18 02:19:48  zappo
+# Removed parens and $ from symbol syntax types.
+# Added IFEQ and IFNEQ tokens
+# Added BACKSLASH and DOLLAR tokens
+# Added IFEQ and IFNEQ rule matches
+# Added $(VAR) types to expression.
+# Support backslash terminated lines for variables.
+#
+# Revision 1.11  2001/12/07 01:36:32  zappo
+# Added ifdef, and ifndef tokens.  (Oy)
+#
+# Revision 1.10  2001/12/07 01:32:45  zappo
+# Added ifdef, and ifndef commands.
+#
+# Revision 1.9  2001/11/08 19:40:21  zappo
+# (Makefile): Handle blank lines
+#
+# Revision 1.8  2001/10/03 00:29:01  zappo
+# Disable number matching.
+#
 # Revision 1.7  2001/04/13 02:01:59  zappo
 # Added a keyword table, and several new tokens and summaries.
 # Added support for the include macro.
 %setupfunction semantic-default-make-setup
 %quotemode     backquote
 
-%(setq semantic-flex-enable-newlines t
-       semantic-symbol->name-assoc-list '((variable . "Variables")
+%(setq semantic-symbol->name-assoc-list '((variable . "Variables")
 					  (function . "Rules")
 					  (include . "Dependencies"))
+       semantic-number-expression nil
        semantic-case-fold t
+       semantic-expand-nonterminal 'semantic-expand-make-nonterminal
        semantic-flex-syntax-modifications '((?. "_")
 					    (?= ".")
 					    (?/ "_")
-					    (?\t ".")
-					    (?( "_")
-					    (?) "_")
-					    (?{ "_")
-					    (?} "_")
-					    (?$ "_")
+					    (?$ ".")
 					    )
        semantic-flex-enable-newlines t
+       semantic-flex-enable-whitespace t
        imenu-create-index-function 'semantic-create-imenu-index
        )%
 
 %token IF "if"
+%token IFDEF "ifdef"
+%token IFNDEF "ifndef"
+%token IFEQ "ifeq"
+%token IFNEQ "ifneq"
 %token ELSE "else"
 %token ENDIF "endif"
 %put { IF ELSE ENDIF } summary "Conditional: if (expression) ... else ... endif"
+%put IFDEF  summary "Conditional: ifdef (expression) ... else ... endif"
+%put IFNDEF summary "Conditional: ifndef (expression) ... else ... endif"
+%put IFEQ summary "Conditional: ifeq (expression) ... else ... endif"
+%put IFNEQ summary "Conditional: ifneq (expression) ... else ... endif"
 %token INCLUDE "include"
 %put INCLUDE summary "Macro: include filename1 filename2 ..."
 
 %token COLON punctuation ":"
 %token PLUS punctuation "+"
 %token EQUAL punctuation "="
+%token DOLLAR punctuation "$"
+%token BACKSLASH punctuation "\\"
 
 Makefile : variable
 	 | rule
 	 | conditional
 	 | include
+	 | whitespace ( nil )
+	 | newline ( nil )
 	 ;
 
-variable: symbol equals elements
-	  (,$1 variable nil ,$3 nil nil)
+variable: symbol opt-whitespace equals opt-whitespace element-list
+	  (,$1 variable nil ,$5 nil nil)
 	;
 
-rule: symbol colons elements commands
-      (,$1 function nil ,$3 nil nil)
+rule: targets opt-whitespace colons opt-whitespace element-list commands
+      (,$1 function nil ,$5 nil nil)
     ;
 
-conditional: IF symbol newline
-	     ( )
+targets: target opt-whitespace targets
+	 ( (car ,$1) (car ,@$3) )
+       | target
+	 ( (car ,$1) )
+       ;
+
+target: sub-target target
+	( (concat (car ,$1) (car ,@$3) ) )
+      | sub-target
+	( (car ,$1) )
+      ;
+
+sub-target: symbol
+	  | string
+	  | varref
+	  ;
+
+conditional: IF whitespace symbol newline
+	     ( nil )
+	   | IFDEF whitespace symbol newline
+	     ( nil )
+	   | IFNDEF whitespace symbol newline
+	     ( nil )
+	   | IFEQ whitespace expression newline
+	     ( nil )
+	   | IFNEQ whitespace expression newline
+	     ( nil )
 	   | ELSE newline
-	     ( )
+	     ( nil )
 	   | ENDIF newline
-	     ( )
+	     ( nil )
 	   ;
 
-include: INCLUDE symbol elements
-	 (,$2 include nil)
+expression : semantic-list
+	   ;
+
+include: INCLUDE whitespace element-list
+	 (,$3 include nil nil)
        ;
 
 equals: COLON EQUAL ()
       | COLON ()
       ;
 
-elements: symbol elements
-	  ( ,$1 ,@$2 )
-	| symbol newline
+element-list: elements newline
+	      ( ,@$1 )
+	    ;
+
+elements: element whitespace elements
+	  ( ,$1 ,@$3 )
+	| element
 	  ( ,$1 )
-	| newline
-	  (  )
+	| EMPTY
 	;
   
+element: sub-element element
+	 ( (concat (car ,$1) (car ,$2)) )
+       | EMPTY
+       ;
+
+sub-element: symbol
+	   | string
+	   | punctuation
+	   | semantic-list
+	     ( (buffer-substring-no-properties
+		 (identity start) (identity end)) )
+	   ;
+
+varref: DOLLAR semantic-list
+	( (buffer-substring-no-properties (identity start) (identity end)) )
+      ;
+
 commands: shell-command newline commands
 	  ( ,$1 ,@$2 )
 	| EMPTY
 	  ( )
 	;
 
+opt-whitespace : whitespace ( nil )
+	       | EMPTY
+	       ;
 # End
 					   (function . "Functions")
 					   (include  . "Loads")
 					   (package  . "DefinModule"))
+       semantic-number-expression nil
        imenu-create-index-function 'semantic-create-imenu-index
        semantic-dependency-include-path semantic-default-scheme-path
        imenu-create-index-function 'semantic-create-imenu-index

semantic-analyze.el

+;;; semantic-analyze.el --- Analyze semantic tokens against local context
+
+;;; Copyright (C) 2000, 2001, 2002 Eric M. Ludlam
+
+;; Author: Eric M. Ludlam <zappo@gnu.org>
+;; Keywords: syntax
+;; X-RCS: $Id$
+
+;; This file is not part of GNU Emacs.
+
+;; Semantic 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., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; Semantic, as a tool, provides a nice list of searchable tokens.
+;; That information can provide some very accurate answers if the current
+;; context of a position is known.
+;;
+;; Semantic-ctxt provides ways of analyzing, and manipulating the
+;; semantic context of a language in code.
+;;
+;; This library provides routines for finding intelligent answers to
+;; tough problems, such as if an argument to a function has the correct
+;; return type, or all possible tokens that fit in a given local context.
+;;
+
+(require 'eieio)
+(require 'semantic-ctxt)
+(eval-when-compile (require 'semanticdb))
+
+;;; Code:
+
+;;; Context Analysis
+;;
+(defun semantic-analyze-find-nonterminals-by-prefix (prefix)
+  "Attempt to find a nonterminal with PREFIX.
+This is a wrapper on top of semanticdb, and semantic search functions.
+Almost all searches use the same arguments."
+  (let ((expr (concat "^" (regexp-quote prefix))))
+    (if (and (fboundp 'semanticdb-minor-mode-p)
+	     (semanticdb-minor-mode-p))
+	;; Search the database
+	(let ((dbans (semanticdb-find-nonterminal-by-name-regexp
+		      expr  nil nil t nil t)))
+	  ;; Concatenate all matches together.
+	  (apply #'append (mapcar #'cdr dbans))
+	  )
+      ;; Search just this file because there is no DB available.
+      (semantic-find-nonterminal-by-name-regexp
+       expr (current-buffer) nil t))))
+  
+(defun semantic-analyze-find-nonterminal (name &optional tokentype)
+  "Attempt to find a nonterminal with NAME.
+Optional argument TOKENTYPE specifies tye type of token to
+return, such as 'function or 'variable.
+This is a wrapper on top of semanticdb, and semantic search functions.
+Almost all searches use the same arguments."
+  (if (and (fboundp 'semanticdb-minor-mode-p)
+	   (semanticdb-minor-mode-p))
+      ;; Search the database
+      (let ((dbans (semanticdb-find-nonterminal-by-name
+		    name nil nil t nil t)))
+	;; Lame, grabbing the first file match
+	(cdr (car dbans)))
+    ;; Search just this file
+    (semantic-find-nonterminal-by-name
+     name (current-buffer) nil t)))
+
+(defun semantic-analyze-token-type-to-name (token)
+  "Get the name of TOKEN's type.
+The TYPE field in a token can be nil (return nil)
+or a string, or a non-positional token."
+  (let ((tt (semantic-token-type token)))
+    (cond ((semantic-token-p tt)
+	   (semantic-token-name tt))
+	  ((stringp tt)
+	   tt)
+	  ((listp tt)
+	   (car tt))
+	  (t nil))))
+
+(defun semantic-analyze-dereference-metatype (type)
+  "Return a concrete type token based on input TYPE token.
+A concrete type is an actual declaration of a memory description,
+such as a structure, or class.  A meta type is an alias,
+or a typedef in C or C++.  If TYPE is concrete, it
+is returned.  If it is a meta type, it will return the concrete
+type defined by TYPE.
+The behavior can be overriden using `analyze-derefernce-metatype'.
+The default behavior always returns TYPE.
+Override functions need not return a real semantic token.
+Just a name, or short token will be ok.  It will be expanded here."
+  (let* ((s (semantic-fetch-overload 'analyze-dereference-metatype)))
+    (if s
+	(let ((ans (funcall s type)))
+	  ;; If ANS is a string, or if ANS is a short token, we
+	  ;; need to do some more work to look it up.
+	  (cond ((stringp ans)
+		 (semantic-analyze-find-nonterminal ans))
+		((and (semantic-token-p ans)
+		      (eq (semantic-token-token ans) 'type)
+		      (semantic-token-type-parts ans))
+		 ans)
+		((and (semantic-token-p ans)
+		      (eq (semantic-token-token ans) 'type)
+		      (not (semantic-token-type-parts ans)))
+		 (semantic-analyze-find-nonterminal
+		  (semantic-token-name ans)))
+		(t nil)))
+      ;; Nothing fancy, just return type be default.
+      type)))
+
+(defun semantic-analyze-token-type (token)
+  "Return the semantic token for a type within the type of TOKEN.
+TOKEN can be a variable, function or other type of token.
+The type of token (such as a class or struct) is a name.
+Lookup this name in database, and return all slots/fields
+within that types field.  Also handles anonymous types."
+  (let ((ttype (semantic-token-type token))
+	(name nil)
+	(typetoken nil)
+	)
+
+    ;; Is it an anonymous type?
+    (if (and ttype
+	     (semantic-token-p ttype)
+	     (eq (semantic-token-token ttype) 'type)
+	     (semantic-nonterminal-children ttype))
+	;; We have an anonymous type for TOKEN with children.
+	;; Use this type directly.
+	(semantic-analyze-dereference-metatype ttype)
+
+      ;; Not an anonymous type.  Look up the name of this type
+      ;; elsewhere, and report back.
+      (setq name (semantic-analyze-token-type-to-name token))
+      (if (and name (not (string= name "")))
+	  (setq typetoken (semantic-analyze-find-nonterminal name))
+	;; No name to look stuff up with.
+	(error "Semantic token %S has no type information"
+	       (semantic-token-name ttype)))
+
+      ;; Handle lists of tokens.
+      (if (and (listp typetoken) (semantic-token-p (car typetoken)))
+
+	  (let ((toklist typetoken))
+	    (setq typetoken nil)
+	    ;; Loop over all returned elements until we find a type
+	    ;; that is a perfect match.
+	    (while (and toklist (not typetoken))
+	      ;; FIXME: Do better matching.
+	      (if (and (car toklist)
+		       (eq (semantic-token-token (car toklist)) 'type))
+		  (setq typetoken (car toklist)))
+	      (setq toklist (cdr toklist)))))
+
+      ;; We now have a token associated with the type.
+      (semantic-analyze-dereference-metatype typetoken))))
+
+(defun semantic-analyze-find-nonterminal-sequence (sequence &optional localvar scope typereturn)
+  "Attempt to find all nonterminals in SEQUENCE.
+Optional argument LOCALVAR is the list of local variables to use when
+finding the details on the first element of SEQUENCE in case
+it is not found in the global set of tables.
+Optional argument SCOPE are additional terminals to search which are currently
+scoped.  These are no local variables, but symbols available in a structure
+which doesn't need to be dereferneced.
+Optional argument TYPERETURN is a symbol ini which the types of all found
+will be stored.  If nil, that data is thrown away."
+  (let ((s sequence)			;copy of the sequence
+	(tmp nil)			;tmp find variable
+	(nexttype nil)			;a token for the type next in sequence
+	(tok nil)			;token return list
+	(toktype nil)			;token types return list
+	)
+    ;; For the first entry, it better be a variable, but it might
+    ;; be in the local context too.
+    ;; NOTE: Don't forget c++ namespace foo::bar.
+    (setq tmp (or (semantic-analyze-find-nonterminal (car s) 'variable)
+		  (semantic-find-nonterminal-by-name
+		   (car s) scope)
+		  (semantic-find-nonterminal-by-name
+		   (car s) (semantic-get-local-arguments))
+		  ;; This should be first, but bugs in the
+		  ;; C parser will turn function calls into
+		  ;; assumed int return function prototypes.  Yuck!
+		  (semantic-find-nonterminal-by-name
+		   (car s) localvar)))
+
+    (if (and (listp tmp) (semantic-token-p (car tmp)))
+	;; We should be smarter... :(
+	(setq tmp (car tmp)))
+    (if (not (semantic-token-p tmp))
+	(error "Cannot find definition for \"%s\"" (car s)))
+    (setq s (cdr s))
+    (setq tok (cons tmp tok))
+
+    ;; For the middle entries
+    (while s
+      ;; Using the token found in TMP, lets find the token
+      ;; representing the full typeographic information of it's
+      ;; type, and use that to determine the search context for
+      ;; (car s)
+      (let ((tmptype (semantic-analyze-token-type tmp))
+	    (slots nil))
+	
+	;; Get the children
+	(setq slots (semantic-nonterminal-children tmptype))
+
+	;; find (car s) in the list o slots
+	(setq tmp (semantic-find-nonterminal-by-name (car s)
+						     slots nil nil))
+	
+	(if (and (listp tmp) (semantic-token-p (car tmp)))
+	    ;; We should be smarter...  For example
+	    ;; search for an item only of 'variable if we know
+	    ;; the syntax is variable, or only 'function if we
+	    ;; can see a function.  Most languages don't allow that
+	    ;; type of duality, so we will probably be safe with this
+	    ;; forever.
+	    (setq tmp (car tmp)))
+
+	;; Make sure we have a token.
+	(if (not (semantic-token-p tmp))
+	    (if (cdr s)
+		;; In the middle, we need to keep seeking our types out.
+		(error "Cannot find definition for \"%s\"" (car s))
+	      ;; Else, it's ok to end with a non-token
+	      (setq tmp (car s))))
+
+	(setq tok (cons tmp tok))
+	(setq toktype (cons tmptype toktype))
+	)
+      (setq s (cdr s)))
+
+    (if typereturn (set typereturn (nreverse toktype)))
+    ;; Return the mess
+    (nreverse tok)))
+
+(defun semantic-analyze-type-parts (type)
+  "Return all parts of TYPE, a nonterminal representing a TYPE declaration.
+This includes both the TYPE parts, and all functions found in all
+databases which have this type as a property."
+  (let ((slots (semantic-token-type-parts type))
+	(extmeth (semantic-nonterminal-external-member-children type)))
+    ;; Flatten the database output.
+    (append slots extmeth)
+    ))
+
+(defun semantic-analyze-scoped-nonterminals (typelist)
+  "Return a list of nonterminals accessable when TYPELIST is in scope.
+Tokens returned are not in the global name space, but are instead
+scoped inside a class or namespace.  Such items can be referenced
+without use of \"object.function()\" style syntax due to an
+implicit \"object\"."
+  (apply #'append (mapcar #'semantic-analyze-type-parts typelist))
+  ;; We also need to get all parents of typelist, and include public or
+  ;; protected methods of those!
+  )
+
+(defun semantic-analyze-scoped-types (&optional position)
+  "Return a list of types current in scope at POSITION.
+This is based on what tokens exist at POSITION, and any associated
+types available."
+  (save-excursion
+    (if position (goto-char position))
+    (let ((tok (semantic-current-nonterminal))
+	  (code-scoped-parents nil)
+	  (parent nil))
+      (setq parent
+	    ;; This only makes sense in a function
+	    (when (and tok (eq (semantic-token-token tok) 'function))
+	      ;; If TOK is a function, it may have a parent class.
+	      ;; Find it.
+	      (let ((p (semantic-token-function-parent tok)))
+		(if p
+		    ;; We have a parent, search for it.
+		    (let ((ptok (semantic-analyze-find-nonterminal
+				 (cond ((stringp p) p)
+				       ((semantic-token-p p)
+					(semantic-token-name p))
+				       ((and (listp p) (stringp (car p)))
+					(car p))) 'type)))
+		      ptok)
+		  ;; No specified parent.  See if there is a parent by
+		  ;; position?
+		  (setq p (semantic-current-nonterminal-parent))
+		  p))
+	      ;; Lets ask if any types are currently scoped.  Scoped
+	      ;; classes and types provide their public methods and types
+	      ;; in source code, but are unrelated hierarchically.
+	      (let ((sp (semantic-ctxt-scoped-types)))
+		(while sp
+		  ;; Get this thing as a non terminal
+		  (setq code-scoped-parents
+			(cons
+			 (semantic-analyze-find-nonterminal (car sp))
+			 code-scoped-parents))
+		  (setq  sp (cdr sp))))
+	      (setq code-scoped-parents (nreverse code-scoped-parents))
+	      ))
+      ;; We return a list in case a function can have multiple explicit
+      ;; parents.
+      (if parent
+	  (cons parent code-scoped-parents)
+	code-scoped-parents))))
+
+;;; Top Level context analysis function
+;;
+(defclass semantic-analyze-context ()
+  ((bounds :initarg :bounds
+	   :type list
+	   :documentation "The bounds of this context.
+Usually bound to the dimension of a single symbol or command.")
+   (prefix :initarg :prefix
+	   :type list
+	   :documentation "List of tokens defining local text.
+This can be nil, or a list where the last element can be a string
+representing text that may be incomplete.  Preceeding elements
+must be semantic tokens representing variables or functions
+called in a dereference sequence.")
+   (prefixtypes :initarg :prefixtypes
+	   :type list
+	   :documentation "List of tokens defining types for :prefix.
+This list is one shorter than :prefix.  Each element is a semantic
+token representing a type matching the semantic token in the same
+position in PREFIX.")
+   (scopetypes :initarg :scopetypes
+	       :type list
+	       :documentation "List of type tokens in scope.
+When in a function is called, it may have certain other types
+in scope, such as classes in it's lineage.  This is a list
+of all those classes.")
+   (scope :initarg :scope
+	  :type list
+	  :documentation "List of tokens available in scopetype.
+See `semantic-analyze-scoped-nonterminals' for details.")
+   (localvariables :initarg :localvariables
+		   :initform nil
+		   :type list
+		   :documentation "List of local variables.
+Local variables are defined withing the code scope.")
+   )
+  "Base analysis data for a any context.")
+
+(defclass semantic-analyze-context-assignment (semantic-analyze-context)
+  ((assignee :initarg :assignee
+	     :type list
+	     :documentation "A sequence of tokens for an assignee.
+This is a variable into which some value is being placed.  The last
+item in the list is the variable accepting the value.  Earlier
+tokens represent the variables being derefernece to get to the
+assignee."))
+  "Analysis class for a value in an assignment.")
+
+(defclass semantic-analyze-context-functionarg (semantic-analyze-context)
+  ((function :initarg :function
+	     :type list
+	     :documentation "A sequence of tokens for a function.
+This is a function being called.  The cursor will be in the position
+of an argument.
+The last token in :function is the function being called.  Earlier
+tokens represent the variables being dereferenced to get to the
+function.")
+   (index :initarg :index
+	  :type integer
+	  :documentation "The index of the argument for this context.
+If a function takes 4 arguments, this value should be bound to
+the values 1 through 4.")
+   (argument :initarg :argument
+	     :type list
+	     :documentation "A sequence of tokens for the :index argument.
+The argument can accept a value of some type, and this contains the 
+nonterminal for that definition.  It should be a nonterminal, but might
+be just a string in some circumstances.")
+   )
+  "Analysis class for a value as a function argument.")
+
+(defclass semantic-analyze-context-return (semantic-analyze-context)
+  () ; No extra data.
+  "Analysis class for return data.
+Return data methods identify the requred type by the return value
+of the parent function.") 
+
+;;;###autoload
+(defun semantic-analyze-current-context (position)
+  "Analyze the current context at POSITION.
+If called interactively, display interesting information about POSITION
+in a separate buffer.
+Returns an object based on symbol `semantic-analyze-context'."
+  (interactive "d")
+  (save-excursion
+    (goto-char position)
+    (let* ((context-return nil)
+	   (startpoint (point))
+	   (prefix (semantic-ctxt-current-symbol))
+	   (endsym (car (reverse prefix)))
+	   (bounds (save-excursion
+		     (cond ((and prefix (looking-at endsym))
+			    (cons (point) (progn
+					    (forward-sexp 1)
+					    (point))))
+			   (prefix
+			    (condition-case nil
+				(cons (progn (forward-sexp -1) (point))
+				      (progn (forward-sexp 1) (point)))
+			      (error nil)))
+			   (t nil))))
+	   (prefixtypes nil)
+	   (scopetypes (semantic-analyze-scoped-types position))
+	   (scope (if scopetypes
+		      (semantic-analyze-scoped-nonterminals scopetypes)))
+	   (localvar (semantic-get-local-variables))
+	   (function (semantic-ctxt-current-function))
+	   (fntok nil)
+	   arg fntokend argtok
+	   )
+
+      (condition-case nil
+	  ;; If we are on lame stuff, it won't be found!
+	  (setq prefix (semantic-analyze-find-nonterminal-sequence
+			prefix localvar scope 'prefixtypes))
+	(error nil))
+
+      (when function
+	;; If we have a function, then we can get the argument
+	(setq arg (semantic-ctxt-current-argument))
+
+	(condition-case nil
+	    (setq fntok
+		  (semantic-analyze-find-nonterminal-sequence
+		   function localvar scope))
+	  (error nil))
+
+	(when fntok
+	  (setq fntokend (car (reverse fntok))
+		argtok (nth (1- arg) (semantic-token-function-args fntokend)))
+	  ))
+
+      (if fntok
+	  ;; If we found a token for our function, we can go into
+	  ;; functional context analysis mode, meaning we have a type
+	  ;; for the argument.
+	  (setq context-return
+		  (semantic-analyze-context-functionarg
+		   "functionargument"
+		   :function fntok
+		   :index arg
+		   :argument (list argtok)
+		   :scope scope
+		   :scopetypes scopetypes
+		   :localvariables localvar
+		   :prefix prefix
+		   :bounds bounds
+		   :prefixtypes prefixtypes))
+
+	;; No function, try assignment
+	(let ((assign (semantic-ctxt-current-assignment))
+	      (asstok nil))
+	  (if assign
+	      ;; We have an assignment
+	      (setq asstok (semantic-analyze-find-nonterminal-sequence
+			    assign localvar scope)))
+	  (if asstok
+	      (setq context-return
+		    (semantic-analyze-context-assignment
+		     "assignment"
+		     :assignee asstok
+		     :scope scope
+		     :scopetypes scopetypes
+		     :localvariables localvar
+		     :bounds bounds
+		     :prefix prefix
+		     :prefixtypes prefixtypes))
+	  
+	    ;; TODO: Identify return value condition.
+
+	    ;; Nothing in particular
+	    (setq context-return
+		  (semantic-analyze-context
+		   "context"
+		   :scope scope
+		   :scopetypes scopetypes
+		   :localvariables localvar
+		   :bounds bounds
+		   :prefix prefix
+		   :prefixtypes prefixtypes)))))
+
+      ;; Check for interactivity
+      (if (interactive-p)
+	  (semantic-analyze-pop-to-context context-return))
+      ;; Return our context.
+      context-return)))
+
+
+;;; Context Analysis Completion
+;;
+(defmethod semantic-analyze-type-constraint
+  ((context semantic-analyze-context) &optional desired-type)
+  "Return a type constraint for completing :prefix in CONTEXT.
+Optional argument DESIRED-TYPE may be a non-type token to analyze."
+  (when desired-type
+    ;; Convert the desired type if needed.
+    (if (not (eq (semantic-token-token desired-type) 'type))
+	(setq desired-type (semantic-token-type desired-type)))
+    ;; Protect against plain strings
+    (cond ((stringp desired-type)
+	   (setq desired-type (list desired-type 'type)))
+	  ((and (stringp (car desired-type))
+		(not (semantic-token-p desired-type)))
+	   (setq desired-type (list (car desired-type) 'type)))
+	  ((semantic-token-p desired-type)
+	   ;; We have a token of some sort.  Yay!
+	   nil)
+	  (t (setq desired-type nil))
+	  ))
+  desired-type)
+
+(defmethod semantic-analyze-type-constraint
+  ((context semantic-analyze-context-functionarg))
+  "Return a type constraint for completing :prefix in CONTEXT."
+  (call-next-method context (car (oref context argument))))
+
+(defmethod semantic-analyze-type-constraint
+  ((context semantic-analyze-context-assignment))
+  "Return a type constraint for completing :prefix in CONTEXT."
+  (call-next-method context (car (reverse (oref context assignee)))))
+
+(defun semantic-analyze-type-constants (type)
+  "For the token TYPE, return any constant symbols of TYPE.
+Used as options when completing."
+  (let* ((s (semantic-fetch-overload 'analyze-type-constants)))
+    (if s
+	;; We need the real type so that language files don't
+	;; need to know much about analysis.
+	(let* ((realtype (semantic-analyze-find-nonterminal
+			  (semantic-token-name type)))
+	       (ans (funcall s realtype))
+	       (out nil))
+	  (while ans
+	    (cond ((stringp (car ans))
+		   (setq out (cons (list (car ans)
+					 'variable
+					 (semantic-token-name type))
+				   out)))
+		  ((semantic-token-p (car ans))
+		   (setq out (cons (car ans) out)))
+		  (t nil))
+	    (setq ans (cdr ans)))
+	  (nreverse out))
+      ;; Be default, we don't know.
+      nil)))
+
+(defun semantic-analyze-possible-completions (context)
+  "Return a list of semantic tokens which are possible completions.
+CONTEXT is either a position (such as point), or a precalculated
+context.  Passing in a context is useful if the caller also needs
+to access parts of the analysis.
+Completions run through the following filters:
+  * Elements currently in scope
+  * Constants currently in scope
+  * Elements match the :prefix in the CONTEXT.
+  * Type of the completion matches the type of the context.
+Context type matching can identify the following:
+  * No specific type
+  * Assignment into a variable of some type.
+  * Argument to a function with type constraints.
+When called interactively, displays the list of possible completions
+in a buffer."
+  (interactive "d")
+  (let* ((a (if (semantic-analyze-context-child-p context)
+		context
+	      (semantic-analyze-current-context context)))
+	 (fnargs (semantic-get-local-arguments
+		  (car (oref a bounds))))
+	 (desired-type (semantic-analyze-type-constraint a))
+	 (prefix (oref a prefix))
+	 (prefixtypes (oref a prefixtypes))
+	 (completetext nil)
+	 (completetexttype nil)
+	 (c nil))
+
+    ;; Calculate what our prefix string is so that we can
+    ;; find all our matching text.
+    (setq completetext (car (reverse prefix)))
+    (if (semantic-token-p completetext)
+	(setq completetext (semantic-token-name completetext)))
+
+    (if (and (not completetext) (not desired-type))
+	(error "Nothing to complete"))
+
+    (if (not completetext) (setq completetext ""))
+
+    ;; This better be a reasonable type, or we should fry it.
+    ;; The prefixtypes should always be at least 1 less than
+    ;; the prefix since the type is never looked up for the last
+    ;; item when calculating a sequence.
+    (setq completetexttype (car (reverse prefixtypes)))
+    (if (or (not completetexttype)
+	    (not (and (semantic-token-p completetexttype)
+		      (eq (semantic-token-token completetexttype) 'type))))
+	;; What should I do here?  I think this is an error condition.
+	(setq completetexttype nil))
+
+    ;; There are many places to get our completion stream for.
+    ;; Here we go.
+    (if completetexttype
+
+	(setq c (semantic-find-nonterminal-by-name-regexp
+		 (concat "^" completetext)
+		 (semantic-nonterminal-children completetexttype)
+		 nil nil))
+	      
+      (let ((expr (concat "^" completetext)))
+	;; No type based on the completetext.  This is a free-range
+	;; var or function.  We need to expand our search beyond this
+	;; scope into semanticdb, etc.
+	(setq c (append
+		 ;; Argument list
+		 (semantic-find-nonterminal-by-name-regexp
+		  expr fnargs
+		  nil nil)
+		 ;; Local variables
+		 (semantic-find-nonterminal-by-name-regexp
+		  expr (oref a localvariables)
+		  nil nil)
+		 ;; The current scope
+		 (semantic-find-nonterminal-by-name-regexp
+		  expr (oref a scope)
+		  nil nil)
+		 ;; The world
+		 (semantic-analyze-find-nonterminals-by-prefix
+		  completetext))
+	      )
+	))
+
+    ;; Ok, we now have a completion list based on the text we found
+    ;; we want to complete on.  Now filter that stream against the
+    ;; type we want to search for.
+    (if desired-type
+	(setq c (semantic-find-nonterminal-by-type
+		 (semantic-token-name desired-type)
+		 c nil nil)))
+
+    ;; Some types, like the enum in C, have special constant values that
+    ;; we could complete with.  Thus, if the target is an enum, we can
+    ;; find possible symbol values to fill in that value.
+    (if desired-type
+	(let ((constants
+	       (semantic-analyze-type-constants desired-type)))
+	  (if constants
+	      (progn
+		;; Filter
+		(setq constants
+		      (semantic-find-nonterminal-by-name-regexp
+		       (concat "^" completetext)
+		       constants nil nil))
+		;; Add to the list
+		(setq c (append c constants)))
+	    )))
+
+    ;; All done!
+
+    ;; If interactive, display them.
+    (when (interactive-p)
+      (with-output-to-temp-buffer "*Possible Completions*"
+	(semantic-analyze-princ-sequence c ""))
+      (shrink-window-if-larger-than-buffer
+       (get-buffer-window "*Possible Completions*"))
+      )
+    c))
+
+
+;;; Friendly output of a context analysis.
+;;
+(defcustom semantic-analyze-summary-function 'semantic-prototype-nonterminal
+  "*Function to use when creating items in Imenu.
+Some useful functions are found in `semantic-token->text-functions'."
+  :group 'semantic
+  :type semantic-token->text-custom-list)
+
+(defun semantic-analyze-princ-sequence (sequence &optional prefix)
+  "Send the token SEQUENCE to standard out.
+Use PREFIX as a label."
+  (while sequence
+    (princ prefix)
+    (if (semantic-token-p (car sequence))
+	(princ (funcall semantic-analyze-summary-function
+			(car sequence)))
+      (if (stringp (car sequence))
+	  (princ (semantic-colorize-text (car sequence) 'variable))
+	(format "%S" (car sequence))))
+    (princ "\n")
+    (setq sequence (cdr sequence))
+    (setq prefix (make-string (length prefix) ? ))
+    ))
+
+(defmethod semantic-analyze-show ((context semantic-analyze-context))
+  "Insert CONTEXT into the current buffer in a nice way."
+  (semantic-analyze-princ-sequence (oref context prefix) "Prefix: ")
+  (semantic-analyze-princ-sequence (oref context prefixtypes) "Prefix Types: ")
+  (princ "--------\n")
+  (semantic-analyze-princ-sequence (oref context scopetypes) "Scope Types: ")
+  (semantic-analyze-princ-sequence (oref context scope) "Scope: ")
+  (semantic-analyze-princ-sequence (oref context localvariables) "LocalVars: ")
+  )
+
+(defmethod semantic-analyze-show ((context semantic-analyze-context-assignment))
+  "Insert CONTEXT into the current buffer in a nice way."
+  (semantic-analyze-princ-sequence (oref context assignee) "Assignee: ")
+  (call-next-method))
+
+(defmethod semantic-analyze-show ((context semantic-analyze-context-functionarg))
+  "Insert CONTEXT into the current buffer in a nice way."
+  (semantic-analyze-princ-sequence (oref context function) "Function: ")
+  (princ "Argument Index: ")
+  (princ (oref context index))
+  (princ "\n")
+  (semantic-analyze-princ-sequence (oref context argument) "Argument: ")
+  (call-next-method))
+
+(defun semantic-analyze-pop-to-context (context)
+  "Display CONTEXT in a temporary buffer.
+CONTEXT's content is described in `semantic-analyze-current-context'."
+  (with-output-to-temp-buffer "*Semantic Context Analysis*"
+    (princ "Context Type: ")
+    (princ (object-name context))
+    (princ "\n")
+    (princ "Bounds: ")
+    (princ (oref context bounds))
+    (princ "\n")
+    (semantic-analyze-show context)
+    )
+  (shrink-window-if-larger-than-buffer
+   (get-buffer-window "*Semantic Context Analysis*"))
+  )
+
+(provide 'semantic-analyze)
+
+;;; semantic-analyze.el ends here
 ;;; semantic-bnf.el --- Semantic details for some languages
 
-;;; Copyright (C) 1999, 2000, 2001 Eric M. Ludlam
+;;; Copyright (C) 1999, 2000, 2001, 2002 Eric M. Ludlam
 
 ;; Author: Eric M. Ludlam <zappo@gnu.org>
 ;; Version: 0.2
      (KEYWORDTABLE symbol
 		   ,(semantic-lambda
 		     (list (nth 1 vals) 'keywordtable)))
+     (TOKENTABLE symbol
+		   ,(semantic-lambda
+		     (list (nth 1 vals) 'tokentable)))
      (LANGUAGEMODE symbol
 		   ,(semantic-lambda
 		     (list (nth 1 vals) 'languagemode)))
      (QUOTEMODE symbol
 		,(semantic-lambda
 		  (list (nth 1 vals) 'quotemode)))
+     (PARSERMODE symbol
+		,(semantic-lambda
+		  (list (nth 1 vals) 'parsermode)))
+     (NONASSOC terms punctuation ";"
+               ,(semantic-lambda
+                 (list (nth 0 vals) 'assoc nil (nth 1 vals))))
+     (LEFT terms punctuation ";"
+           ,(semantic-lambda
+             (list (nth 0 vals) 'assoc nil (nth 1 vals))))
+     (RIGHT terms punctuation ";"
+            ,(semantic-lambda
+              (list (nth 0 vals) 'assoc nil (nth 1 vals))))
+     )
+    (terms
+     (symbol terms
+             ,(semantic-lambda
+               (cons (nth 0 vals) (nth 1 vals))))
+     (symbol
+      ,(semantic-lambda
+        (list (nth 0 vals))))
      )
     (put-name-list
      (open-paren ,(semantic-lambda (list nil)))
 			  (nth 3 vals))))
      (,(semantic-lambda nil)))
     (match-list
-     (symbol match-list
+     (match-list-1 prec
+                   ,(semantic-lambda
+                     (append (nth 0 vals) (nth 1 vals))))
+     (match-list-1)
+     )
+    (match-list-1
+     (symbol match-list-1
 	     ,(semantic-lambda
 	       (cons (nth 0 vals) (nth 1 vals))))
-     (string match-list
+     (string match-list-1
 	     ,(semantic-lambda
 	       (cons (nth 0 vals) (nth 1 vals))))
      (string)
      (symbol)
      )
+    (prec
+     (punctuation "%" PREC symbol
+                  ,(semantic-lambda
+                    (list '%prec (nth 2 vals))))
+     )
     (lambda-fn
      (semantic-list
       ,(semantic-lambda
       ("outputfile" . OUTPUTFILE)
       ("parsetable" . PARSETABLE)
       ("keywordtable" . KEYWORDTABLE)
+      ("tokentable" . TOKENTABLE)
       ("languagemode" . LANGUAGEMODE)
       ("setupfunction" . SETUPFUNCTION)
       ("quotemode" . QUOTEMODE)
+      ("parsermode" . PARSERMODE)
+      ("nonassoc" . NONASSOC)
+      ("left" . LEFT)
+      ("right" . RIGHT)
+      ("prec" . PREC)
       )
    `(("put" summary "%put <keyword> <lisp expression>")
      ("token" summary "%token <keyword> [syntax] \"matchtext\"")
      ("start" summary "%start <starting rule name>")
      ("scopestart" summary "%scopestart <starting scope (code) rule name>")
      ("languagemode" summary "%languagemode [ lispsymbol | ( lispsym lispsym ...) ]")
+     ("parsermode" summary "%parsermode <mode>")
+     ("prec" summary "rule precedence")
      ))
   "Keyword table used for Semantic BNF files.")
 
 
+;;; Basic API
+;;
+(defsubst semantic-bnf-token-name-symbol (token)
+  "Return TOKEN name as an interned symbol."
+  (intern (semantic-token-name token)))
+
+(defmacro semantic-bnf-token-token-type (token)
+  "Return type of a 'token TOKEN."
+  `(nth 2 ,token))
+
+(defmacro semantic-bnf-token-token-value (token)
+  "Return the lisp value of a 'token TOKEN."
+  `(condition-case nil
+       (car (read-from-string (nth 3 ,token)))
+     (error
+      ;;(message "read error on %S" (nth 3 ,token))
+      nil)))
+
+(defmacro semantic-bnf-token-rule-matchlist (token)
+  "Return the matching list of a 'rule TOKEN."
+  `(nth 3 ,token))
+
+(defmacro semantic-bnf-token-assoc-terms (token)
+  "Return the list of terminals from associativity TOKEN.
+Token must be of category 'assoc."
+  `(nth 3 ,token))
+
+
 ;;; Conversion routines
 ;;
 (defun semantic-bnf-EXPAND (lst)
 	(setq tokstream (cdr tokstream))
 	(working-status (* 100.0 (- 1.0 (/ (float (length tokstream)) tl)))))
       (working-status t))
-    (insert ")\n ")
+    (insert ")\n")
     ))
+
+
+;;; LALR conversion routines
+;;
+(defun semantic-bnf-to-lalr-ASSOC (&rest args)
+  "Return expansion of built-in ASSOC expression.
+ARGS are ASSOC's key value list."
+  (let ((key t))
+    `(semantic-bovinate-make-assoc-list
+      ,@(mapcar #'(lambda (i)
+                    (prog1
+                        (if key
+                            (list 'quote i)
+                          i)
+                      (setq key (not key))))
+                args))))
+
+(defun semantic-bnf-to-lalr-EXPANDTHING ($i nonterm expander)
+  "Return expansion of built-in EXPAND/EXPANDFULL expression.
+$I is the placeholder value to expand.
+NONTERM is the nonterminal symbol to start with.
+EXPANDER is the Semantic function called to expand NONTERM"
+  (let* ((n   (symbol-name $i))
+         ($ri (and (string-match "^[$]\\([1-9][0-9]*\\)$" n)
+                   (intern (concat "$region" (match-string 1 n))))))
+    (if $ri
+        `(,expander (car ,$ri) (cdr ,$ri) ',nonterm))))
+
+(defun semantic-bnf-to-lalr-EXPAND ($i nonterm)
+  "Return expansion of built-in EXPAND expression.
+$I is the placeholder value to expand.
+NONTERM is the nonterminal symbol to start with."
+  (or (semantic-bnf-to-lalr-EXPANDTHING
+       $i nonterm 'wisent-bovinate-from-nonterminal)
+      (error "Invalid form (EXPAND %s %s)" $i nonterm)))
+
+(defun semantic-bnf-to-lalr-EXPANDFULL ($i nonterm)
+  "Return expansion of built-in EXPANDFULL expression.
+$I is the placeholder value to expand.
+NONTERM is the nonterminal symbol to start with."
+  (or (semantic-bnf-to-lalr-EXPANDTHING
+       $i nonterm 'wisent-bovinate-from-nonterminal-full)
+      (error "Invalid form (EXPANDFULL %s %s)" $i nonterm)))
+
+(defconst semantic-bnf-to-lalr-builtins
+  '(
+    ;; Builtin name . Expander
+    ;; ------------ . ---------------------------------
+    (  ASSOC        . semantic-bnf-to-lalr-ASSOC)
+    (  EXPAND       . semantic-bnf-to-lalr-EXPAND)
+    (  EXPANDFULL   . semantic-bnf-to-lalr-EXPANDFULL)
+    ;; ------------ . ---------------------------------
+    )
+  "Expanders of Semantic built-in functions in LALR grammar.")
+
+(defsubst semantic-bnf-quote-p (sym)
+  "Return non-nil if SYM is bound to the `quote' function."
+  (condition-case nil
+      (eq (indirect-function sym)
+          (indirect-function 'quote))
+    (error nil)))
+
+(defsubst semantic-bnf-backquote-p (sym)
+  "Return non-nil if SYM is bound to the `backquote' function."
+  (condition-case nil
+      (eq (indirect-function sym)
+          (indirect-function 'backquote))
+    (error nil)))
+
+(defun semantic-bnf-to-lalr-action (expr)
+  "Return expanded form of the semantic action expression EXPR.
+`backquote' expressions and Semantic built-in function calls are
+expanded.  The variable `semantic-bnf-to-lalr-builtins' defines
+built-in functions and corresponding expanders."
+  (if (not (listp expr))
+      ;; EXPR is an atom, no expansion needed
+      expr
+    ;; EXPR is a list, expand inside it
+    (let (eexpr sexpr bltn)
+      ;; If backquote expand it first
+      (if (semantic-bnf-backquote-p (car expr))
+          (setq expr (macroexpand expr)))
+      ;; Expand builtins
+      (if (setq bltn (assq (car expr) semantic-bnf-to-lalr-builtins))
+          (setq expr (apply (cdr bltn) (cdr expr))))
+      (while expr
+        (setq sexpr (car expr)
+              expr  (cdr expr))
+        ;; Recursively expand function call but quote expression
+        (and (consp sexpr)
+             (not (semantic-bnf-quote-p (car sexpr)))
+             (setq sexpr (semantic-bnf-to-lalr-action sexpr)))
+        ;; Accumulate expanded forms
+        (setq eexpr (nconc eexpr (list sexpr))))
+      eexpr)))
+
+(defun semantic-bnf-matching-to-lalr (matching)
+  "Convert the rule MATCHING from BNF to LALR internal lisp form."
+  (let* ((act (condition-case nil
+                  (read-from-string (car matching))
+                (error
+                 ;;(message "read error on %S" (car matching))
+                 nil)))
+         (l   (cdr matching))
+         ml prec)
+    (if (string-equal (car l) "EMPTY")
+        (setq l (cdr l)) ;; EMPTY rule can have a %prec clause too!
+      (while (and l (not (eq (car l) '%prec)))
+        (setq ml (cons (intern (car l)) ml)
+              l  (cdr l)))
+      (setq ml (nreverse ml)))
+    (if (eq (car l) '%prec)
+        (setq prec (vector (intern (cadr l)))))
+    ;; Here `act' is nil if previous `read-from-string' failed of a
+    ;; cons (OBJECT-READ . FINAL-STRING-INDEX) otherwise.  This permit
+    ;; to distinguish if the semantic action is missing or is actually
+    ;; nil!
+    (if act
+        (progn
+          (setq act (semantic-bnf-to-lalr-action (car act)))
+          (if prec
+              (list ml prec act)
+            (list ml act)))
+      (if prec
+          (list ml prec)
+        (list ml)))))
+
+(defsubst semantic-bnf-terminal-token-p (token)
+  "Return non-nil if BNF TOKEN is a terminal one.
+That is a token of 'keyword or 'token category."
+  (memq (semantic-token-token token) '(token keyword)))
+
+(defsubst semantic-bnf-find-terminals (tokstream)
+  "Return the list of terminal tokens from TOKSTREAM."
+  (semantic-find-nonterminal-by-function
+   #'semantic-bnf-terminal-token-p tokstream))
+
+(defsubst semantic-bnf-find-terminal-symbols (tokstream)
+  "Return the list of terminal symbols from TOKSTREAM."
+  (mapcar #'semantic-bnf-token-name-symbol
+          (semantic-bnf-find-terminals tokstream)))
+
+(defun semantic-bnf-token-table (tokstream)
+  "Return the table of 'token tokens from TOKSTREAM.
+The table is an alist of (TOK-CAT . TOK-DEFS) where TOK-CAT is a token
+category symbol.  TOK-DEFS is an alist of (TOK-KEY . TOK-VALUE) where
+TOK-KEY is a token symbol and TOK-VALUE its value as a string.
+
+For example the following BNF entries:
+
+  %token EQ     operator \":=\"
+  %token LT     operator \"<\"
+  %token LPAREN paren    \"(\"
+  %token RPAREN paren    \")\"
+
+produce the following table of tokens:
+
+  '((operator (EQ . \":=\")
+              (LT . \"<\"))
+    (paren (LPAREN . \"(\")
+           (RPAREN . \")\")))"
+  (let ((tokens (semantic-find-nonterminal-by-token 'token tokstream))
+        token tsymb ttype tvalue bin bins)
+    (while tokens
+      (setq token  (car tokens)
+            tokens (cdr tokens)
+            tsymb  (semantic-bnf-token-name-symbol token)
+            ttype  (intern (semantic-bnf-token-token-type token))
+            tvalue (semantic-bnf-token-token-value token)
+            bin    (assq ttype bins))
+      (if bin
+          (setcdr bin (cons (cons tsymb tvalue) (cdr bin)))
+        (setq bins (cons (list ttype (cons tsymb tvalue)) bins))))
+    bins))
+
+(defun semantic-bnf-find-terminal-assocs (tokstream)
+  "Return terminals associativity from TOKSTREAM.
+This is a list of elements of the form: (ASSOC-TYPE . TERMS) where
+ASSOC-TYPE is one of 'nonassoc, 'left or 'right.  And TERMS is a list
+of terminal symbols.  Elements are in the same order as the
+corresponding %nonassoc, %left and %right statements in the BNF file."
+  (let ((tokens (semantic-find-nonterminal-by-token
+                 'assoc tokstream))
+        assocs terms type)
+    (while tokens
+      (setq type (intern (semantic-token-name (car tokens)))
+            terms (mapcar #'intern (semantic-bnf-token-assoc-terms