blob: dbbf04abf3317c74d5d22216f91fcd698ea3a712 [file] [log] [blame]
%{
/* -----------------------------------------------------------------------------
* parser.yxx
*
* YACC parser for SWIG1.1. This grammar is a broken subset of C/C++.
* This file is in the process of being deprecated.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1998-2000. The University of Chicago
* Copyright (C) 1995-1998. The University of Utah and The Regents of the
* University of California.
*
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
#define yylex yylex
static char cvsroot[] = "$Header$";
extern "C" int yylex();
void yyerror (char *s);
extern int line_number;
extern int start_line;
extern void skip_brace(void);
extern void skip_define(void);
extern void skip_decl(void);
extern int skip_cond(int);
extern void skip_to_end(void);
extern void skip_template(void);
extern void scanner_check_typedef(void);
extern void scanner_ignore_typedef(void);
extern void scanner_clear_start(void);
extern void start_inline(char *, int);
extern void swig_pragma(char *, char *);
char *typemap_lang = 0;
#include "internal.h"
extern "C" {
#include "preprocessor.h"
}
#ifdef NEED_ALLOC
void *alloca(unsigned n) {
return((void *) malloc(n));
}
#else
// This redefinition is apparently needed on a number of machines,
// particularly HPUX
#undef alloca
#define alloca malloc
#endif
// Initialization flags. These indicate whether or not certain
// features have been initialized. These were added to allow
// interface files without the block (required in previous
// versions).
static int module_init = 0; /* Indicates whether the %module name was given */
static int lang_init = 0; /* Indicates if the language has been initialized */
static int i;
int Error = 0;
static char temp_name[128];
static SwigType *temp_typeptr, *temp_type = 0;
static char yy_rename[256];
static int Rename_true = 0;
static SwigType *Active_type = 0; // Used to support variable lists
static int Active_extern = 0; // Whether or not list is external
static int Active_static = 0;
static SwigType *Active_typedef = 0; // Used for typedef lists
static int InArray = 0; // Used when an array declaration is found
static DOHString *ArrayString = 0; // Array type attached to parameter names
static DOHString *ArrayBackup = 0;
static char *DefArg = 0; // Default argument hack
static String *ConstChar = 0; // Used to store raw character constants
static ParmList *tm_parm = 0; // Parameter list used to hold typemap parameters
static DOHHash *name_hash = 0; // Hash table containing renamings
char *objc_construct = (char *) "new"; // Objective-C constructor
char *objc_destruct = (char *) "free"; // Objective-C destructor
static DOHHash *symbols = 0;
/* Some macros for building constants */
#define E_BINARY(TARGET, SRC1, SRC2, OP) \
TARGET = (char *) malloc(strlen(SRC1) + strlen(SRC2) +strlen(OP)+1);\
sprintf(TARGET,"%s%s%s",SRC1,OP,SRC2);
/* C++ modes */
#define CPLUS_PUBLIC 1
#define CPLUS_PRIVATE 2
#define CPLUS_PROTECTED 3
int cplus_mode;
// Declarations of some functions for handling C++
extern void cplus_open_class(char *name, char *rname, char *ctype);
extern void cplus_member_func(char *, char *, SwigType *, ParmList *, int);
extern void cplus_constructor(char *, char *, ParmList *);
extern void cplus_destructor(char *, char *);
extern void cplus_variable(char *, char *, SwigType *);
extern void cplus_static_func(char *, char *, SwigType *, ParmList *);
extern void cplus_declare_const(char *, char *, SwigType *, char *);
extern void cplus_class_close(char *);
extern void cplus_inherit(int, char **);
extern void cplus_cleanup(void);
extern void cplus_static_var(char *, char *, SwigType *);
extern void cplus_register_type(char *);
extern void cplus_register_scope(void *);
extern void cplus_inherit_scope(int, char **);
extern void cplus_add_pragma(char *, char *, char *);
extern void cplus_set_class(char *);
extern void cplus_unset_class();
extern void cplus_abort();
void parser_init() {
ArrayString = NewString("");
temp_type = NewString("");
}
static void my_cplus_declare_const(char *name, char *iname, SwigType *type, char *value) {
String *tval;
if (value) {
tval = NewStringf("%(escape)s",value);
cplus_declare_const(name,iname,type,Char(tval));
Delete(tval);
} else {
cplus_declare_const(name,iname,type,value);
}
}
static TMParm *NewTMParm() {
TMParm *tmp = (TMParm *) malloc(sizeof(TMParm));
tmp->next = 0;
return tmp;
}
static void add_pointers(SwigType *t, int npointer) {
int i;
for (i = 0; i < npointer; i++) {
SwigType_add_pointer(t);
}
}
// Emit an external function declaration
static void emit_extern_func(char *decl, SwigType *t, ParmList *L, int extern_type, DOHFile *f) {
switch(extern_type) {
case 0:
Printf(f,"%s", SwigType_str(t,0));
Printf(f,"%s(%s);\n", decl, ParmList_protostr(L));
break;
case 1:
Printf(f,"extern %s", SwigType_str(t,0));
Printf(f,"%s(%s);\n", decl, ParmList_protostr(L));
break;
case 2:
/* A C++ --- > C Extern */
Printf(f,"extern \"C\" %s", SwigType_str(t,0));
Printf(f,"%s(%s);\n", decl, ParmList_protostr(L));
break;
case 3:
Printf(f,"%s", SwigType_str(t,0));
Printf(f,"%s(%s)\n", decl, ParmList_str(L));
break;
default:
break;
}
}
// ----------------------------------------------------------------------
// static init_language()
//
// Initialize the target language.
// Does nothing if this function has already been called.
// ----------------------------------------------------------------------
static void init_language() {
if (!lang_init) {
lang->initialize();
}
lang_init = 1;
}
/* Add a symbol to the symbol table. Return -1 if it already exists */
int add_symbol(char *name) {
if (!symbols) symbols = NewHash();
if (Getattr(symbols,name)) return -1;
Setattr(symbols,name,name);
return 0;
}
// ----------------------------------------------------------------------
// int promote(int t1, int t2)
//
// Promote types (for constant expressions)
// ----------------------------------------------------------------------
int promote(int t1, int t2) {
if ((t1 == T_ERROR) || (t2 == T_ERROR)) return T_ERROR;
if ((t1 == T_DOUBLE) || (t2 == T_DOUBLE)) return T_DOUBLE;
if ((t1 == T_FLOAT) || (t2 == T_FLOAT)) return T_FLOAT;
if ((t1 == T_ULONG) || (t2 == T_ULONG)) return T_ULONG;
if ((t1 == T_LONG) || (t2 == T_LONG)) return T_LONG;
if ((t1 == T_UINT) || (t2 == T_UINT)) return T_UINT;
if ((t1 == T_INT) || (t2 == T_INT)) return T_INT;
if ((t1 == T_USHORT) || (t2 == T_USHORT)) return T_SHORT;
if ((t1 == T_SHORT) || (t2 == T_SHORT)) return T_SHORT;
if ((t1 == T_UCHAR) || (t2 == T_UCHAR)) return T_UCHAR;
if (t1 != t2) {
Printf(stderr,"%s : Line %d. Type mismatch in constant expression\n",
input_file, line_number);
FatalError();
}
return t1;
}
/* Generate the scripting name of an object. Takes %name directive into
account among other things */
static char *make_name(char *name) {
// Check to see if the name is in the hash
if (!name_hash) name_hash = NewHash();
char *nn = GetChar(name_hash,name);
if (nn) return nn; // Yep, return it.
if (Rename_true) {
Rename_true = 0;
return yy_rename;
} else {
// Now check to see if the name contains a $
if (strchr(name,'$')) {
static DOHString *temp = 0;
if (!temp) temp= NewString("");
Clear(temp);
Append(temp,name);
Replace(temp,"$","_S_",DOH_REPLACE_ANY);
return Char(temp);
} else {
return name;
}
}
}
// ----------------------------------------------------------------------
// create_function(int ext, char *name, DataType *t, ParmList *l)
//
// Creates a function and manages documentation creation. Really
// only used internally to the parser.
// ----------------------------------------------------------------------
void create_function(int ext, char *name, SwigType *t, ParmList *l) {
if (Active_static) return; // Static declaration. Ignore
init_language();
if (WrapExtern) return; // External wrapper file. Ignore
char *iname = make_name(name);
// Check if symbol already exists
if (add_symbol(iname)) {
Printf(stderr,"%s : Line %d. Function %s multiply defined (2nd definition ignored).\n",
input_file, line_number, iname);
} else {
// If extern, make an extern declaration in the SWIG wrapper file
if (ext)
emit_extern_func(name, t, l, ext, f_header);
else if (ForceExtern) {
emit_extern_func(name, t, l, 1, f_header);
}
// If this function has been declared inline, produce a function
lang->create_function(name, iname, t, l);
}
scanner_clear_start();
}
// -------------------------------------------------------------------
// create_variable(int ext, char *name, DataType *t)
//
// Create a link to a global variable.
// -------------------------------------------------------------------
void create_variable(int ext, char *name, SwigType *t) {
if (WrapExtern) return; // External wrapper file. Ignore
if (Active_static) return; // If static ignore
init_language();
char *iname = make_name(name);
if (add_symbol(iname)) {
Printf(stderr,"%s : Line %d. Variable %s multiply defined (2nd definition ignored).\n",
input_file, line_number, iname);
} else {
// If externed, output an external declaration
if (ext || ForceExtern) {
Printf(f_header,"extern %s;\n", SwigType_str(t,name));
}
// Now dump it out
lang->link_variable(name, iname, t);
}
scanner_clear_start();
}
// ------------------------------------------------------------------
// create_constant(char *name, DataType *type, char *value)
//
// Creates a new constant.
// -------------------------------------------------------------------
void create_constant(char *name, SwigType *type, char *value) {
if (Active_static) return;
if (WrapExtern) return; // External wrapper file. Ignore
init_language();
if (Rename_true) {
Printf(stderr,"%s : Line %d. %%name directive ignored with #define\n",
input_file, line_number);
Rename_true = 0;
}
if (SwigType_type(type) == T_CHAR) {
SwigType_add_pointer(type);
}
if (!value) value = Swig_copy_string(name);
sprintf(temp_name,"const:%s", name);
if (add_symbol(temp_name)) {
Printf(stderr,"%s : Line %d. Constant %s multiply defined. (2nd definition ignored)\n",
input_file, line_number, name);
} else {
if (!WrapExtern) { // Only wrap the constant if not in %extern mode
String *tval = NewStringf("%(escape)s",value);
lang->declare_const(name, name, type, Char(tval));
Delete(tval);
}
}
scanner_clear_start();
}
/* Print out array brackets */
void print_array() {
int i;
for (i = 0; i < InArray; i++)
Printf(stderr,"[]");
}
// Structures for handling code fragments built for nested classes
struct Nested {
DOHString *code; // Associated code fragment
int line; // line number where it starts
char *name; // Name associated with this nested class
SwigType *type; // Datatype associated with the name
Nested *next; // Next code fragment in list
};
// Some internal variables for saving nested class information
static Nested *nested_list = 0;
// Add a function to the nested list
static void add_nested(Nested *n) {
Nested *n1;
if (!nested_list) nested_list = n;
else {
n1 = nested_list;
while (n1->next) n1 = n1->next;
n1->next = n;
}
}
// Dump all of the nested class declarations to the inline processor
// However. We need to do a few name replacements and other munging
// first. This function must be called before closing a class!
static void dump_nested(char *parent) {
Nested *n,*n1;
n = nested_list;
int oldstatus = Status;
Status = STAT_READONLY;
while (n) {
char temp[256];
// Token replace the name of the parent class
Replace(n->code, "$classname", parent, DOH_REPLACE_ANY);
// Fix up the name of the datatype (for building typedefs and other stuff)
sprintf(temp,"%s_%s", parent,n->name);
Append(n->type,parent);
Append(n->type,"_");
Append(n->type,n->name);
// Add the appropriate declaration to the C++ processor
cplus_variable(n->name,(char *) 0, n->type);
// Dump the code to the scanner
Printf(f_header,"\n%s\n", Char(n->code));
start_inline(Char(n->code),n->line);
n1 = n->next;
Delete(n->code);
free(n);
n = n1;
}
nested_list = 0;
Status = oldstatus;
}
static DOHList *typelist(Parm *p) {
DOHList *l = NewList();
while (p) {
Append(l,Gettype(p));
p = Getnext(p);
}
return l;
}
%}
/* The type of each node in the parse tree
must be one of the elements of the union
given below. This is used to derive the
C++ declaration for "yylval" that appears
in parser.tab.h. */
%union {
char *id;
struct Declaration {
char *id;
int is_pointer;
int is_reference;
} decl;
struct InitList {
char **names;
int count;
} ilist;
struct DocList {
char **names;
char **values;
int count;
} dlist;
struct Define {
char *id;
int type;
} dtype;
struct {
char *filename;
int line;
int flag;
} loc;
SwigType *type;
Parm *p;
TMParm *tmparm;
ParmList *pl;
int ivalue;
};
%token <id> ID
%token <id> HBLOCK WRAPPER POUND RUNTIME HEADER
%token <id> STRING
%token <loc> INCLUDE IMPORT WEXTERN SWIGMACRO INSERT
%token <id> NUM_INT NUM_FLOAT CHARCONST NUM_UNSIGNED NUM_LONG NUM_ULONG
%token <ivalue> TYPEDEF
%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_TYPEDEF TYPE_RAW
%token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD
%token CONST STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
%token ILLEGAL CONSTANT
%token READONLY READWRITE NAME RENAME ADDMETHODS PRAGMA
%token ENUM
%token CLASS PRIVATE PUBLIC PROTECTED COLON STATIC VIRTUAL FRIEND OPERATOR THROW TEMPLATE
%token NATIVE INLINE
%token TEXT DOC_DISABLE DOC_ENABLE STYLE LOCALSTYLE
%token TYPEMAP EXCEPT ECHO NEW APPLY CLEAR DOCONLY
%token <ivalue> TITLE SECTION SUBSECTION SUBSUBSECTION
%token LESSTHAN GREATERTHAN
%token TYPES
/* Objective C tokens */
%token OC_INTERFACE OC_END OC_PUBLIC OC_PRIVATE OC_PROTECTED OC_CLASS OC_IMPLEMENT OC_PROTOCOL
%left OR
%left XOR
%left AND
%left LSHIFT RSHIFT
%left PLUS MINUS
%left STAR SLASH
%left UMINUS NOT LNOT
%left DCOLON
%type <ivalue> extern array array2;
%type <pl> parms ptail;
%type <p> parm parm_type;
%type <tmparm> typemap_parm tm_list tm_tail;
%type <id> pname cpptype base_specifier access_specifier typemap_name tm_method;
%type <type> type opt_signed opt_unsigned strict_type;
%type <decl> declaration nested_decl;
%type <ivalue> stars maybestars cpp_vend;
%type <ilist> initlist base_list inherit;
%type <dtype> definetype def_args;
%type <dtype> etype;
%type <dtype> expr;
%type <id> ename stylearg objc_inherit;
%type <dlist> stylelist styletail;
%type <type> objc_ret_type objc_arg_type;
%type <id> objc_protolist objc_separator;
%type <pl> objc_args;
%%
/* The productions of the grammar with their
associated semantic actions. */
program : command {
cplus_cleanup();
if (lang_init) {
lang->close();
}
}
;
command : command statement {
scanner_clear_start();
Error = 0;
}
| empty {
}
;
statement : INCLUDE STRING LBRACE {
$1.filename = Swig_copy_string(input_file);
$1.line = line_number;
input_file = Swig_copy_string($2);
line_number = 0;
} command RBRACE {
input_file = $1.filename;
line_number = $1.line;
}
/* %extern directive */
| WEXTERN STRING LBRACE {
$1.flag = WrapExtern;
WrapExtern = 1;
$1.filename = Swig_copy_string(input_file);
$1.line = line_number;
input_file = Swig_copy_string($2);
line_number = 0;
} command RBRACE {
input_file = $1.filename;
line_number = $1.line;
WrapExtern = $1.flag;
}
/* %import directive. Like %extern but calls out to a language module */
| IMPORT STRING LBRACE {
$1.flag = WrapExtern;
WrapExtern = 1;
$1.filename = Swig_copy_string(input_file);
$1.line = line_number;
input_file = Swig_copy_string($2);
line_number = 0;
lang->import($2);
} command RBRACE {
input_file = $1.filename;
line_number = $1.line;
WrapExtern = $1.flag;
}
| SWIGMACRO ID COMMA STRING COMMA NUM_INT LBRACE {
$1.filename = Swig_copy_string(input_file);
$1.line = line_number;
input_file = Swig_copy_string($4);
line_number = atoi($6) - 1;
} command RBRACE {
input_file = $1.filename;
line_number = $1.line;
}
/* An unknown C preprocessor statement. Just throw it away */
| POUND {
}
/* A variable declaration */
| extern type declaration array2 def_args {
init_language();
if (Active_type) Delete(Active_type);
Active_type = Copy($2);
Active_extern = $1;
add_pointers($2,$3.is_pointer);
if ($4 > 0) {
SwigType_push($2,ArrayString);
}
if ($3.is_reference) {
Printf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
FatalError();
} else {
if (SwigType_isconst($2)) {
create_constant($3.id, $2, $5.id);
} else {
create_variable($1,$3.id,$2);
}
}
Delete($2);
} stail { }
/* Global variable that smells like a function pointer */
| extern strict_type LPAREN STAR {
skip_decl();
Printf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
input_file, line_number);
}
/* A static variable declaration (Ignored) */
| STATIC type declaration array2 def_args {
Active_static = 1;
Delete($2);
} stail {
Active_static = 0;
}
/* Global variable that smells like a function pointer */
| STATIC strict_type LPAREN STAR {
skip_decl();
Printf(stderr,"%s : Line %d. Function pointers not currently supported.\n",
input_file, line_number);
}
/* A function declaration */
| extern type declaration LPAREN parms RPAREN cpp_const {
init_language();
if (Active_type) Delete(Active_type);
Active_type = Copy($2);
Active_extern = $1;
add_pointers($2,$3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
create_function($1, $3.id, $2, $5);
Delete($2);
Delete($5);
} stail { }
/* A function declaration with code after it */
| extern type declaration LPAREN parms RPAREN func_end {
init_language();
add_pointers($2,$3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
create_function($1, $3.id, $2, $5);
Delete($2);
Delete($5);
};
/* A function declared without any return datatype */
| extern declaration LPAREN parms RPAREN cpp_const {
init_language();
SwigType *t = NewString("int");
add_pointers(t,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference(t);
create_function($1,$2.id,t,$4);
Delete(t);
} stail { };
/* A static function declaration code after it */
| STATIC type declaration LPAREN parms RPAREN func_end {
if (Inline) {
if (strlen(Char(CCode))) {
init_language();
add_pointers($2, $3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
create_function(0, $3.id, $2, $5);
}
}
Delete($2);
Delete($5);
};
/* A function with an explicit inline directive. Not safe to use inside a %inline block */
| INLINE type declaration LPAREN parms RPAREN func_end {
init_language();
add_pointers($2,$3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
if (Inline) {
Printf(stderr,"%s : Line %d. Repeated %%inline directive.\n",input_file,line_number);
FatalError();
} else {
if (strlen(Char(CCode))) {
Printf(f_header,"static ");
emit_extern_func($3.id,$2,$5,3,f_header);
Printf(f_header,"%s\n",Char(CCode));
}
create_function(0, $3.id, $2, $5);
}
Delete($2);
Delete($5);
};
/* A static function declaration (ignored) */
| STATIC type declaration LPAREN parms RPAREN cpp_const {
Active_static = 1;
Delete($2);
Delete($5);
} stail {
Active_static = 0;
}
/* Enable Read-only mode */
| READONLY {
Status = Status | STAT_READONLY;
}
/* Enable Read-write mode */
| READWRITE {
Status = Status & ~STAT_READONLY;
}
/* New %name directive */
| NAME LPAREN ID RPAREN {
strcpy(yy_rename,$3);
Rename_true = 1;
}
/* and its string version */
| NAME LPAREN STRING RPAREN {
strcpy(yy_rename,$3);
Rename_true = 1;
}
/* %rename directive */
| RENAME ID ID SEMI {
if (!name_hash) name_hash = NewHash();
Setattr(name_hash,$2,$3);
}
/* and its string version */
| RENAME ID STRING SEMI {
if (!name_hash) name_hash = NewHash();
Setattr(name_hash,$2,$3);
}
/* %new directive */
| NEW {
NewObject = 1;
} statement {
NewObject = 0;
}
/* Empty name directive. No longer allowed */
| NAME LPAREN RPAREN {
Printf(stderr,"%s : Lind %d. Empty %%name() is no longer supported.\n",
input_file, line_number);
FatalError();
} cpp {
Rename_true = 0;
}
/* A native wrapper function */
| NATIVE LPAREN ID RPAREN extern ID SEMI {
if (!WrapExtern) {
init_language();
if (add_symbol($3)) {
Printf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n",
input_file, line_number, $3);
} else {
lang->add_native($3,$6,0,0);
}
}
}
| NATIVE LPAREN ID RPAREN extern type declaration LPAREN parms RPAREN SEMI {
if (!WrapExtern) {
init_language();
add_pointers($6,$7.is_pointer);
if (add_symbol($3)) {
Printf(stderr,"%s : Line %d. Name of native function %s conflicts with previous declaration (ignored)\n",
input_file, line_number, $3);
} else {
if ($5) {
emit_extern_func($7.id, $6, $9, $5, f_header);
}
lang->add_native($3,$7.id,$6,$9);
}
}
Delete($6);
Delete($9);
}
/* %title directive */
| TITLE STRING styletail {
}
/* %section directive */
| SECTION STRING styletail {
}
/* %subsection directive */
| SUBSECTION STRING styletail {
}
/* %subsubsection directive */
| SUBSUBSECTION STRING styletail {
}
| doc_enable { }
/* %text directive */
| TEXT HBLOCK {
}
| typedef_decl { }
/* Code insertion block */
| HBLOCK {
if (!WrapExtern) {
$1[strlen($1) - 1] = 0;
Printf(f_header, "%s\n", $1);
}
}
| HEADER HBLOCK {
if (!WrapExtern) {
$2[strlen($1) - 2] = 0;
Printf(f_header, "%s\n", $2);
}
}
/* Super-secret undocumented for people who really know what's going on feature */
| WRAPPER HBLOCK {
if (!WrapExtern) {
$2[strlen($2) - 1] = 0;
Printf(f_wrappers,"%s\n",$2);
}
}
| RUNTIME HBLOCK {
if (!WrapExtern) {
$2[strlen($2) - 1] = 0;
Printf(f_runtime,"%s\n", $2);
}
}
/* Initialization code */
| INIT HBLOCK {
if (!WrapExtern) {
$2[strlen($2) -1] = 0;
Printf(f_init,"%s\n", $2);
}
}
| INSERT LPAREN ID RPAREN STRING {
if (!WrapExtern) {
File *f = 0;
if (strcmp($3,"headers") == 0) {
f = f_header;
} else if (strcmp($3,"runtime") == 0) {
f = f_runtime;
} else if (strcmp($3,"wrappers") == 0) {
f = f_wrappers;
} else if (strcmp($3,"init") == 0) {
f = f_init;
}
if (!f) {
Printf(stderr,"%s:%d: Unknown target '%s' for %%insert directive.\n", input_file, line_number, $3);
} else {
if (Swig_insert_file($5,f) < 0) {
Printf(stderr,"%s:%d: Couldn't find '%s'. Possible installation problem.\n", input_file, line_number, $5);
SWIG_exit (EXIT_FAILURE);
}
}
}
}
/* Inline block */
| INLINE HBLOCK {
if (!WrapExtern) {
init_language();
$2[strlen($2) - 1] = 0;
Printf(f_header, "%s\n", $2);
{
/* Need to run through the preprocessor */
DOH *cpps;
DOH *s = NewString($2);
Setline(s,start_line);
Setfile(s,input_file);
Seek(s,0,SEEK_SET);
cpps = Preprocessor_parse(s);
start_inline(Char(cpps), start_line);
Delete(s);
Delete(cpps);
}
}
}
/* Echo mode */
| ECHO HBLOCK {
if (!WrapExtern) {
Printf(stderr,"%s\n", $2);
}
}
| ECHO STRING {
if (!WrapExtern) {
Printf(stderr,"%s\n", $2);
}
}
/* Disable code generation */
| DOCONLY {
}
/* Init directive--to avoid errors in other modules */
| INIT ID initlist {
Printf(stderr,"%s : Line %d. Warning. %%init directive is deprecated (ignored).\n", input_file,line_number);
for (i = 0; i < $3.count; i++)
if ($3.names[i]) free($3.names[i]);
free($3.names);
}
/* Module directive */
| MODULE ID initlist {
lang->set_module($2);
module_init = 1;
init_language();
for (i = 0; i < $3.count; i++)
if ($3.names[i]) free($3.names[i]);
free($3.names);
}
/* constant directive */
| CONSTANT ID definetype SEMI {
if (($3.type != T_ERROR) && ($3.type != T_SYMBOL)) {
init_language();
temp_typeptr = NewSwigType($3.type);
create_constant($2, temp_typeptr, $3.id);
Delete(temp_typeptr);
} else if ($3.type == T_SYMBOL) {
// Add a symbol to the SWIG symbol table
if (add_symbol($2)) {
Printf(stderr,"%s : Line %d. Warning. Symbol %s already defined.\n",
input_file,line_number, $2);
}
}
}
| CONSTANT LPAREN parm RPAREN ID def_args SEMI {
if (($6.type != T_ERROR) && ($6.type != T_SYMBOL)) {
init_language();
create_constant($5,Gettype($3), $6.id);
Delete($3);
}
}
/* Enumerations */
| extern ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE SEMI {
init_language();
if ($3) {
if (temp_type) Delete(temp_type);
temp_type = NewStringf("enum %s", $3);
/* String *ts = NewSwigType(T_INT); */
SwigType_typedef(temp_type,$3);
lang->add_typedef(temp_type,$3);
}
}
/* A typdef'd enum. Pretty common in C headers */
| TYPEDEF ENUM ename LBRACE { scanner_clear_start(); } enumlist RBRACE ID {
init_language();
if (temp_type) Delete(temp_type);
temp_type = NewStringf("enum %s", $3);
/* temp_type= NewSwigType(T_INT);*/
Active_typedef = Copy(temp_type);
if ($3) {
SwigType_typedef(temp_type,$3);
lang->add_typedef(temp_type,$3);
}
if ($8) {
SwigType_typedef(temp_type,$8);
lang->add_typedef(temp_type,$8);
}
} typedeflist { }
/* -----------------------------------------------------------------
typemap support.
These constructs are used to support type-maps.
----------------------------------------------------------------- */
/* Create a new typemap */
| TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
TMParm *p;
skip_brace();
p = $7;
while (p) {
if (strcmp($3,typemap_lang) == 0)
Swig_typemap_register($5,Gettype(p->p),Getname(p->p), CCode, p->args);
p = p->next;
}
free($3);
free($5);
}
/* Create a new typemap in current language */
| TYPEMAP LPAREN tm_method RPAREN tm_list LBRACE {
if (!typemap_lang) {
Printf(stderr,"SWIG internal error. No typemap_lang specified.\n");
Printf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
FatalError();
} else {
TMParm *p;
skip_brace();
p = $5;
while (p) {
Swig_typemap_register($3,Gettype(p->p),Getname(p->p), CCode, p->args);
p = p->next;
}
}
free($3);
}
/* Create a new typemap */
| TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list STRING {
TMParm *p;
p = $7;
while (p) {
if (strcmp($3,typemap_lang) == 0)
Swig_typemap_register($5,Gettype(p->p),Getname(p->p), $8, p->args);
p = p->next;
}
free($3);
free($5);
}
/* Create a new typemap in current language */
| TYPEMAP LPAREN tm_method RPAREN tm_list STRING {
if (!typemap_lang) {
Printf(stderr,"SWIG internal error. No typemap_lang specified.\n");
Printf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
FatalError();
} else {
TMParm *p;
p = $5;
while (p) {
Swig_typemap_register($3,Gettype(p->p),Getname(p->p), $6, p->args);
p = p->next;
}
}
free($3);
}
/* Clear a typemap */
| TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list SEMI {
TMParm *p;
p = $7;
while (p) {
if (strcmp($3,typemap_lang) == 0) {
Printf(stderr,"%s:%d. Warning. Typemap deletion is temporary disabled in this release.\n", input_file, line_number);
/* Swig_typemap_clear($5,Gettype(p->p),Getname(p->p)); */
}
p = p->next;
}
free($3);
free($5);
}
/* Clear a typemap in current language */
| TYPEMAP LPAREN tm_method RPAREN tm_list SEMI {
if (!typemap_lang) {
Printf(stderr,"SWIG internal error. No typemap_lang specified.\n");
Printf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
FatalError();
} else {
TMParm *p;
p = $5;
while (p) {
Printf(stderr,"%s:%d. Warning. Typemap deletion is temporary disabled in this release.\n", input_file, line_number);
/* Swig_typemap_clear($3,Gettype(p->p),Getname(p->p)); */
p = p->next;
}
}
free($3);
}
/* Copy a typemap */
| TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
TMParm *p;
p = $7;
while (p) {
if (strcmp($3,typemap_lang) == 0) {
Swig_typemap_copy($5,Gettype($9->p),Getname($9->p),Gettype(p->p),Getname(p->p));
}
p = p->next;
}
free($3);
free($5);
Delete($9->p);
free($9);
}
/* Copy typemap in current language */
| TYPEMAP LPAREN tm_method RPAREN tm_list EQUAL typemap_parm SEMI {
if (!typemap_lang) {
Printf(stderr,"SWIG internal error. No typemap_lang specified.\n");
Printf(stderr,"typemap on %s : Line %d. will be ignored.\n",input_file,line_number);
FatalError();
} else {
TMParm *p;
p = $5;
while (p) {
Swig_typemap_copy($3,Gettype($7->p),Getname($7->p),Gettype(p->p),Getname(p->p));
p = p->next;
}
}
free($3);
Delete($7->p);
free($7);
}
/* -----------------------------------------------------------------
apply and clear support (for typemaps)
----------------------------------------------------------------- */
| APPLY typemap_parm LBRACE tm_list RBRACE {
TMParm *p;
p = $4;
while(p) {
Swig_typemap_apply(Gettype($2->p),Getname($2->p),Gettype(p->p),Getname(p->p));
p = p->next;
}
free($4);
Delete($2->args);
free($2);
}
| CLEAR tm_list SEMI {
TMParm *p;
p = $2;
while (p) {
Printf(stderr,"%s:%d. Warning. %%clear directive is temporarily disabled in this release. Ignored.\n", input_file, line_number);
/* Swig_typemap_clear_apply(Gettype(p->p), Getname(p->p)); */
p = p->next;
}
}
/* -----------------------------------------------------------------
exception support
These constructs are used to define exceptions
----------------------------------------------------------------- */
/* An exception definition */
| EXCEPT LPAREN ID RPAREN LBRACE {
skip_brace();
if (strcmp($3,typemap_lang) == 0) {
Swig_except_register(CCode);
}
free($3);
}
/* A Generic Exception (no language specified */
| EXCEPT LBRACE {
skip_brace();
Swig_except_register(CCode);
}
/* Clear an exception */
| EXCEPT LPAREN ID RPAREN SEMI {
Swig_except_clear();
}
/* Generic clear */
| EXCEPT SEMI {
Swig_except_clear();
}
/* Miscellaenous stuff */
| SEMI { }
| cpp { }
| objective_c { }
| error {
if (!Error) {
{
static int last_error_line = -1;
if (last_error_line != line_number) {
Printf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
FatalError();
last_error_line = line_number;
// Try to make some kind of recovery.
skip_decl();
}
Error = 1;
}
}
}
/* A an extern C type declaration. Does nothing, but is ignored */
| EXTERN STRING LBRACE command RBRACE { }
/* Officially, this directive doesn't exist yet */
| pragma { }
/* %style directive. This applies to all current styles */
| STYLE stylelist {
}
/* %localstyle directive. This applies only to the current style */
| LOCALSTYLE stylelist {
}
/* %types directive. Used to register types with the type-checker */
| TYPES LPAREN parms RPAREN SEMI {
Parm *p = $3;
while (p) {
SwigType *t = Gettype(p);
SwigType_remember(t);
p = Getnext(p);
}
Delete($3);
}
/* Dcumentation disable/enable */
doc_enable : DOC_DISABLE {
}
/* %enabledoc directive */
| DOC_ENABLE {
}
;
/* Note : This really needs to be re-done */
/* A typedef with pointers */
typedef_decl : TYPEDEF type declaration {
init_language();
/* Add a new typedef */
Active_typedef = Copy($2);
add_pointers($2,$3.is_pointer);
SwigType_typedef($2, $3.id);
lang->add_typedef($2,$3.id);
cplus_register_type($3.id);
} typedeflist { };
/* A rudimentary typedef involving function pointers */
| TYPEDEF type LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
init_language();
/* Typedef'd pointer */
DOHList *l = typelist($8);
SwigType_add_function($2,l);
SwigType_add_pointer($2);
SwigType_typedef($2,$5);
lang->add_typedef($2,$5);
cplus_register_type($5);
Delete($2);
free($5);
Delete($8);
Delete(l);
}
/* A typedef involving function pointers again */
| TYPEDEF type stars LPAREN STAR pname RPAREN LPAREN parms RPAREN SEMI {
init_language();
add_pointers($2,$3);
DOHList *l = typelist($9);
SwigType_add_function($2,l);
SwigType_add_pointer($2);
SwigType_typedef($2,$6);
lang->add_typedef($2,$6);
cplus_register_type($6);
Delete($2);
free($6);
Delete($9);
Delete(l);
}
/* A typedef involving arrays */
| TYPEDEF type declaration array {
init_language();
Active_typedef = Copy($2);
// This datatype is going to be readonly
add_pointers($2,$3.is_pointer);
SwigType_push($2,ArrayString);
SwigType_typedef($2,$3.id);
lang->add_typedef($2,$3.id);
cplus_register_type($3.id);
} typedeflist { }
;
/* ------------------------------------------------------------------------
Typedef list
The following rules are used to manage typedef lists. Only a temporary
hack until the SWIG 2.0 parser gets online.
Active_typedef contains the datatype of the last typedef (if applicable)
------------------------------------------------------------------------ */
typedeflist : COMMA declaration typedeflist {
if (Active_typedef) {
SwigType *t;
t = Copy(Active_typedef);
add_pointers(t,$2.is_pointer);
SwigType_typedef(t,$2.id);
lang->add_typedef(t,$2.id);
cplus_register_type($2.id);
Delete(t);
}
}
| COMMA declaration array {
SwigType *t;
t = Copy(Active_typedef);
add_pointers(t, $2.is_pointer);
SwigType_push(t,ArrayString);
SwigType_typedef(t,$2.id);
lang->add_typedef(t,$2.id);
cplus_register_type($2.id);
Delete(t);
Printf(stderr,"%s : Line %d. Warning. Array type %s will be read-only without a typemap.\n",input_file,line_number, $2.id);
}
| empty { }
;
pragma : PRAGMA LPAREN ID COMMA ID stylearg RPAREN {
if (!WrapExtern)
lang->pragma($3,$5,$6);
Printf(stderr,"%s : Line %d. Warning. '%%pragma(lang,opt=value)' syntax is obsolete.\n",
input_file,line_number);
Printf(stderr," Use '%%pragma(lang) opt=value' instead.\n");
}
| PRAGMA ID stylearg {
if (!WrapExtern)
swig_pragma($2,$3);
}
| PRAGMA LPAREN ID RPAREN ID stylearg {
if (!WrapExtern)
lang->pragma($3,$5,$6);
}
;
/* Allow lists of variables and functions to be built up */
stail : SEMI { }
| COMMA declaration array2 def_args {
init_language();
temp_typeptr = Copy(Active_type);
add_pointers(temp_typeptr, $2.is_pointer);
if ($3 > 0) {
SwigType_push(temp_typeptr, ArrayString);
}
if ($2.is_reference) {
Printf(stderr,"%s : Line %d. Error. Linkage to C++ reference not allowed.\n", input_file, line_number);
FatalError();
} else {
if (SwigType_isconst(temp_typeptr)) {
create_constant($2.id, temp_typeptr, $4.id);
} else {
create_variable(Active_extern,$2.id, temp_typeptr);
}
}
Delete(temp_typeptr);
} stail { }
| COMMA declaration LPAREN parms RPAREN cpp_const {
init_language();
temp_typeptr = Copy(Active_type);
add_pointers(temp_typeptr, $2.is_pointer);
if ($2.is_reference) SwigType_add_reference(temp_typeptr);
create_function(Active_extern, $2.id, temp_typeptr, $4);
Delete(temp_typeptr);
Delete($4);
} stail { }
;
extern : EXTERN { $$ = 1; }
| empty {$$ = 0; }
| EXTERN STRING {
if (strcmp($2,"C") == 0) {
$$ = 2;
} else {
Printf(stderr,"%s : Line %d. Unrecognized extern type \"%s\" (ignored).\n", input_file, line_number, $2);
FatalError();
}
}
;
/* End of a function declaration. Allows C++ "const" directive and inline code */
func_end : cpp_const LBRACE { skip_brace(); }
/* | LBRACE { skip_brace(); } */
;
/* ------------------------------------------------------------------------------
Function parameter lists
------------------------------------------------------------------------------ */
parms : parm ptail {
SwigType *pt = Gettype($1);
if (SwigType_type(pt) != T_VOID) {
Setnext($1,$2);
$$ = $1;
} else {
$$ = $2;
}
}
| empty { $$ = 0; }
;
ptail : COMMA parm ptail {
Setnext($2,$3);
$$ = $2;
}
| empty { $$ = 0; }
;
parm : parm_type {
$$ = $1;
}
parm_type : type pname {
if (InArray) {
// Add array string to the type
SwigType_push($1, ArrayString);
}
$$ = NewParm($1,$2);
Setvalue($$,DefArg);
Delete($1);
free($2);
}
| type stars pname {
$$ = NewParm($1,$3);
add_pointers(Gettype($$), $2);
Setvalue($$,DefArg);
if (InArray) {
// Add array string to the type
SwigType_push(Gettype($$), ArrayString);
}
Delete($1);
free($3);
}
| type maybestars CONST pname {
$$ = NewParm($1,$4);
add_pointers(Gettype($$), $2);
SwigType_add_qualifier($$,(char*)"const");
Setvalue($$,DefArg);
Delete($1);
free($4);
}
| type maybestars AND pname {
$$ = NewParm($1,$4);
SwigType *pt = Gettype($$);
add_pointers(Gettype($$), $2);
SwigType_add_reference(pt);
Setvalue($$,DefArg);
if (!CPlusPlus) {
Printf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number);
}
Delete($1);
free($4);
}
| type LPAREN stars pname RPAREN LPAREN parms RPAREN {
$$ = NewParm($1,$4);
SwigType *pt = Gettype($$);
DOHList *l = typelist($7);
SwigType_add_function(pt,l);
add_pointers(pt,$3);
Setname($$,$4);
Delete($1);
free($4);
Delete($7);
Delete(l);
}
| PERIOD PERIOD PERIOD {
Printf(stderr,"%s : Line %d. Variable length arguments not supported (ignored).\n", input_file, line_number);
$$ = NewParm(NewSwigType(T_INT),(char *) "varargs");
FatalError();
}
;
pname : ID def_args {
$$ = $1;
InArray = 0;
if ($2.type == T_CHAR)
DefArg = Swig_copy_string(Char(ConstChar));
else
DefArg = Swig_copy_string($2.id);
if ($2.id) free($2.id);
}
| ID array {
$$ = $1;
InArray = $2;
DefArg = 0;
}
| array {
$$ = (char *) malloc(1);
$$[0] = 0;
InArray = $1;
DefArg = 0;
}
| empty { $$ = (char *) malloc(1);
$$[0] = 0;
InArray = 0;
DefArg = 0;
}
;
def_args : EQUAL definetype { $$ = $2; }
| EQUAL AND ID {
$$.id = (char *) malloc(strlen($3)+2);
$$.id[0] = '&';
strcpy(&$$.id[1], $3);
$$.type = T_USER;
}
| EQUAL LBRACE {
skip_brace();
$$.id = 0; $$.type = T_INT;
}
| COLON NUM_INT {
}
| empty {$$.id = 0; $$.type = T_INT;}
;
/* Declaration must be an identifier, possibly preceded by a * for pointer types */
declaration : ID { $$.id = $1;
$$.is_pointer = 0;
$$.is_reference = 0;
}
| stars ID {
$$.id = $2;
$$.is_pointer = $1;
$$.is_reference = 0;
}
| AND ID {
$$.id = $2;
$$.is_pointer = 0;
$$.is_reference = 1;
if (!CPlusPlus) {
Printf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number);
}
}
;
stars : STAR empty { $$ = 1; }
| STAR stars { $$ = $2 + 1;}
;
maybestars : empty { $$ = 0; }
| stars { $$ = $1; }
;
array : LBRACKET RBRACKET array2 {
$$ = $3 + 1;
SwigType_add_array(ArrayString,(char*)"");
}
| LBRACKET expr RBRACKET array2 {
$$ = $4 + 1;
SwigType_add_array(ArrayString,$2.id);
}
;
array2 : array {
$$ = $1;
}
| empty {
$$ = 0;
Clear(ArrayString);
}
;
/* Data type must be a built in type or an identifier for user-defined types
This type can be preceded by a modifier. */
type : TYPE_INT {
$$ = $1;
}
| TYPE_SHORT opt_int {
$$ = $1;
}
| TYPE_LONG opt_int {
$$ = $1;
}
| TYPE_LONG TYPE_LONG opt_int {
$$ = NewString("long long");
}
| TYPE_CHAR {
$$ = $1;
}
| TYPE_BOOL {
$$ = $1;
}
| TYPE_FLOAT {
$$ = $1;
}
| TYPE_DOUBLE {
$$ = $1;
}
| TYPE_VOID {
$$ = $1;
}
| TYPE_SIGNED opt_signed {
if ($2) $$ = $2;
else $$ = $1;
}
| TYPE_UNSIGNED opt_unsigned {
if ($2) $$ = $2;
else $$ = $1;
}
| TYPE_TYPEDEF objc_protolist {
$$ = $1;
$$ = NewStringf("%s%s",$1,$2);
Delete($1);
}
| ID objc_protolist {
$$ = NewStringf("%s%s",$1,$2);
free($1);
}
| CONST type {
$$ = $2;
SwigType_add_qualifier($$,(char*)"const");
}
| cpptype ID {
$$ = NewStringf("%s %s",$1,$2);
}
| ID DCOLON ID {
$$ = NewStringf("%s::%s", $1,$3);
}
/* This declaration causes a shift-reduce conflict. Unresolved for now */
| DCOLON ID {
$$ = NewString($2);
}
| ENUM ID {
$$ = NewStringf("enum %s", $2);
}
| TYPE_RAW {
$$ = $1;
}
;
/* type specification without ID symbol. Used in some cases to prevent shift-reduce conflicts */
strict_type : TYPE_INT {
$$ = $1;
}
| TYPE_SHORT opt_int {
$$ = $1;
}
| TYPE_LONG opt_int {
$$ = $1;
}
| TYPE_LONG TYPE_LONG opt_int {
$$ = NewString("long long");
}
| TYPE_CHAR {
$$ = $1;
}
| TYPE_BOOL {
$$ = $1;
}
| TYPE_FLOAT {
$$ = $1;
}
| TYPE_DOUBLE {
$$ = $1;
}
| TYPE_VOID {
$$ = $1;
}
| TYPE_SIGNED opt_signed {
if ($2) $$ = $2;
else $$ = $1;
}
| TYPE_UNSIGNED opt_unsigned {
if ($2) $$ = $2;
else $$ = $1;
}
| TYPE_TYPEDEF objc_protolist {
$$ = NewStringf("%s%s", $1,$2);
}
| CONST type {
$$ = $2;
SwigType_add_qualifier($$,(char*)"const");
}
| cpptype ID {
$$ = NewStringf("%s %s", $1, $2);
}
| TYPE_RAW {
$$ = $1;
}
;
/* Optional signed types */
opt_signed : empty {
$$ = 0;
}
| TYPE_INT {
$$ = $1;
}
| TYPE_SHORT opt_int {
$$ = $1;
}
| TYPE_LONG opt_int {
$$ = $1;
}
| TYPE_LONG TYPE_LONG opt_int {
$$ = NewString("long long");
}
| TYPE_CHAR {
$$ = NewString("signed char");
}
;
/* Optional unsigned types */
opt_unsigned : empty {
$$ = 0;
}
| TYPE_INT {
$$ = NewString("unsigned int");
}
| TYPE_SHORT opt_int {
$$ = NewString("unsigned short");
}
| TYPE_LONG opt_int {
$$ = NewString("unsigned long");
}
| TYPE_LONG TYPE_LONG opt_int {
$$ = NewString("unsigned long long");
}
| TYPE_CHAR {
$$ = NewString("unsigned char");
}
;
opt_int : TYPE_INT { }
| empty { }
;
definetype : { scanner_check_typedef(); } expr {
$$ = $2;
scanner_ignore_typedef();
if (ConstChar) Delete(ConstChar);
ConstChar = 0;
}
| STRING {
$$.id = $1;
$$.type = T_CHAR;
if (ConstChar) Delete(ConstChar);
ConstChar = NewStringf("\"%(escape)s\"",$1);
}
| CHARCONST {
$$.id = $1;
$$.type = T_CHAR;
if (ConstChar) Delete(ConstChar);
ConstChar = NewStringf("'%(escape)s'", $1);
}
;
/* Initialization function links */
initlist : initlist COMMA ID {
$$ = $1;
$$.names[$$.count] = Swig_copy_string($3);
$$.count++;
$$.names[$$.count] = (char *) 0;
}
| empty {
$$.names = (char **) malloc(NI_NAMES*sizeof(char*));
$$.count = 0;
for (i = 0; i < NI_NAMES; i++)
$$.names[i] = (char *) 0;
}
;
/* Some stuff for handling enums */
ename : ID { $$ = $1; }
| empty { $$ = (char *) 0;}
;
/* SWIG enum list.
*/
enumlist : enumlist COMMA edecl {}
| edecl {}
;
edecl : ID {
temp_typeptr = NewSwigType(T_INT);
create_constant($1, temp_typeptr, $1);
Delete(temp_typeptr);
}
| ID EQUAL { scanner_check_typedef();} etype {
temp_typeptr = NewSwigType($4.type);
// Use enum name instead of value
// OLD create_constant($1, temp_typeptr, $4.id);
if ($4.type == T_CHAR)
create_constant($1,temp_typeptr, $4.id);
else
create_constant($1, temp_typeptr, $1);
Delete(temp_typeptr);
scanner_ignore_typedef();
}
| empty { }
;
etype : expr {
$$ = $1;
if (($$.type != T_INT) && ($$.type != T_UINT) &&
($$.type != T_LONG) && ($$.type != T_ULONG) &&
($$.type != T_SHORT) && ($$.type != T_USHORT) &&
($$.type != T_SCHAR) && ($$.type != T_UCHAR)) {
Printf(stderr,"%s : Lind %d. Type error. Expecting an int\n",
input_file, line_number);
FatalError();
}
}
| CHARCONST {
$$.id = $1;
$$.type = T_INT;
}
;
/* Arithmetic expressions. Used for constants and other cool stuff.
Really, we're not doing anything except string concatenation, but
this does allow us to parse many constant declarations.
*/
expr : NUM_INT {
$$.id = $1;
$$.type = T_INT;
}
| NUM_FLOAT {
$$.id = $1;
$$.type = T_DOUBLE;
}
| NUM_UNSIGNED {
$$.id = $1;
$$.type = T_UINT;
}
| NUM_LONG {
$$.id = $1;
$$.type = T_LONG;
}
| NUM_ULONG {
$$.id = $1;
$$.type = T_ULONG;
}
| SIZEOF LPAREN type RPAREN {
$$.id = (char *) malloc(Len($3)+9);
sprintf($$.id,"sizeof(%s)", Char($3));
$$.type = T_INT;
}
| LPAREN strict_type RPAREN expr %prec UMINUS {
$$.id = (char *) malloc(strlen($4.id)+Len($2)+3);
sprintf($$.id,"(%s)%s",Char($2),$4.id);
$$.type = SwigType_type($2);
}
| ID {
$$.id = $1;
$$.type = T_INT;
}
| ID DCOLON ID {
$$.id = (char *) malloc(strlen($1)+strlen($3)+3);
sprintf($$.id,"%s::%s",$1,$3);
$$.type = T_INT;
free($1);
free($3);
}
| expr PLUS expr {
E_BINARY($$.id,$1.id,$3.id,"+");
$$.type = promote($1.type,$3.type);
free($1.id);
free($3.id);
}
| expr MINUS expr {
E_BINARY($$.id,$1.id,$3.id,"-");
$$.type = promote($1.type,$3.type);
free($1.id);
free($3.id);
}
| expr STAR expr {
E_BINARY($$.id,$1.id,$3.id,"*");
$$.type = promote($1.type,$3.type);
free($1.id);
free($3.id);
}
| expr SLASH expr {
E_BINARY($$.id,$1.id,$3.id,"/");
$$.type = promote($1.type,$3.type);
free($1.id);
free($3.id);
}
| expr AND expr {
E_BINARY($$.id,$1.id,$3.id,"&");
$$.type = promote($1.type,$3.type);
if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
Printf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
FatalError();
}
free($1.id);
free($3.id);
}
| expr OR expr {
E_BINARY($$.id,$1.id,$3.id,"|");
$$.type = promote($1.type,$3.type);
if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
Printf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
FatalError();
}
$$.type = T_INT;
free($1.id);
free($3.id);
}
| expr XOR expr {
E_BINARY($$.id,$1.id,$3.id,"^");
$$.type = promote($1.type,$3.type);
if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
Printf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
FatalError();
}
$$.type = T_INT;
free($1.id);
free($3.id);
}
| expr LSHIFT expr {
E_BINARY($$.id,$1.id,$3.id,"<<");
$$.type = promote($1.type,$3.type);
if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
Printf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
FatalError();
}
$$.type = T_INT;
free($1.id);
free($3.id);
}
| expr RSHIFT expr {
E_BINARY($$.id,$1.id,$3.id,">>");
$$.type = promote($1.type,$3.type);
if (($1.type == T_DOUBLE) || ($3.type == T_DOUBLE)) {
Printf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
FatalError();
}
$$.type = T_INT;
free($1.id);
free($3.id);
}
| MINUS expr %prec UMINUS {
$$.id = (char *) malloc(strlen($2.id)+2);
sprintf($$.id,"-%s",$2.id);
$$.type = $2.type;
free($2.id);
}
| NOT expr {
$$.id = (char *) malloc(strlen($2.id)+2);
sprintf($$.id,"~%s",$2.id);
if ($2.type == T_DOUBLE) {
Printf(stderr,"%s : Line %d. Type error in constant expression (expecting integers).\n", input_file, line_number);
FatalError();
}
$$.type = $2.type;
free($2.id);
}
| LPAREN expr RPAREN {
$$.id = (char *) malloc(strlen($2.id)+3);
sprintf($$.id,"(%s)", $2.id);
$$.type = $2.type;
free($2.id);
}
;
/****************************************************************/
/* C++ Support */
/****************************************************************/
cpp : cpp_class { }
| cpp_other {}
;
cpp_class :
/* A class/struct/union definition */
extern cpptype ID inherit LBRACE {
char *iname;
init_language();
SwigType_new_scope();
sprintf(temp_name,"CPP_CLASS:%s\n",$3);
if (add_symbol(temp_name)) {
Printf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $3);
FatalError();
}
if ((!CPlusPlus) && (strcmp($2,"class") == 0))
Printf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
iname = make_name($3);
if (iname == $3)
cplus_open_class($3, 0, $2);
else
cplus_open_class($3, iname, $2);
if (strcmp($2,"class") == 0)
cplus_mode = CPLUS_PRIVATE;
else
cplus_mode = CPLUS_PUBLIC;
scanner_clear_start();
nested_list = 0;
// Merge in scope from base classes
cplus_inherit_scope($4.count,$4.names);
} cpp_members RBRACE {
if ($4.names) {
if (strcmp($2,"union") != 0)
cplus_inherit($4.count, $4.names);
else {
Printf(stderr,"%s : Line %d. Inheritance not allowed for unions.\n",input_file, line_number);
FatalError();
}
}
// Clean up the inheritance list
if ($4.names) {
int j;
for (j = 0; j < $4.count; j++) {
if ($4.names[j]) free($4.names[j]);
}
free($4.names);
}
// Dumped nested declarations (if applicable)
dump_nested($3);
// Save and collapse current scope
SwigType_set_scope_name($3);
cplus_register_scope(SwigType_pop_scope());
cplus_class_close((char *) 0);
cplus_mode = CPLUS_PUBLIC;
}
/* Class with a typedef */
| TYPEDEF cpptype ID inherit LBRACE {
char *iname;
init_language();
SwigType_new_scope();
sprintf(temp_name,"CPP_CLASS:%s\n",$3);
if (add_symbol(temp_name)) {
Printf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $3);
FatalError();
}
if ((!CPlusPlus) && (strcmp($2,"class") == 0))
Printf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
iname = make_name($3);
if ($3 == iname)
cplus_open_class($3, 0, $2);
else
cplus_open_class($3, iname, $2);
if (strcmp($2,"class") == 0)
cplus_mode = CPLUS_PRIVATE;
else
cplus_mode = CPLUS_PUBLIC;
scanner_clear_start();
nested_list = 0;
// Merge in scope from base classes
cplus_inherit_scope($4.count,$4.names);
} cpp_members RBRACE declaration {
if ($4.names) {
if (strcmp($2,"union") != 0)
cplus_inherit($4.count, $4.names);
else {
Printf(stderr,"%s : Line %d. Inheritance not allowed for unions.\n",input_file, line_number);
FatalError();
}
}
// Create a datatype for correctly processing the typedef
Active_typedef = NewStringf("%s %s", $2, $3);
// Clean up the inheritance list
if ($4.names) {
int j;
for (j = 0; j < $4.count; j++) {
if ($4.names[j]) free($4.names[j]);
}
free($4.names);
}
if ($9.is_pointer > 0) {
Printf(stderr,"%s : Line %d. typedef struct { } *id not supported properly. Winging it...\n", input_file, line_number);
}
// Create dump nested class code
if ($9.is_pointer > 0) {
dump_nested($3);
} else {
dump_nested($9.id);
}
// Collapse any datatypes created in the the class
SwigType_set_scope_name($3);
cplus_register_scope(SwigType_pop_scope());
if ($9.is_pointer > 0) {
cplus_class_close($3);
} else {
cplus_class_close($9.id);
}
// Create a typedef in global scope
if ($9.is_pointer == 0) {
SwigType_typedef(Active_typedef,$9.id);
lang->add_typedef(Active_typedef,$9.id);
} else {
SwigType *t = Copy(Active_typedef);
add_pointers(t,$9.is_pointer);
SwigType_typedef(t,$9.id);
lang->add_typedef(t,$9.id);
cplus_register_type($9.id);
Delete(t);
}
cplus_mode = CPLUS_PUBLIC;
} typedeflist { };
/* An unnamed struct with a typedef */
| TYPEDEF cpptype LBRACE {
char *iname;
init_language();
SwigType_new_scope();
if ((!CPlusPlus) && (strcmp($2,"class") == 0))
Printf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
iname = make_name((char*)"");
if (strlen(iname))
cplus_open_class((char *)"", iname, $2);
else
cplus_open_class((char *) "",0,$2);
if (strcmp($2,"class") == 0)
cplus_mode = CPLUS_PRIVATE;
else
cplus_mode = CPLUS_PUBLIC;
scanner_clear_start();
nested_list = 0;
} cpp_members RBRACE declaration {
if ($7.is_pointer > 0) {
Printf(stderr,"%s : Line %d. typedef %s {} *%s not supported correctly. Will be ignored.\n", input_file, line_number, $2, $7.id);
cplus_abort();
} else {
sprintf(temp_name,"CPP_CLASS:%s\n",$7.id);
if (add_symbol(temp_name)) {
Printf(stderr,"%s : Line %d. Error. %s %s is multiply defined.\n", input_file, line_number, $2, $7.id);
FatalError();
}
}
// Create a datatype for correctly processing the typedef
Active_typedef = NewString($7.id);
// Dump nested classes
if ($7.is_pointer == 0)
dump_nested($7.id);
// Go back to previous scope
cplus_register_scope(SwigType_pop_scope());
if ($7.is_pointer == 0)
cplus_class_close($7.id);
cplus_mode = CPLUS_PUBLIC;
} typedeflist { }
;
cpp_other :/* A dummy class name */
extern cpptype ID SEMI {
char *iname;
init_language();
iname = make_name($3);
lang->cpp_class_decl($3,iname,$2);
}
/* A static C++ member function (declared out of scope) */
| extern type declaration DCOLON ID LPAREN parms RPAREN SEMI {
init_language();
if (!CPlusPlus)
Printf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
add_pointers($2,$3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
// Fix up the function name
sprintf(temp_name,"%s::%s",$3.id,$5);
if (!Rename_true) {
Rename_true = 1;
sprintf(yy_rename,"%s_%s",$3.id,$5);
}
create_function($1, temp_name, $2, $7);
Delete($2);
Delete($7);
}
/* A static C++ member data */
| extern type declaration DCOLON ID SEMI {
init_language();
if (!CPlusPlus)
Printf(stderr,"%s : Line %d. *** WARNING ***. C++ mode is disabled (enable using -c++)\n", input_file, line_number);
add_pointers($2,$3.is_pointer);
// Fix up the function name
sprintf(temp_name,"%s::%s",$3.id,$5);
if (!Rename_true) {
Rename_true = 1;
sprintf(yy_rename,"%s_%s",$3.id,$5);
}
create_variable($1,temp_name, $2);
Delete($2);
}
/* Operator overloading catch */
| extern type declaration DCOLON OPERATOR {
Printf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
skip_decl();
Delete($2);
}
/* Template catch */
| TEMPLATE {
Printf(stderr,"%s : Line %d. Templates not currently supported (ignored).\n",
input_file, line_number);
skip_decl();
}
/* %addmethods directive used outside of a class definition */
| ADDMETHODS ID LBRACE {
cplus_mode = CPLUS_PUBLIC;
cplus_set_class($2);
scanner_clear_start();
AddMethods = 1;
} added_members RBRACE {
cplus_unset_class();
AddMethods = 0;
}
;
added_members : cpp_member cpp_members { }
| objc_method objc_methods { }
| empty { }
;
cpp_members : cpp_member cpp_members {}
| ADDMETHODS LBRACE {
AddMethods = 1;
} cpp_members RBRACE {
AddMethods = 0;
} cpp_members { }
| error {
skip_decl();
{
static int last_error_line = -1;
if (last_error_line != line_number) {
Printf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
FatalError();
last_error_line = line_number;
}
}
} cpp_members { }
| empty { }
;
cpp_member : type declaration LPAREN parms RPAREN cpp_end {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
add_pointers($1,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference($1);
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_member_func($2.id, iname, $1,$4,0);
}
scanner_clear_start();
Delete($1);
Delete($4);
}
/* Virtual member function */
| VIRTUAL type declaration LPAREN parms RPAREN cpp_vend {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
add_pointers($2,$3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
iname = make_name($3.id);
if (iname == $3.id) iname = 0;
cplus_member_func($3.id,iname,$2,$5,$7 ? PURE_VIRTUAL : PLAIN_VIRTUAL);
}
scanner_clear_start();
Delete($2);
Delete($5);
}
/* Possibly a constructor */
| ID LPAREN parms RPAREN ctor_end {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
iname = make_name($1);
if (iname == $1) iname = 0;
cplus_constructor($1,iname, $3);
}
scanner_clear_start();
Delete($3);
}
/* A destructor (hopefully) */
| NOT ID LPAREN parms RPAREN cpp_end {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
iname = make_name($2);
if (iname == $2) iname = 0;
cplus_destructor($2,iname);
}
scanner_clear_start();
Delete($4);
}
/* A virtual destructor */
| VIRTUAL NOT ID LPAREN RPAREN cpp_end {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
iname = make_name($3);
if (iname == $3) iname = 0;
cplus_destructor($3,iname);
}
scanner_clear_start();
}
/* Member data */
| type declaration def_args {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
if (Active_type) Delete(Active_type);
Active_type = Copy($1);
add_pointers($1,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference($1);
if (SwigType_isconst($1)) {
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
my_cplus_declare_const($2.id,iname, $1, $3.id);
} else {
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_variable($2.id,iname,$1);
}
}
scanner_clear_start();
Delete($1);
} cpp_tail { }
| type declaration array def_args {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
if (Active_type) Delete(Active_type);
Active_type = Copy($1);
add_pointers($1, $2.is_pointer);
if ($2.is_reference) SwigType_add_reference($1);
SwigType_push($1,ArrayString);
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_variable($2.id,iname,$1);
}
scanner_clear_start();
Delete($1);
}
/* Static Member data */
| STATIC type declaration {
char *iname;
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
add_pointers($2,$3.is_pointer);
iname = make_name($3.id);
if (iname == $3.id) iname = 0;
cplus_static_var($3.id,iname,$2);
if (Active_type) Delete(Active_type);
Active_type = Copy($2);
}
scanner_clear_start();
Delete($2);
} cpp_tail { }
/* Static member function */
| STATIC type declaration LPAREN parms RPAREN cpp_end {
char *iname;
add_pointers($2,$3.is_pointer);
if ($3.is_reference) SwigType_add_reference($2);
if (cplus_mode == CPLUS_PUBLIC) {
iname = make_name($3.id);
if (iname == $3.id) iname = 0;
cplus_static_func($3.id, iname, $2, $5);
}
scanner_clear_start();
Delete($2);
Delete($5);
}
/* Turn on public: mode */
| PUBLIC COLON {
cplus_mode = CPLUS_PUBLIC;
scanner_clear_start();
}
/* Turn on private: mode */
| PRIVATE COLON {
cplus_mode = CPLUS_PRIVATE;
scanner_clear_start();
}
/* Turn on protected mode */
| PROTECTED COLON {
cplus_mode = CPLUS_PROTECTED;
scanner_clear_start();
}
/* This is the new style rename */
| NAME LPAREN ID RPAREN {
strcpy(yy_rename,$3);
Rename_true = 1;
}
/* New mode */
| NEW {
NewObject = 1;
} cpp_member {
NewObject = 0;
}
/* C++ Enum */
| ENUM ename LBRACE {scanner_clear_start();} cpp_enumlist RBRACE SEMI {
// if ename was supplied. Install it as a new integer datatype.
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
if ($2) {
cplus_register_type($2);
if (temp_type) Delete(temp_type);
/* temp_type = NewSwigType(T_INT); */
temp_type = NewStringf("enum %s",$2);
SwigType_typedef(temp_type,$2);
lang->add_typedef(temp_type,$2);
}
}
}
| READONLY {
Status = Status | STAT_READONLY;
scanner_clear_start();
}
| READWRITE {
Status = Status & ~(STAT_READONLY);
scanner_clear_start();
}
/* A friend : Illegal */
| FRIEND {
Printf(stderr,"%s : Line %d. Friends are not allowed--members only! (ignored)\n", input_file, line_number);
skip_decl();
scanner_clear_start();
}
/* An operator: Illegal */
| type type_extra OPERATOR {
Printf(stderr,"%s : Line %d. Operator overloading not supported (ignored).\n", input_file, line_number);
skip_decl();
scanner_clear_start();
}
/* A typedef inside a class */
| typedef_decl { }
/* Pragma directive */
| cpp_pragma {
scanner_clear_start();
}
cpp_pragma : PRAGMA ID stylearg {
if (!WrapExtern) { }
}
| PRAGMA LPAREN ID RPAREN ID stylearg {
if (!WrapExtern)
cplus_add_pragma($3,$5,$6);
}
;
/* ----------------------------------------------------------------------
Nested structure. This is a big ugly "hack". If we encounter
a nested structure, we're going to grab the text of its definition and
feed it back into the scanner. In the meantime, we need to grab
variable declaration information and generate the associated wrapper
code later. Yikes!
This really only works in a limited sense. Since we use the
code attached to the nested class to generate both C/C++ code,
it can't have any SWIG directives in it. It also needs to be parsable
by SWIG or this whole thing is going to puke.
---------------------------------------------------------------------- */
/* A struct sname { } id; declaration */
| cpptype ID LBRACE { start_line = line_number; skip_brace();
} nested_decl SEMI {
if (cplus_mode == CPLUS_PUBLIC) {
cplus_register_type($2);
if ($5.id) {
if (strcmp($1,"class") == 0) {
Printf(stderr,"%s : Line %d. Warning. Nested classes not currently supported (ignored).\n", input_file, line_number);
/* Generate some code for a new class */
} else {
Nested *n = (Nested *) malloc(sizeof(Nested));
n->code = NewString("");
Printv(n->code, "typedef ", $1, " ",
Char(CCode), " $classname_", $5.id, ";\n", 0);
n->name = Swig_copy_string($5.id);
n->line = start_line;
n->type = NewString("");
add_pointers(n->type, $5.is_pointer);
if ($5.is_reference) SwigType_add_reference(n->type);
n->next = 0;
add_nested(n);
}
}
}
}
/* An unnamed structure definition */
| cpptype LBRACE { start_line = line_number; skip_brace();
} declaration SEMI {
if (cplus_mode == CPLUS_PUBLIC) {
if (strcmp($1,"class") == 0) {
Printf(stderr,"%s : Line %d. Warning. Nested classes not currently supported (ignored)\n", input_file, line_number);
/* Generate some code for a new class */
} else {
/* Generate some code for a new class */
Nested *n = (Nested *) malloc(sizeof(Nested));
n->code = NewString("");
Printv(n->code, "typedef ", $1, " " ,
Char(CCode), " $classname_", $4.id, ";\n",0);
n->name = Swig_copy_string($4.id);
n->line = start_line;
n->type = NewString("");
add_pointers(n->type, $4.is_pointer);
if ($4.is_reference) SwigType_add_reference(n->type);
n->next = 0;
add_nested(n);
}
}
}
/* An empty class declaration */
| cpptype ID SEMI {
if (cplus_mode == CPLUS_PUBLIC) {
cplus_register_type($2);
}
}
/* Other miscellaneous errors */
| type stars LPAREN {
skip_decl();
Printf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
}
| strict_type LPAREN STAR {
skip_decl();
Printf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
}
| ID LPAREN STAR {
skip_decl();
Printf(stderr,"%s : Line %d. Function pointers not currently supported (ignored).\n", input_file, line_number);
}
| doc_enable { }
| SEMI { }
;
nested_decl : declaration { $$ = $1;}
| empty { $$.id = 0; }
;
type_extra : stars {}
| AND {}
| empty {}
;
cpp_tail : SEMI { }
| COMMA declaration def_args {
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
temp_typeptr = Copy(Active_type);
add_pointers(temp_typeptr, $2.is_pointer);
cplus_variable($2.id,(char *) 0,temp_typeptr);
Delete(temp_typeptr);
}
scanner_clear_start();
} cpp_tail { }
| COMMA declaration array def_args {
init_language();
if (cplus_mode == CPLUS_PUBLIC) {
temp_typeptr = Copy(Active_type);
add_pointers(temp_typeptr, $2.is_pointer);
cplus_variable($2.id,(char *) 0,temp_typeptr);
Delete(temp_typeptr);
}
scanner_clear_start();
} cpp_tail { }
;
cpp_end : cpp_const SEMI {
Clear(CCode);
}
| cpp_const LBRACE { skip_brace(); }
;
cpp_vend : cpp_const SEMI { Clear(CCode); $$ = 0; }
| cpp_const EQUAL definetype SEMI { Clear(CCode); $$ = 1; }
| cpp_const LBRACE { skip_brace(); $$ = 0; }
;
cpp_enumlist : cpp_enumlist COMMA cpp_edecl {}
| cpp_edecl {}
;
cpp_edecl : ID {
if (cplus_mode == CPLUS_PUBLIC) {
temp_typeptr = NewSwigType(T_INT);
my_cplus_declare_const($1, (char *) 0, temp_typeptr, (char *) 0);
Delete(temp_typeptr);
scanner_clear_start();
}
}
| ID EQUAL etype {
if (cplus_mode == CPLUS_PUBLIC) {
temp_typeptr = NewSwigType(T_INT);
my_cplus_declare_const($1,(char *) 0, temp_typeptr,(char *) 0);
// OLD : Bug with value my_cplus_declare_const($1,(char *) 0, temp_typeptr,$3.id);
Delete(temp_typeptr);
scanner_clear_start();
}
}
| NAME LPAREN ID RPAREN ID {
if (cplus_mode == CPLUS_PUBLIC) {
temp_typeptr = NewSwigType(T_INT);
my_cplus_declare_const($5, $3, temp_typeptr, (char *) 0);
Delete(temp_typeptr);
scanner_clear_start();
}
}
| NAME LPAREN ID RPAREN ID EQUAL etype {
if (cplus_mode == CPLUS_PUBLIC) {
temp_typeptr = NewSwigType(T_INT);
my_cplus_declare_const($5,$3, temp_typeptr, (char *) 0);
Delete(temp_typeptr);
scanner_clear_start();
}
}
| empty { }
;
inherit : COLON base_list {
$$ = $2;
}
| empty {
$$.names = (char **) 0;
$$.count = 0;
}
;
base_list : base_specifier {
int i;
$$.names = (char **) malloc(NI_NAMES*sizeof(char *));
$$.count = 0;
for (i = 0; i < NI_NAMES; i++){
$$.names[i] = (char *) 0;
}
if ($1) {
$$.names[$$.count] = Swig_copy_string($1);
$$.count++;
}
}
| base_list COMMA base_specifier {
$$ = $1;
if ($3) {
$$.names[$$.count] = Swig_copy_string($3);
$$.count++;
}
}
;
base_specifier : ID {
Printf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
input_file,line_number,$1);
$$ = (char *) 0;
}
| VIRTUAL ID {
Printf(stderr,"%s : Line %d. No access specifier given for base class %s (ignored).\n",
input_file,line_number,$2);
$$ = (char *) 0;
}
| VIRTUAL access_specifier ID {
if (strcmp($2,"public") == 0) {
$$ = $3;
} else {
Printf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
input_file,line_number,$2);
$$ = (char *) 0;
}
}
| access_specifier ID {
if (strcmp($1,"public") == 0) {
$$ = $2;
} else {
Printf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
input_file,line_number,$1);
$$ = (char *) 0;
}
}
| access_specifier VIRTUAL ID {
if (strcmp($1,"public") == 0) {
$$ = $3;
} else {
Printf(stderr,"%s : Line %d. %s inheritance not supported (ignored).\n",
input_file,line_number,$1);
$$ = (char *) 0;
}
}
;
access_specifier : PUBLIC { $$ = (char*)"public"; }
| PRIVATE { $$ = (char*)"private"; }
| PROTECTED { $$ = (char*)"protected"; }
;
cpptype : CLASS { $$ = (char*)"class"; }
| STRUCT { $$ = (char*)"struct"; }
| UNION {$$ = (char*)"union"; }
;
cpp_const : CONST {}
| THROW LPAREN parms RPAREN { Delete($3);}
| CONST THROW LPAREN parms RPAREN { Delete($4);}
| empty {}
;
/* Constructor initializer */
ctor_end : cpp_const ctor_initializer SEMI {
Clear(CCode);
}
| cpp_const ctor_initializer LBRACE { skip_brace(); }
;
ctor_initializer : COLON mem_initializer_list {}
| empty {}
;
mem_initializer_list : mem_initializer { }
| mem_initializer_list COMMA mem_initializer { }
;
mem_initializer : ID LPAREN expr_list RPAREN { }
| ID LPAREN RPAREN { }
;
expr_list : expr { }
| expr_list COMMA expr { }
;
/**************************************************************/
/* Objective-C parsing */
/**************************************************************/
objective_c : OC_INTERFACE ID objc_inherit {
ObjCClass = 1;
init_language();
cplus_mode = CPLUS_PROTECTED;
sprintf(temp_name,"CPP_CLASS:%s\n",$2);
if (add_symbol(temp_name)) {
Printf(stderr,"%s : Line %d. @interface %s is multiple defined.\n",
input_file,line_number,$2);
FatalError();
}
scanner_clear_start();
cplus_open_class($2, (char *) 0, (char*)""); // Open up a new C++ class
} LBRACE objc_data RBRACE objc_methods OC_END {
if ($3) {
char *inames[1];
inames[0] = $3;
cplus_inherit(1,inames);
}
cplus_class_close($2);
cplus_mode = CPLUS_PUBLIC;
ObjCClass = 0;
free($2);
free($3);
}
/* An obj-c category declaration */
| OC_INTERFACE ID LPAREN ID RPAREN objc_protolist {
ObjCClass = 1;
init_language();
cplus_mode = CPLUS_PROTECTED;
cplus_set_class($2);
scanner_clear_start();
} objc_methods OC_END {
cplus_unset_class();
}
| OC_IMPLEMENT { skip_to_end(); }
| OC_PROTOCOL { skip_to_end(); }
| OC_CLASS ID initlist SEMI {
char *iname = make_name($2);
init_language();
lang->cpp_class_decl($2,iname,(char*)"");
for (int i = 0; i <$3.count; i++) {
if ($3.names[i]) {
iname = make_name($3.names[i]);
lang->cpp_class_decl($3.names[i],iname,(char*)"");
free($3.names[i]);
}
}
free($3.names);
}
;
objc_inherit : COLON ID objc_protolist { $$ = $2;}
| objc_protolist empty { $$ = 0; }
;
objc_protolist : LESSTHAN { skip_template();
/* CCode.strip(); // Strip whitespace
CCode.replace("<","< ");
CCode.replace(">"," >"); */
$$ = Char(CCode);
}
| empty {
$$ = (char*)"";
}
;
objc_data : objc_vars objc_data { }
| OC_PUBLIC {
cplus_mode = CPLUS_PUBLIC;
} objc_data { }
| OC_PRIVATE {
cplus_mode = CPLUS_PRIVATE;
} objc_data { }
| OC_PROTECTED {
cplus_mode = CPLUS_PROTECTED;
} objc_data { }
| error {
if (!Error) {
skip_decl();
{
static int last_error_line = -1;
if (last_error_line != line_number) {
Printf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
FatalError();
last_error_line = line_number;
}
Error = 1;
}
}
} objc_data { }
| empty { }
;
objc_vars : objc_var objc_vartail SEMI {
}
;
/* An objective-C member variable */
objc_var : type declaration {
if (cplus_mode == CPLUS_PUBLIC) {
int oldstatus = Status;
char *iname;
if (Active_type) Delete(Active_type);
Active_type = Copy($1);
add_pointers($1,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference($1);
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_variable($2.id,iname,$1);
Status = oldstatus;
}
scanner_clear_start();
Delete($1);
}
| type declaration array {
if (cplus_mode == CPLUS_PUBLIC) {
int oldstatus = Status;
char *iname;
if (Active_type) Delete(Active_type);
Active_type = Copy($1);
add_pointers($1,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference($1);
SwigType_push($1,ArrayString);
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_variable($2.id,iname,$1);
Status = oldstatus;
}
scanner_clear_start();
Delete($1);
}
| NAME LPAREN ID RPAREN {
strcpy(yy_rename,$3);
Rename_true = 1;
} objc_var { };
objc_vartail : COMMA declaration objc_vartail {
if (cplus_mode == CPLUS_PUBLIC) {
int oldstatus = Status;
char *iname;
SwigType *t = Copy(Active_type);
add_pointers(t,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference(t);
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_variable($2.id,iname,t);
Status = oldstatus;
Delete(t);
}
scanner_clear_start();
}
| COMMA declaration array objc_vartail {
char *iname;
if (cplus_mode == CPLUS_PUBLIC) {
int oldstatus = Status;
SwigType *t = Copy(Active_type);
add_pointers(t,$2.is_pointer);
if ($2.is_reference) SwigType_add_reference(t);
SwigType_push(t,ArrayString);
iname = make_name($2.id);
if (iname == $2.id) iname = 0;
cplus_variable($2.id,iname,t);
Status = oldstatus;
Delete(t);
}
scanner_clear_start();
}
| empty { }
;
objc_methods : objc_method objc_methods { };
| ADDMETHODS LBRACE {
AddMethods = 1;
} objc_methods RBRACE {
AddMethods = 0;
}
| NAME LPAREN ID RPAREN {
strcpy(yy_rename,$3);
Rename_true = 1;
} objc_methods { }
| error {
skip_decl();
if (!Error) {
{
static int last_error_line = -1;
if (last_error_line != line_number) {
Printf(stderr,"%s : Line %d. Syntax error in input.\n", input_file, line_number);
FatalError();
last_error_line = line_number;
}
Error = 1;
}
}
} objc_methods { }
| empty { }
;
objc_method : MINUS objc_ret_type ID objc_args objc_end {
char *iname;
// An objective-C instance function
// This is like a C++ member function
if (strcmp($3,objc_destruct) == 0) {
// This is an objective C destructor
cplus_destructor($3,(char *) 0);
} else {
iname = make_name($3);
if (iname == $3) iname = 0;
cplus_member_func($3,iname,$2,$4,0);
scanner_clear_start();
Delete($2);
free($3);
Delete($4);
}
}
| PLUS objc_ret_type ID objc_args objc_end {
char *iname;
// An objective-C class function
// This is like a c++ static member function
if (strcmp($3,objc_construct) == 0) {
// This is an objective C constructor
cplus_constructor($3,0,$4);
} else {
iname = make_name($3);
if (iname == $3) iname = 0;
cplus_static_func($3,iname,$2,$4);
}
scanner_clear_start();
Delete($2);
free($3);
Delete($4);
}
;
objc_end : SEMI { Clear(CCode); }
| LBRACE { skip_brace(); }
;
objc_ret_type : LPAREN type RPAREN {
$$ = $2;
}
| LPAREN type stars RPAREN {
$$ = $2;
add_pointers($$,$3);
}
| empty { /* Empty type means "id" type */
$$ = NewString("id");
}
;
objc_arg_type : LPAREN parm RPAREN {
$$ = Copy(Gettype($2));
Delete($2);
}
| empty {
$$ = NewString("id");
}
;
objc_args : objc_args objc_separator objc_arg_type ID {
Parm *p= NewParm($3,$4);
/* p->objc_separator = $2; */
$$ = $1;
if (!$$) {
$$ = p;
} else {
Parm *np, *pp;
np = $$;
while(np) {
pp = np;
np = Getnext(np);
}
Setnext(pp,p);
}
}
| empty {
$$ = 0;
}
;
objc_separator : COLON { $$ = Swig_copy_string((char*)":"); }
| ID COLON { $$ = (char *) malloc(strlen($1)+2);
strcpy($$,$1);
strcat($$,":");
free($1);
}
;
/* Miscellaneous stuff */
/* Documentation style list */
stylelist : ID stylearg styletail {
$$ = $3;
$$.names[$$.count] = Swig_copy_string($1);
$$.values[$$.count] = Swig_copy_string($2);
$$.count++;
}
;
styletail : styletail COMMA ID stylearg {
$$ = $1;
$$.names[$$.count] = Swig_copy_string($3);
$$.values[$$.count] = Swig_copy_string($4);
$$.count++;
}
| empty {
$$.names = (char **) malloc(NI_NAMES*sizeof(char *));
$$.values = (char **) malloc(NI_NAMES*sizeof(char *));
$$.count = 0;
}
;
stylearg : EQUAL NUM_INT {
$$ = $2;
}
| EQUAL STRING {
$$ = $2;
}
| empty {
$$ = 0;
}
;
/* --------------------------------------------------------------
* Type-map parameters
* -------------------------------------------------------------- */
tm_method : ID {
$$ = $1;
}
| CONST {
$$ = Swig_copy_string((char*)"const");
}
;
tm_list : typemap_parm tm_tail {
$$ = $1;
$$->next = $2;
}
;
tm_tail : COMMA typemap_parm tm_tail {
$$ = $2;
$$->next = $3;
}
| empty { $$ = 0;}
;
typemap_parm : type typemap_name {
if (InArray) {
SwigType_push($1,ArrayString);
}
$$ = NewTMParm();
$$->p = NewParm($1,$2);
$$->args = tm_parm;
Delete($1);
free($2);
}
| type stars typemap_name {
$$ = NewTMParm();
$$->p = NewParm($1,$3);
SwigType *pt = Gettype($$->p);
add_pointers(pt,$2);
if (InArray) {
SwigType_push(pt,ArrayString);
}
$$->args = tm_parm;
Delete($1);
free($3);
}
| type maybestars AND typemap_name {
$$ = NewTMParm();
$$->p = NewParm($1,$4);
SwigType *pt = Gettype($$->p);
add_pointers(pt,$2);
SwigType_add_reference(pt);
if (!CPlusPlus) {
Printf(stderr,"%s : Line %d. Warning. Use of C++ Reference detected. Use the -c++ option.\n", input_file, line_number);
}
$$->args = tm_parm;
Delete($1);
free($4);
}
| type LPAREN stars typemap_name RPAREN LPAREN parms RPAREN {
Printf(stderr,"%s : Line %d. Error. Function pointer not allowed (remap with typedef).\n", input_file, line_number);
FatalError();
$$ = NewTMParm();
$$->p = NewParm($1,$4);
SwigType *pt = Gettype($$->p);
DOHList *l = typelist($7);
SwigType_add_function(pt,l);
add_pointers(pt,$3);
$$->args = tm_parm;
Delete($1);
free($4);
Delete($7);
}
;
typemap_name : ID typemap_args {
$$ = $1;
InArray = 0;
}
| ID array {
ArrayBackup = Copy(ArrayString);
} typemap_args {
$$ = $1;
InArray = $2;
Clear(ArrayString);
Append(ArrayString,ArrayBackup);
Delete(ArrayBackup);
}
| array {
ArrayBackup = Copy(ArrayString);
} typemap_args {
$$ = (char *) malloc(1);
$$[0] = 0;
InArray = $1;
Clear(ArrayString);
Append(ArrayString,ArrayBackup);
Delete(ArrayBackup);
}
| typemap_args { $$ = (char *) malloc(1);
$$[0] = 0;
InArray = 0;
}
;
typemap_args : LPAREN parms RPAREN {
tm_parm = $2;
}
| empty {
tm_parm = 0;
}
;
/* Parsing of expressions, but only for throw away code */
/* Might need someday
dummyexpr : NUM_INT { }
| NUM_FLOAT { }
| NUM_UNSIGNED { }
| NUM_LONG { }
| NUM_ULONG { }
| SIZEOF LPAREN type RPAREN { }
| ID { }
| dummyexpr PLUS dummyexpr { }
| dummyexpr MINUS dummyexpr { }
| dummyexpr STAR dummyexpr { }
| dummyexpr SLASH dummyexpr { }
| dummyexpr AND dummyexpr { }
| dummyexpr OR dummyexpr { }
| dummyexpr XOR dummyexpr { }
| dummyexpr LSHIFT dummyexpr { }
| dummyexpr RSHIFT dummyexpr { }
| MINUS dummyexpr %prec UMINUS { }
| NOT dummyexpr { }
| LPAREN dummyexpr RPAREN { }
;
*/
empty : ;
%%
void error_recover() {
int c;
c = yylex();
while ((c > 0) && (c != SEMI))
c = yylex();
}
/* Called by the parser (yyparse) when an error is found.*/
void yyerror (char *) {
// Printf(stderr,"%s : Line %d. Syntax error.\n", input_file, line_number);
// error_recover();
}