PageRenderTime 51ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/main-premerge/SWIG/Source/LParse/parser.y

#
Happy | 1912 lines | 1729 code | 183 blank | 0 comment | 0 complexity | 9d782be9c4496d2fb7e09766ce61167e MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. %{
  2. /* -----------------------------------------------------------------------------
  3. * parser.y
  4. *
  5. * YACC grammar for Dave's lame C parser. Based loosely on the SWIG1.1 parser
  6. *
  7. * Author(s) : David Beazley (beazley@cs.uchicago.edu)
  8. *
  9. * Copyright (C) 1999-2000. The University of Chicago
  10. * See the file LICENSE for information on usage and redistribution.
  11. * ----------------------------------------------------------------------------- */
  12. /* These defines are to move the bison generated functions into their own namespace */
  13. #define yylex lparse_yylex
  14. #define yyerror lparse_yyerror
  15. #define yyparse lparse_yyparse
  16. #define yylval lparse_yylval
  17. #define yychar lparse_yychar
  18. #define yynerrs lparse_yynerrs
  19. static char cvsroot[] = "$Header$";
  20. extern int lparse_yylex();
  21. extern void LParse_strict_type(int);
  22. void yyerror (char *s);
  23. #include "lparse.h"
  24. #include "preprocessor.h"
  25. static DOH *top = 0;
  26. static Hash *class_hash = 0;
  27. /* Pre-created attribute name objects. Used to improve parsing performance */
  28. static DOH *ATTR_TAG = 0;
  29. static DOH *ATTR_CHILD = 0;
  30. static DOH *ATTR_PARENT = 0;
  31. static DOH *ATTR_NEXT = 0;
  32. static DOH *ATTR_PREV = 0;
  33. static DOH *ATTR_NAME = 0;
  34. static DOH *ATTR_VALUE = 0;
  35. static DOH *ATTR_TYPE = 0;
  36. static DOH *ATTR_PARMS = 0;
  37. static DOH *ATTR_PARM = 0;
  38. static DOH *ATTR_STORAGE = 0;
  39. static DOH *TAG_ENUMVALUE = 0;
  40. static DOH *TAG_FUNCTION = 0;
  41. static DOH *TAG_VARIABLE = 0;
  42. static int pure_virtual = 0;
  43. /* Set parent node of a collection of children */
  44. static void setparent(DOH *parent, DOH *child) {
  45. DOH *o;
  46. o = child;
  47. while (o) {
  48. Setattr(o,ATTR_PARENT,parent);
  49. o = Getattr(o,ATTR_NEXT);
  50. }
  51. }
  52. /* Create all back links so we get a doubly-linked lists */
  53. static void create_backlinks(DOH *top) {
  54. DOH *prev = 0;
  55. DOH *obj;
  56. if (!top) return;
  57. obj = top;
  58. while (obj) {
  59. if (prev) {
  60. Setattr(obj,ATTR_PREV,prev);
  61. }
  62. create_backlinks(Getattr(obj,ATTR_CHILD));
  63. prev = obj;
  64. obj = Getattr(obj,ATTR_NEXT);
  65. }
  66. }
  67. /* LParse_parse() - Main entry point to the C parser */
  68. DOH *LParse_parse(DOH *str) {
  69. int yyparse();
  70. DOH *tp;
  71. if (!ATTR_NEXT) {
  72. ATTR_PARENT = NewString("parent");
  73. DohIntern(ATTR_PARENT);
  74. ATTR_NEXT = NewString("next");
  75. DohIntern(ATTR_NEXT);
  76. ATTR_PREV = NewString("prev");
  77. DohIntern(ATTR_PREV);
  78. ATTR_CHILD = NewString("child");
  79. DohIntern(ATTR_CHILD);
  80. ATTR_TAG = NewString("tag");
  81. DohIntern(ATTR_TAG);
  82. ATTR_NAME = NewString("name");
  83. DohIntern(ATTR_NAME);
  84. ATTR_VALUE = NewString("value");
  85. DohIntern(ATTR_VALUE);
  86. ATTR_TYPE = NewString("type");
  87. DohIntern(ATTR_TYPE);
  88. ATTR_PARMS = NewString("parms");
  89. DohIntern(ATTR_PARMS);
  90. ATTR_PARM = NewString("parm");
  91. DohIntern(ATTR_PARM);
  92. ATTR_STORAGE = NewString("storage");
  93. DohIntern(ATTR_STORAGE);
  94. TAG_ENUMVALUE = NewString("c:enumvalue");
  95. DohIntern(TAG_ENUMVALUE);
  96. TAG_FUNCTION = NewString("c:function");
  97. DohIntern(TAG_FUNCTION);
  98. TAG_VARIABLE = NewString("c:variable");
  99. DohIntern(TAG_VARIABLE);
  100. }
  101. LParse_push(str);
  102. top = 0;
  103. class_hash = NewHash();
  104. tp = NewHash();
  105. Setattr(tp, "tag", "swig:top");
  106. Setattr(tp, ATTR_NAME, Getfile(str));
  107. yyparse();
  108. Setattr(tp, ATTR_CHILD, top);
  109. setparent(tp,top);
  110. create_backlinks(tp);
  111. {
  112. DOH *key;
  113. key = Firstkey(class_hash);
  114. while (key) {
  115. DOH *node, *tag;
  116. node = Getattr(class_hash,key);
  117. tag = Gettag(node);
  118. if (Cmp(tag,"swig:addmethods") == 0) {
  119. Printf(stderr,"%s:%d. Warning. Added methods for '%s' ignored.\n", Getfile(node),Getline(node),Getname(node));
  120. }
  121. key = Nextkey(class_hash);
  122. }
  123. }
  124. return tp;
  125. }
  126. static DOH *new_node(char *tag, DOH *file, int line) {
  127. DOH *o;
  128. o = NewHash();
  129. Setattr(o,ATTR_TAG,tag);
  130. Setline(o,line);
  131. Setfile(o,file);
  132. return o;
  133. }
  134. #ifdef NEED_ALLOC
  135. void *alloca(unsigned n) {
  136. return((void *) malloc(n));
  137. }
  138. #else
  139. /* This redefinition is apparently needed on a number of machines */
  140. #undef alloca
  141. #define alloca malloc
  142. #endif
  143. /* Promote the type of arithmetic expressions */
  144. static int promote(int t1, int t2) {
  145. if ((t1 == LPARSE_T_ERROR) || (t2 == LPARSE_T_ERROR)) return LPARSE_T_ERROR;
  146. if ((t1 == LPARSE_T_DOUBLE) || (t2 == LPARSE_T_DOUBLE)) return LPARSE_T_DOUBLE;
  147. if ((t1 == LPARSE_T_FLOAT) || (t2 == LPARSE_T_FLOAT)) return LPARSE_T_FLOAT;
  148. if ((t1 == LPARSE_T_ULONG) || (t2 == LPARSE_T_ULONG)) return LPARSE_T_ULONG;
  149. if ((t1 == LPARSE_T_LONG) || (t2 == LPARSE_T_LONG)) return LPARSE_T_LONG;
  150. if ((t1 == LPARSE_T_UINT) || (t2 == LPARSE_T_UINT)) return LPARSE_T_UINT;
  151. if ((t1 == LPARSE_T_INT) || (t2 == LPARSE_T_INT)) return LPARSE_T_INT;
  152. if ((t1 == LPARSE_T_USHORT) || (t2 == LPARSE_T_USHORT)) return LPARSE_T_SHORT;
  153. if ((t1 == LPARSE_T_SHORT) || (t2 == LPARSE_T_SHORT)) return LPARSE_T_SHORT;
  154. if ((t1 == LPARSE_T_UCHAR) || (t2 == LPARSE_T_UCHAR)) return LPARSE_T_UCHAR;
  155. if ((t1 == LPARSE_T_CHAR) || (t2 == LPARSE_T_CHAR)) return LPARSE_T_INT;
  156. if (t1 != t2) {
  157. LParse_error(0,0,"Type mismatch in constant expression.\n");
  158. }
  159. return t1;
  160. }
  161. %}
  162. %union {
  163. struct {
  164. DOH *filename;
  165. int line;
  166. DOH *text;
  167. int ivalue;
  168. void *data;
  169. } tok;
  170. DOH *node;
  171. struct {
  172. DOH *node;
  173. DOH *last;
  174. } nodelist;
  175. struct {
  176. DOH *id;
  177. DOH *decl;
  178. } decl;
  179. struct {
  180. DOH *name;
  181. DOH *value;
  182. DOH *array;
  183. } pname;
  184. struct {
  185. DOH *name;
  186. DOH *array;
  187. DOH *parms;
  188. } tmname;
  189. struct {
  190. DOH *name;
  191. DOH *array;
  192. DOH *stars;
  193. } sdecl;
  194. };
  195. /* Literals */
  196. %token <tok> ID TYPE_TYPEDEF
  197. %token <tok> HBLOCK
  198. %token <tok> STRING
  199. %token <tok> NUM_INT NUM_FLOAT CHARCONST NUM_UNSIGNED NUM_LONG NUM_ULONG
  200. /* C Symbols */
  201. %token <tok> LPAREN RPAREN LBRACE RBRACE COMMA SEMI PERIOD LBRACKET RBRACKET EQUAL COLON
  202. /* C keywords */
  203. %token <tok> CONST ENUM EXTERN SIZEOF STATIC STRUCT TYPEDEF UNION
  204. /* C++ keywords */
  205. %token <tok> VIRTUAL CLASS FRIEND OPERATOR PRIVATE PROTECTED PUBLIC TEMPLATE THROW
  206. /* Objective C keywords */
  207. %token <tok> OC_INTERFACE OC_END OC_PUBLIC OC_PRIVATE OC_PROTECTED OC_CLASS OC_IMPLEMENT OC_PROTOCOL
  208. /* C Types */
  209. %token <tok> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_TYPESTRING
  210. /* SWIG directives */
  211. %token <tok> ADDMETHODS APPLY CLEAR CONSTANT ECHO EXCEPT SCOPE
  212. %token <tok> ILLEGAL FILEDIRECTIVE INLINE MACRO MODULE NAME PRAGMA INSERT
  213. %token <tok> TYPEMAP TYPES
  214. /* Operators */
  215. %left <tok> LOR
  216. %left <tok> LAND
  217. %left <tok> EQUALTO NOTEQUAL GREATERTHAN LESSTHAN LTEQUAL GTEQUAL
  218. %left <tok> OR
  219. %left <tok> XOR
  220. %left <tok> AND
  221. %left <tok> LSHIFT RSHIFT
  222. %left <tok> PLUS MINUS
  223. %left <tok> STAR SLASH
  224. %left <tok> UMINUS NOT LNOT
  225. %left <tok> DCOLON
  226. %type <tok> idstring template_decl cpptype expr definetype def_args storage_spec pragma_arg ename tm_code
  227. %type <node> parm parms ptail stars
  228. %type <node> array array2
  229. %type <node> type strict_type opt_signed opt_unsigned
  230. %type <decl> declaration
  231. %type <pname> pname
  232. %type <node> tm_args tm_parm tm_tail tm_list
  233. %type <tmname> tm_name
  234. %type <tok> tm_method
  235. %type <node> statement swig_directive c_declaration constant_directive
  236. %type <node> file_include code_block except_directive pragma_directive typemap_directive scope_directive type_directive
  237. %type <node> variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist
  238. %type <nodelist> enumlist interface
  239. %type <node> inherit base_list
  240. %type <tok> base_specifier access_specifier cpp_end ctor_end opt_id
  241. %type <node> cpp_decl cpp_class cpp_other
  242. %type <sdecl> starparm
  243. %%
  244. /* The productions of the grammar with their
  245. associated semantic actions. */
  246. program : interface {
  247. top = $1.node;
  248. }
  249. ;
  250. interface : interface statement {
  251. DOH *o, *o2 = 0;
  252. if (!$1.node) {
  253. $$.node = $2;
  254. o = $2;
  255. while (o) {
  256. o2 = o;
  257. o = Getattr(o,ATTR_NEXT);
  258. }
  259. $$.last = o2;
  260. } else {
  261. if ($2) {
  262. o = $1.last;
  263. if (o) {
  264. Setattr(o,ATTR_NEXT,$2);
  265. } else {
  266. Setattr($1.node,ATTR_NEXT,$2);
  267. }
  268. o = $2;
  269. while (o) {
  270. o2 = o;
  271. o = Getattr(o,ATTR_NEXT);
  272. }
  273. $1.last = o2;
  274. }
  275. $$ = $1;
  276. }
  277. }
  278. | empty { $$.node = 0; $$.last = 0; }
  279. ;
  280. statement : swig_directive { $$ = $1; }
  281. | c_declaration { $$ = $1; }
  282. | SEMI { $$ = 0; }
  283. | error { $$ = 0; }
  284. ;
  285. /* =============================================================================
  286. * -- SWIG DIRECTIVES --
  287. * ============================================================================= */
  288. swig_directive : MODULE idstring {
  289. $$ = new_node("swig:module",$1.filename,$1.line);
  290. Setattr($$,ATTR_NAME,$2.text);
  291. }
  292. | MACRO ID COMMA STRING COMMA NUM_INT LBRACE {
  293. LParse_macro_location($2.text,$1.filename,$1.line);
  294. LParse_set_location($4.text, atoi(Char($6.text))-1);
  295. } interface RBRACE {
  296. LParse_macro_location(0,0,0);
  297. LParse_set_location($7.filename,$7.line-1);
  298. $$ = $9.node;
  299. }
  300. | constant_directive {
  301. $$ = $1;
  302. }
  303. | echo_directive { $$ = 0; }
  304. | file_include { $$ = $1; }
  305. | code_block { $$ = $1; }
  306. | except_directive { $$ = $1; }
  307. | pragma_directive { $$ = $1; }
  308. | typemap_directive { $$ = $1; }
  309. | scope_directive {$$ = $1; }
  310. | type_directive { $$ = $1; }
  311. ;
  312. constant_directive:
  313. CONSTANT ID EQUAL definetype SEMI {
  314. $$ = new_node("swig:constant",$2.filename, $2.line);
  315. Setattr($$,ATTR_NAME,$2.text);
  316. Setattr($$,ATTR_VALUE,$4.text);
  317. switch($4.ivalue) {
  318. case LPARSE_T_DOUBLE:
  319. Setattr($$,ATTR_TYPE,"double");
  320. break;
  321. case LPARSE_T_FLOAT:
  322. Setattr($$,ATTR_TYPE,"float");
  323. break;
  324. case LPARSE_T_ULONG:
  325. Setattr($$,ATTR_TYPE,"unsigned long");
  326. break;
  327. case LPARSE_T_LONG:
  328. Setattr($$,ATTR_TYPE,"long");
  329. break;
  330. case LPARSE_T_UINT:
  331. Setattr($$,ATTR_TYPE,"unsigned int");
  332. break;
  333. case LPARSE_T_INT:
  334. Setattr($$,ATTR_TYPE,"int");
  335. break;
  336. case LPARSE_T_USHORT:
  337. Setattr($$,ATTR_TYPE,"unsigned short");
  338. break;
  339. case LPARSE_T_SHORT:
  340. Setattr($$,ATTR_TYPE,"short");
  341. break;
  342. case LPARSE_T_UCHAR:
  343. Setattr($$,ATTR_TYPE,"unsigned char");
  344. break;
  345. case LPARSE_T_CHAR:
  346. Setattr($$,ATTR_TYPE,"char");
  347. Delitem($4.text,0);
  348. Delitem($4.text,DOH_END);
  349. break;
  350. case LPARSE_T_STRING:
  351. Setattr($$,ATTR_TYPE,"p.char");
  352. break;
  353. default:
  354. break;
  355. }
  356. }
  357. | CONSTANT LPAREN parm RPAREN ID def_args SEMI {
  358. $$ = new_node("swig:constant", $5.filename, $5.line);
  359. Setattr($$,ATTR_NAME,$5.text);
  360. Setattr($$,ATTR_VALUE,$6.text);
  361. Setattr($$,ATTR_TYPE,Gettype($3));
  362. }
  363. ;
  364. scope_directive: SCOPE LBRACE interface RBRACE {
  365. $$ = new_node("swig:scope",$1.filename,$1.line);
  366. if ($3.node) {
  367. Setattr($$,ATTR_CHILD,$3.node);
  368. setparent($$,$3.node);
  369. }
  370. }
  371. | SCOPE LPAREN idstring RPAREN LBRACE interface RBRACE {
  372. $$ = new_node("swig:scope",$1.filename,$1.line);
  373. if ($6.node) {
  374. Setattr($$,ATTR_CHILD,$6.node);
  375. Setattr($$,ATTR_NAME,$3.text);
  376. setparent($$,$6.node);
  377. }
  378. }
  379. ;
  380. echo_directive: ECHO HBLOCK {
  381. char line[32];
  382. sprintf(line,"%d",Getline($2.text));
  383. Replace($2.text,"$file",Getfile($2.text),DOH_REPLACE_ANY);
  384. Replace($2.text,"$line",line, DOH_REPLACE_ANY);
  385. Printf(stderr,"%s\n", $2.text);
  386. }
  387. | ECHO STRING {
  388. char line[32];
  389. sprintf(line,"%d",Getline($2.text));
  390. Replace($2.text,"$file",Getfile($2.text),DOH_REPLACE_ANY);
  391. Replace($2.text,"$line",line, DOH_REPLACE_ANY);
  392. Printf(stderr,"%s\n", $2.text);
  393. }
  394. ;
  395. /* -- File inclusion directives -- */
  396. file_include : FILEDIRECTIVE LPAREN STRING RPAREN STRING LBRACE {
  397. $1.data = new_node("swig:file",$1.filename,$1.line);
  398. Setattr($1.data,ATTR_NAME,$5.text);
  399. Setattr($1.data,ATTR_TYPE,$3.text);
  400. LParse_set_location($5.text,0);
  401. } interface RBRACE {
  402. LParse_set_location($6.filename,$6.line + 1);
  403. $$ = $1.data;
  404. if ($8.node) {
  405. Setattr($$,ATTR_CHILD,$8.node);
  406. setparent($$,$8.node);
  407. }
  408. }
  409. ;
  410. /* -- Code inclusion directives -- */
  411. code_block : INSERT LPAREN idstring RPAREN STRING {
  412. $$ = new_node("swig:insert", $1.filename, $1.line);
  413. Setattr($$,"filename", $5.text);
  414. Setattr($$,"section",$3.text);
  415. }
  416. | INSERT LPAREN idstring RPAREN HBLOCK {
  417. $$ = new_node("swig:insert",$1.filename, $1.line);
  418. Setattr($$,"section",$3.text);
  419. Setattr($$,"code",$5.text);
  420. }
  421. | HBLOCK {
  422. $$ = new_node("swig:insert",$1.filename, $1.line);
  423. Setattr($$,"code",$1.text);
  424. }
  425. | INLINE HBLOCK {
  426. DOH *pp;
  427. $$ = new_node("swig:insert",$2.filename,$2.line);
  428. Setattr($$,"code", $2.text);
  429. Seek($2.text,0,SEEK_SET);
  430. pp = Preprocessor_parse($2.text);
  431. Seek(pp,0,SEEK_SET);
  432. LParse_push(pp);
  433. }
  434. ;
  435. idstring : ID { $$ = $1; }
  436. | TYPE_TYPEDEF { $$ = $1; }
  437. | STRING { $$ = $1; }
  438. ;
  439. /* -- Exceptions -- */
  440. except_directive: EXCEPT LPAREN ID RPAREN LBRACE {
  441. DOH *t;
  442. t = LParse_skip_balanced('{','}');
  443. $$ = new_node("swig:exception",$1.filename,$1.line);
  444. Setattr($$,"lang",$3.text);
  445. Setattr($$,"code",t);
  446. LParse_error($1.filename,$1.line,"Warning. Language specifier in %%except is now ignored.\n");
  447. }
  448. /* A Generic Exception (no language specified) */
  449. | EXCEPT LBRACE {
  450. DOH *t;
  451. t = LParse_skip_balanced('{','}');
  452. $$ = new_node("swig:exception",$1.filename,$1.line);
  453. Setattr($$,"code",t);
  454. }
  455. /* Clear an exception */
  456. | EXCEPT LPAREN ID RPAREN SEMI {
  457. $$ = new_node("swig:exception",$1.filename,$1.line);
  458. Setattr($$,"lang",$3.text);
  459. LParse_error($1.filename,$1.line,"Warning. Language specifier in %%except is now ignored.\n");
  460. }
  461. /* Generic clear */
  462. | EXCEPT SEMI {
  463. $$ = new_node("swig:exception",$1.filename,$1.line);
  464. }
  465. ;
  466. pragma_directive : PRAGMA idstring pragma_arg SEMI {
  467. $$ = new_node("swig:pragma",$1.filename,$1.line);
  468. Setattr($$,ATTR_NAME,$2.text);
  469. Setattr($$,ATTR_VALUE,$3.text);
  470. }
  471. | PRAGMA LPAREN idstring RPAREN idstring pragma_arg SEMI {
  472. $$ = new_node("swig:pragma",$1.filename,$1.line);
  473. Setattr($$,ATTR_NAME,$5.text);
  474. Setattr($$,"lang",$3.text);
  475. Setattr($$,ATTR_VALUE,$6.text);
  476. }
  477. ;
  478. pragma_arg : idstring {
  479. $$.text = $1.text;
  480. }
  481. | EQUAL idstring {
  482. $$.text = $2.text;
  483. /* print warning message here */
  484. }
  485. | HBLOCK {
  486. $$.text = $1.text;
  487. }
  488. | empty {
  489. $$.text = 0;
  490. }
  491. ;
  492. /* -- Typemap directives -- */
  493. typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list tm_code {
  494. DOH *o, *prev = 0, *t, *l;
  495. t = $8.text;
  496. $$ = 0;
  497. for (l = $7; l; l = Getnext(l)) {
  498. o = new_node("swig:typemap",$1.filename, $1.line);
  499. Setattr(o,"lang",$3.text);
  500. Setattr(o,"method",$5.text);
  501. Setattr(o,"code",t);
  502. Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
  503. Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
  504. Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
  505. if (!$$) $$ = o;
  506. if (prev) {
  507. Setattr(prev,ATTR_NEXT,o);
  508. }
  509. prev = o;
  510. }
  511. }
  512. /* Create a new typemap in current language */
  513. | TYPEMAP LPAREN tm_method RPAREN tm_list tm_code {
  514. DOH *o, *t, *l, *prev = 0;
  515. /* t = LParse_skip_balanced('{','}');*/
  516. t = $6.text;
  517. $$ = 0;
  518. for (l = $5; l; l = Getnext(l)) {
  519. o = new_node("swig:typemap",$1.filename, $1.line);
  520. Setattr(o,"method",$3.text);
  521. Setattr(o,"code",t);
  522. Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
  523. Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
  524. Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
  525. if (!$$) $$ = o;
  526. if (prev) Setattr(prev,ATTR_NEXT,o);
  527. prev = o;
  528. }
  529. }
  530. /* Clear a typemap */
  531. | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list SEMI {
  532. DOH *o, *l, *prev = 0;
  533. $$ = 0;
  534. for (l = $7; l; l = Getnext(l)) {
  535. o = new_node("swig:typemap",$1.filename, $1.line);
  536. Setattr(o,"lang",$3.text);
  537. Setattr(o,"method",$5.text);
  538. Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
  539. Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
  540. if (!$$) $$ = o;
  541. if (prev) Setattr(prev,ATTR_NEXT,o);
  542. prev = o;
  543. }
  544. }
  545. /* Clear a typemap in current language */
  546. | TYPEMAP LPAREN tm_method RPAREN tm_list SEMI {
  547. DOH *o, *l, *prev = 0;
  548. $$ = 0;
  549. for (l = $5; l; l = Getnext(l)) {
  550. o = new_node("swig:typemap",$1.filename, $1.line);
  551. Setattr(o,"method",$3.text);
  552. Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
  553. Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
  554. if (!$$) $$ = o;
  555. if (prev) Setattr(prev,ATTR_NEXT,o);
  556. prev = o;
  557. }
  558. }
  559. /* Copy a typemap */
  560. | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list EQUAL tm_parm SEMI {
  561. DOH *o, *l, *prev = 0;
  562. $$ = 0;
  563. for (l = $7; l ; l = Getnext(l)) {
  564. o = new_node("swig:typemap",$1.filename, $1.line);
  565. Setattr(o,"method", $5.text);
  566. Setattr(o,"lang", $3.text);
  567. Setattr(o,ATTR_NAME, Getattr(l,ATTR_NAME));
  568. Setattr(o,ATTR_TYPE, Getattr(l,ATTR_TYPE));
  569. Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
  570. Setattr(o,"srcname",Getattr($9,ATTR_NAME));
  571. Setattr(o,"srctype",Getattr($9,ATTR_TYPE));
  572. if (!$$) $$ = o;
  573. if (prev) Setattr(prev,ATTR_NEXT,o);
  574. prev = o;
  575. }
  576. }
  577. /* Copy typemap in current language */
  578. | TYPEMAP LPAREN tm_method RPAREN tm_list EQUAL tm_parm SEMI {
  579. DOH *o, *l, *prev = 0;
  580. $$ = 0;
  581. for (l = $5; l; l = Getnext(l)) {
  582. o = new_node("swig:typemap",$1.filename, $1.line);
  583. Setattr(o,"method", $3.text);
  584. Setattr(o,ATTR_NAME, Getattr(l,ATTR_NAME));
  585. Setattr(o,ATTR_TYPE, Getattr(l,ATTR_TYPE));
  586. Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
  587. Setattr(o,"srcname",Getattr($7,ATTR_NAME));
  588. Setattr(o,"srctype",Getattr($7,ATTR_TYPE));
  589. if (!$$) $$ = o;
  590. if (prev) Setattr(prev,ATTR_NEXT,o);
  591. prev = o;
  592. }
  593. }
  594. /* Apply directive */
  595. | APPLY tm_parm LBRACE tm_list RBRACE {
  596. $$ = new_node("swig:apply",$1.filename, $1.line);
  597. Setattr($$,ATTR_NAME,Getattr($2,ATTR_NAME));
  598. Setattr($$,ATTR_TYPE,Getattr($2,ATTR_TYPE));
  599. Setattr($$,ATTR_PARMS,$4);
  600. }
  601. /* Clear directive */
  602. | CLEAR tm_list SEMI {
  603. $$ = new_node("swig:clear",$1.filename, $1.line);
  604. Setattr($$,ATTR_PARMS,$2);
  605. }
  606. ;
  607. tm_code : STRING {
  608. $$.text = $1.text;
  609. }
  610. | LBRACE {
  611. $$.text = LParse_skip_balanced('{','}');
  612. }
  613. ;
  614. tm_method : ID {
  615. $$ = $1;
  616. }
  617. | CONST {
  618. $$.text = NewString("const");
  619. }
  620. ;
  621. tm_list : tm_parm tm_tail {
  622. if ($2) {
  623. Setattr($1,ATTR_NEXT,$2);
  624. Setattr($2,ATTR_PREV,$1);
  625. }
  626. $$ = $1;
  627. }
  628. ;
  629. tm_tail : COMMA tm_parm tm_tail {
  630. if ($3) {
  631. Setattr($2,ATTR_NEXT,$3);
  632. Setattr($3,ATTR_PREV,$2);
  633. }
  634. $$ = $2;
  635. }
  636. | empty { $$ = 0; }
  637. ;
  638. tm_parm : type tm_name {
  639. $$ = new_node("tmparm",Getfile($2.name),Getline($2.name));
  640. if ($2.array) {
  641. SwigType_push($1,$2.array);
  642. }
  643. Setattr($$,ATTR_TYPE,$1);
  644. if ($2.name)
  645. Setattr($$,ATTR_NAME,$2.name);
  646. if ($2.parms)
  647. Setattr($$,ATTR_PARMS,$2.parms);
  648. }
  649. | type stars tm_name {
  650. $$ = new_node("tmparm",Getfile($3.name),Getline($3.name));
  651. SwigType_push($1,$2);
  652. if ($3.array) {
  653. SwigType_push($1,$3.array);
  654. }
  655. Setattr($$,ATTR_TYPE,$1);
  656. if ($3.name)
  657. Setattr($$,ATTR_NAME,$3.name);
  658. if ($3.parms)
  659. Setattr($$,ATTR_PARMS,$3.parms);
  660. }
  661. | type AND tm_name {
  662. $$ = new_node("tmparm",Getfile($3.name),Getline($3.name));
  663. SwigType_add_reference($1);
  664. if ($3.array) {
  665. SwigType_push($1,$3.array);
  666. }
  667. Setattr($$,ATTR_TYPE,$1);
  668. if ($3.name)
  669. Setattr($$,ATTR_NAME,$3.name);
  670. if ($3.parms)
  671. Setattr($$,ATTR_PARMS,$3.parms);
  672. }
  673. | type LPAREN stars tm_name RPAREN LPAREN parms RPAREN {
  674. $$ = new_node("tmparm", Getfile($4.name),Getline($4.name));
  675. SwigType_add_function($1,$7);
  676. SwigType_push($1,$3);
  677. if ($4.array) {
  678. SwigType_push($1,$4.array);
  679. }
  680. if ($4.name)
  681. Setattr($$,ATTR_NAME,$4.name);
  682. Setattr($$,ATTR_TYPE,$1);
  683. if ($4.parms)
  684. Setattr($$,ATTR_PARMS,$4.parms);
  685. }
  686. | type stars LPAREN stars tm_name RPAREN LPAREN parms RPAREN {
  687. SwigType_push($1,$2);
  688. $$ = new_node("tmparm", Getfile($5.name),Getline($5.name));
  689. SwigType_add_function($1,$8);
  690. SwigType_push($1,$4);
  691. if ($5.array) {
  692. SwigType_push($1,$5.array);
  693. }
  694. if ($5.name)
  695. Setattr($$,ATTR_NAME,$5.name);
  696. Setattr($$,ATTR_TYPE,$1);
  697. if ($5.parms)
  698. Setattr($$,ATTR_PARMS,$5.parms);
  699. }
  700. ;
  701. tm_name : ID tm_args {
  702. $$.parms = $2;
  703. $$.name = $1.text;
  704. $$.array = 0;
  705. }
  706. | ID array tm_args {
  707. $$.name = $1.text;
  708. $$.array = $2;
  709. $$.parms = $3;
  710. }
  711. | array tm_args {
  712. $$.name = 0;
  713. $$.array = $1;
  714. $$.parms = $2;
  715. }
  716. | tm_args {
  717. $$.name = 0;
  718. $$.array = 0;
  719. $$.parms = $1;
  720. }
  721. ;
  722. tm_args : LPAREN parms RPAREN {
  723. $$ = $2;
  724. }
  725. | empty {
  726. $$ = 0;
  727. }
  728. ;
  729. type_directive : TYPES LPAREN parms RPAREN SEMI {
  730. $$ = new_node("swig:types",$1.filename,$1.line);
  731. Setattr($$,"parms",$3);
  732. }
  733. ;
  734. /* =============================================================================
  735. * -- C Declarations --
  736. * ============================================================================= */
  737. c_declaration : variable_decl { $$ = $1; }
  738. | function_decl { $$ = $1; }
  739. | enum_decl { $$ = $1; }
  740. | typedef_decl { $$ = $1; }
  741. | cpp_decl { $$ = $1; }
  742. ;
  743. /* A variable declaration */
  744. variable_decl : storage_spec type declaration array2 def_args stail {
  745. DOH *o, *t;
  746. $$ = new_node(TAG_VARIABLE,Getfile($3.id),Getline($3.id));
  747. t = Copy($2);
  748. SwigType_push(t,$3.decl);
  749. SwigType_push(t,$4);
  750. Setattr($$,ATTR_NAME,$3.id);
  751. Setattr($$,ATTR_TYPE,t);
  752. if ($1.ivalue) {
  753. Setattr($$,ATTR_STORAGE,$1.text);
  754. }
  755. if ($5.text) {
  756. Setattr($$,ATTR_VALUE,$5.text);
  757. }
  758. if ($6) {
  759. Setattr($$,ATTR_NEXT,$6);
  760. o = $6;
  761. while (o) {
  762. t = Copy($2);
  763. SwigType_push(t,Getattr(o,ATTR_TYPE));
  764. Setattr(o,ATTR_TYPE,t);
  765. if ($1.ivalue) {
  766. Setattr(o,ATTR_STORAGE,$1.text);
  767. }
  768. o = Getattr(o,ATTR_NEXT);
  769. }
  770. }
  771. }
  772. /* Global variable that smells like a function pointer */
  773. | storage_spec strict_type LPAREN STAR {
  774. LParse_error($3.filename,$3.line,"Pointer to function not currently supported.\n");
  775. LParse_skip_decl();
  776. $$ = 0;
  777. }
  778. ;
  779. /* A function declaration */
  780. function_decl : storage_spec type declaration LPAREN parms RPAREN cpp_const stail {
  781. DOH *o, *t;
  782. t = Copy($2);
  783. SwigType_push(t,$3.decl);
  784. $$ = new_node(TAG_FUNCTION,Getfile($3.id),Getline($3.id));
  785. Setattr($$,ATTR_NAME,$3.id);
  786. Setattr($$,ATTR_TYPE,t);
  787. Setattr($$,ATTR_PARMS,$5);
  788. if ($1.ivalue) {
  789. Setattr($$,ATTR_STORAGE, $1.text);
  790. }
  791. if ($8) {
  792. Setattr($$,ATTR_NEXT,$8);
  793. o = $8;
  794. while (o) {
  795. t = Copy($2);
  796. SwigType_push(t,Getattr(o,ATTR_TYPE));
  797. Setattr(o,ATTR_TYPE,t);
  798. if ($1.ivalue) {
  799. Setattr(o,ATTR_STORAGE,$1.text);
  800. }
  801. o = Getattr(o,ATTR_NEXT);
  802. }
  803. }
  804. }
  805. /* A function declaration with code after it */
  806. | storage_spec type declaration LPAREN parms RPAREN cpp_end {
  807. SwigType_push($2,$3.decl);
  808. $$ = new_node(TAG_FUNCTION,Getfile($3.id),Getline($3.id));
  809. Setattr($$,ATTR_NAME,$3.id);
  810. Setattr($$,ATTR_TYPE,$2);
  811. Setattr($$,ATTR_PARMS,$5);
  812. if ($1.ivalue) {
  813. Setattr($$,ATTR_STORAGE, $1.text);
  814. }
  815. if ($7.text)
  816. Setattr($$,"code",$7.text);
  817. if (pure_virtual) {
  818. SetInt($$,"abstract",1);
  819. pure_virtual = 0;
  820. }
  821. }
  822. /* Possibly a constructor */
  823. | storage_spec ID LPAREN parms RPAREN ctor_end {
  824. DOH *t = NewString("int");
  825. $$ = new_node(TAG_FUNCTION,$2.filename,$2.line);
  826. Setattr($$,ATTR_NAME,$2.text);
  827. Setattr($$,ATTR_TYPE,t);
  828. Setattr($$,ATTR_PARMS,$4);
  829. if ($1.ivalue) {
  830. Setattr($$,ATTR_STORAGE,$1.text);
  831. }
  832. if ($6.text) {
  833. Setattr($$,"code",$6.text);
  834. }
  835. }
  836. /* A C++ destructor */
  837. | storage_spec NOT ID LPAREN parms RPAREN cpp_end {
  838. $$ = new_node("c:destructor",$3.filename,$3.line);
  839. Setattr($$,ATTR_NAME,$3.text);
  840. if ($7.text) {
  841. Setattr($$,"code",$7.text);
  842. }
  843. if (pure_virtual) {
  844. SetInt($$,"abstract",1);
  845. pure_virtual = 0;
  846. }
  847. if ($1.ivalue) {
  848. Setattr($$,ATTR_STORAGE,$1.text);
  849. }
  850. }
  851. | storage_spec NOT ID LPAREN parms RPAREN cpp_const SEMI {
  852. $$ = new_node("c:destructor",$3.filename,$3.line);
  853. Setattr($$,ATTR_NAME,$3.text);
  854. if ($1.ivalue) {
  855. Setattr($$,ATTR_STORAGE,$1.text);
  856. }
  857. }
  858. ;
  859. /* Allow lists of variables and functions to be built up */
  860. stail : SEMI { $$ = 0; }
  861. | COMMA declaration array2 def_args stail {
  862. DOH *t = NewString("");
  863. SwigType_push(t,$2.decl);
  864. SwigType_push(t,$3);
  865. $$ = new_node(TAG_VARIABLE, Getfile($2.id),Getline($2.id));
  866. Setattr($$,ATTR_NAME,$2.id);
  867. Setattr($$,ATTR_TYPE,t);
  868. if ($4.text)
  869. Setattr($$,ATTR_VALUE,$4.text);
  870. if ($5)
  871. Setattr($$,ATTR_NEXT, $5);
  872. }
  873. | COMMA declaration LPAREN parms RPAREN stail {
  874. DOH *t = NewString("");
  875. SwigType_push(t,$2.decl);
  876. $$ = new_node(TAG_FUNCTION, Getfile($2.id), Getline($2.id));
  877. Setattr($$,ATTR_NAME,$2.id);
  878. Setattr($$,ATTR_PARMS,$4);
  879. Setattr($$,ATTR_TYPE, t);
  880. if ($6)
  881. Setattr($$,ATTR_NEXT,$6);
  882. }
  883. ;
  884. storage_spec : EXTERN {
  885. $$.ivalue = 1;
  886. $$.text = NewString("extern");
  887. }
  888. | EXTERN STRING {
  889. $$.ivalue = 1;
  890. $$.text = NewStringf("extern \"%s\"", $2.text);
  891. }
  892. | VIRTUAL {
  893. $$.ivalue = 1;
  894. $$.text = NewString("virtual");
  895. }
  896. | STATIC {
  897. $$.ivalue = 1;
  898. $$.text = NewString("static");
  899. }
  900. | empty {
  901. $$.ivalue = 0;
  902. $$.text = 0;
  903. }
  904. ;
  905. cpp_const : CONST {}
  906. | THROW LPAREN { LParse_skip_balanced('(',')'); }
  907. | empty {}
  908. ;
  909. /* Enumerations */
  910. enum_decl : storage_spec ENUM ename LBRACE enumlist RBRACE SEMI {
  911. $$ = new_node("c:enum", $2.filename,$2.line);
  912. Setattr($$,ATTR_NAME,$3.text);
  913. Setattr($$,ATTR_CHILD,$5.node);
  914. setparent($$,$5.node);
  915. /* Add typename */
  916. }
  917. /* A typdef'd enum. Pretty common in C headers */
  918. | TYPEDEF ENUM ename LBRACE enumlist RBRACE ID SEMI {
  919. $$ = new_node("c:enum",$2.filename,$2.line);
  920. Setattr($$,ATTR_NAME,$3.text);
  921. Setattr($$,ATTR_CHILD,$5.node);
  922. setparent($$,$5.node);
  923. /* Add typedef for enum */
  924. {
  925. DOH *o;
  926. o = new_node("c:typedef",$7.filename,$7.line);
  927. Setattr(o,ATTR_NAME,$7.text);
  928. Setattr(o,ATTR_TYPE,$3.text);
  929. Setattr($$,ATTR_NEXT,o);
  930. }
  931. }
  932. ;
  933. /* Some stuff for handling enums */
  934. ename : ID { $$ = $1; }
  935. | empty { $$.text = NewString(""); }
  936. ;
  937. enumlist : enumlist COMMA edecl {
  938. Setattr($1.last,ATTR_NEXT,$3);
  939. $1.last = $3;
  940. $$ = $1;
  941. }
  942. | edecl {
  943. $$.node = $1;
  944. $$.last = $1;
  945. }
  946. ;
  947. edecl : ID {
  948. $$ = new_node(TAG_ENUMVALUE,$1.filename,$1.line);
  949. Setattr($$,ATTR_NAME,$1.text);
  950. }
  951. | ID EQUAL expr {
  952. $$ = new_node(TAG_ENUMVALUE,$1.filename,$1.line);
  953. Setattr($$,ATTR_NAME,$1.text);
  954. Setattr($$,ATTR_VALUE,$1.text);
  955. }
  956. | empty { $$ = 0; }
  957. ;
  958. typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI {
  959. DOH *t, *d, *o, *prev;
  960. int i;
  961. $$ = new_node("c:typedef", $1.filename,$1.line);
  962. t = Copy($2);
  963. SwigType_push($2,$3.decl);
  964. if ($4) SwigType_push($2,$4);
  965. Setattr($$,ATTR_NAME,$3.id);
  966. Setattr($$,ATTR_TYPE,$2);
  967. /* Go create more typedefs */
  968. prev = $$;
  969. for (i = 0; i < Len($5); i++) {
  970. DOH *ty;
  971. d = Getitem($5,i);
  972. o = new_node("c:typedef",$1.filename,$1.line);
  973. ty = Copy(t);
  974. SwigType_push(ty,Getattr(d,"decl"));
  975. SwigType_push(ty,Getattr(d,"array"));
  976. Setattr(o,ATTR_TYPE,ty);
  977. Setattr(o,ATTR_NAME,Getattr(d,ATTR_NAME));
  978. Setattr(prev,ATTR_NEXT,o);
  979. prev = o;
  980. }
  981. Delete($5);
  982. }
  983. /* A rudimentary typedef involving function pointers */
  984. | TYPEDEF type LPAREN starparm RPAREN LPAREN parms RPAREN SEMI {
  985. $$ = new_node("c:typedef", $1.filename,$1.line);
  986. SwigType_add_function($2,$7);
  987. if ($4.stars)
  988. SwigType_push($2,$4.stars);
  989. if ($4.array)
  990. SwigType_push($2,$4.array);
  991. Setattr($$,ATTR_NAME,$4.name);
  992. Setattr($$,ATTR_TYPE,$2);
  993. }
  994. /* A typedef involving function pointers again */
  995. | TYPEDEF type stars LPAREN starparm RPAREN LPAREN parms RPAREN SEMI {
  996. $$ = new_node("c:typedef", $1.filename,$1.line);
  997. SwigType_push($2,$3);
  998. SwigType_add_function($2,$8);
  999. if ($5.stars)
  1000. SwigType_push($2,$5.stars);
  1001. if ($5.array)
  1002. SwigType_push($2,$5.array);
  1003. Setattr($$,ATTR_NAME,$5.name);
  1004. Setattr($$,ATTR_TYPE,$2);
  1005. }
  1006. ;
  1007. typedeflist : COMMA declaration typedeflist {
  1008. DOH *o = NewHash();
  1009. Setattr(o,ATTR_NAME,$2.id);
  1010. Setattr(o,"decl",$2.decl);
  1011. Insert($3,0,o);
  1012. $$ = $3;
  1013. }
  1014. | COMMA declaration array typedeflist {
  1015. DOH *o;
  1016. $$ = $4;
  1017. o = NewHash();
  1018. Setattr(o,ATTR_NAME,$2.id);
  1019. Setattr(o,"decl",$2.decl);
  1020. if ($3)
  1021. Setattr(o,"array",$3);
  1022. Append($$,o);
  1023. }
  1024. | empty {
  1025. $$ = NewList();
  1026. }
  1027. ;
  1028. /* =============================================================================
  1029. * -- Feeble C++ (yuck) Parsing --
  1030. * ============================================================================= */
  1031. cpp_decl : cpp_class {
  1032. String *name;
  1033. DOH *cls;
  1034. $$ = $1;
  1035. /* Save a copy of the class */
  1036. name = Getattr($$,"altname");
  1037. if (!name) {
  1038. name = Getname($$);
  1039. }
  1040. cls = Getattr(class_hash,name);
  1041. if (cls) {
  1042. /* We already saw this class. If the previous class really was a class,
  1043. we'll generate an error. If the class was an added method instead,
  1044. we'll add those methods to our class */
  1045. String *tag = Gettag(cls);
  1046. if (Cmp(tag,"c:class") == 0) {
  1047. /* Already saw this */
  1048. Printf(stderr,"%s:%d. Class '%s' previously defined.\n", Getfile($$),Getline($$),name);
  1049. $$ = 0;
  1050. } else {
  1051. /* Hmmm. Must have been an added method. Attach to the end of my children */
  1052. Swig_node_append_child($$,cls);
  1053. Setattr(class_hash,name,$$);
  1054. }
  1055. } else {
  1056. Setattr(class_hash,name,$$);
  1057. }
  1058. }
  1059. | cpp_other { $$ = $1; }
  1060. ;
  1061. cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id SEMI {
  1062. $$ = new_node("c:class",$3.filename,$3.line);
  1063. Setattr($$,"classtype",$2.text);
  1064. Setattr($$,ATTR_NAME,$3.text);
  1065. Setattr($$,"bases", $4);
  1066. Setattr($$,"namespace",$3.text);
  1067. if ($6.node) {
  1068. Setattr($$,ATTR_CHILD,$6.node);
  1069. setparent($$,$6.node);
  1070. }
  1071. if ($8.text) {
  1072. Setattr($$,TAG_VARIABLE,$8.text);
  1073. }
  1074. }
  1075. | storage_spec cpptype LBRACE interface RBRACE opt_id SEMI {
  1076. $$ = new_node("c:class",$3.filename,$3.line);
  1077. Setattr($$,"classtype",$2.text);
  1078. if ($4.node) {
  1079. Setattr($$,ATTR_CHILD,$4.node);
  1080. setparent($$,$4.node);
  1081. }
  1082. if ($6.text)
  1083. Setattr($$,TAG_VARIABLE,$6.text);
  1084. }
  1085. /* Class with a typedef */
  1086. | TYPEDEF cpptype ID inherit LBRACE interface RBRACE declaration typedeflist {
  1087. $$ = new_node("c:class",$3.filename,$3.line);
  1088. Setattr($$,"classtype",$2.text);
  1089. Setattr($$,ATTR_NAME,$3.text);
  1090. Setattr($$,"bases",$4);
  1091. Setattr($$,"namespace",$3.text);
  1092. if ($6.node) {
  1093. Setattr($$,ATTR_CHILD,$6.node);
  1094. setparent($$,$6.node);
  1095. }
  1096. if (Len($8.decl) == 0)
  1097. Setattr($$,"altname",$8.id);
  1098. {
  1099. /* Go add a bunch of typedef declarations */
  1100. DOH *o, *t, *prev, *d;
  1101. int i;
  1102. o = new_node("c:typedef",$3.filename,$3.line);
  1103. Setattr(o,ATTR_NAME,$8.id);
  1104. t = Copy($3.text);
  1105. SwigType_push(t,$8.decl);
  1106. Setattr(o,ATTR_TYPE,t);
  1107. Setattr($$,ATTR_NEXT,o);
  1108. prev = o;
  1109. for (i = 0; i < Len($9); i++) {
  1110. d = Getitem($9,i);
  1111. o = new_node("c:typedef",$3.filename,$3.line);
  1112. t = Copy($3.text);
  1113. SwigType_push(t,Getattr(d,"decl"));
  1114. SwigType_push(t,Getattr(d,"array"));
  1115. Setattr(o,ATTR_TYPE,t);
  1116. Setattr(o,ATTR_NAME,Getattr(d,ATTR_NAME));
  1117. Setattr(prev,ATTR_NEXT,o);
  1118. prev = o;
  1119. }
  1120. Delete($9);
  1121. }
  1122. }
  1123. /* An unnamed struct with a typedef */
  1124. | TYPEDEF cpptype LBRACE interface RBRACE declaration typedeflist {
  1125. $$ = new_node("c:class",$3.filename,$3.line);
  1126. Setattr($$,"classtype",$2.text);
  1127. if ($4.node) {
  1128. Setattr($$,ATTR_CHILD,$4.node);
  1129. setparent($$,$4.node);
  1130. }
  1131. if (Len($6.decl) == 0)
  1132. Setattr($$,"altname",$6.id);
  1133. }
  1134. ;
  1135. inherit : COLON base_list {
  1136. $$ = $2;
  1137. }
  1138. | empty {
  1139. $$ = 0;
  1140. }
  1141. ;
  1142. base_list : base_specifier {
  1143. $$ = NewList();
  1144. Append($$,$1.text);
  1145. }
  1146. | base_list COMMA base_specifier {
  1147. $$ = $1;
  1148. if ($3.text)
  1149. Append($$,$3.text);
  1150. }
  1151. ;
  1152. base_specifier : ID {
  1153. LParse_error($1.filename,$1.line,"No access specifier given for base class %s (ignored).\n", $1.text);
  1154. $$.text = 0;
  1155. }
  1156. | access_specifier ID {
  1157. if (Cmp($1.text,"public") == 0) {
  1158. $$ = $2;
  1159. } else {
  1160. LParse_error($2.filename,$2.line,"%s inheritance not supported (ignored).\n", $1.text);
  1161. $$.text = 0;
  1162. }
  1163. }
  1164. ;
  1165. access_specifier : PUBLIC { $$.text = NewString("public"); }
  1166. | PRIVATE { $$.text = NewString("private"); }
  1167. | PROTECTED { $$.text = NewString("protected"); }
  1168. ;
  1169. cpp_end : cpp_const LBRACE {
  1170. $$.text = LParse_skip_balanced('{','}');
  1171. pure_virtual = 0;
  1172. }
  1173. | EQUAL definetype SEMI {
  1174. $$.text = 0;
  1175. pure_virtual = 1;
  1176. }
  1177. /* | cpp_const {
  1178. $$.text = 0;
  1179. pure_virtual = 0;
  1180. }
  1181. */
  1182. ;
  1183. type_extra : stars {}
  1184. | AND {}
  1185. | empty {}
  1186. ;
  1187. /* Constructor initializer */
  1188. ctor_end : cpp_const ctor_initializer SEMI { $$.text = 0; }
  1189. | cpp_const ctor_initializer LBRACE { $$.text = LParse_skip_balanced('{','}'); }
  1190. ;
  1191. ctor_initializer : COLON mem_initializer_list {}
  1192. | empty {}
  1193. ;
  1194. mem_initializer_list : mem_initializer { }
  1195. | mem_initializer_list COMMA mem_initializer { }
  1196. ;
  1197. mem_initializer : ID LPAREN { LParse_skip_balanced('(',')'); }
  1198. ;
  1199. cpp_other :/* A dummy class name */
  1200. storage_spec cpptype ID SEMI {
  1201. DOH *o = new_node("c:classdecl",$4.filename,$4.line);
  1202. Setattr(o,ATTR_NAME,$3.text);
  1203. }
  1204. | PUBLIC COLON {
  1205. $$ = new_node("c:access",$1.filename,$1.line);
  1206. Setattr($$,ATTR_NAME,"public");
  1207. }
  1208. | PRIVATE COLON {
  1209. $$ = new_node("c:access",$1.filename,$1.line);
  1210. Setattr($$,ATTR_NAME,"private");
  1211. }
  1212. | PROTECTED COLON {
  1213. $$ = new_node("c:access",$1.filename,$1.line);
  1214. Setattr($$,ATTR_NAME,"protected");
  1215. }
  1216. | FRIEND {
  1217. LParse_skip_decl();
  1218. }
  1219. | storage_spec type type_extra OPERATOR {
  1220. LParse_skip_decl();
  1221. }
  1222. /* Any sort of out-of-class C++ declaration */
  1223. | storage_spec type declaration DCOLON {
  1224. LParse_skip_decl();
  1225. }
  1226. /* Template catch */
  1227. | TEMPLATE {
  1228. LParse_skip_decl();
  1229. }
  1230. /* %addmethods directive */
  1231. | ADDMETHODS opt_id LBRACE interface RBRACE {
  1232. $$ = new_node("swig:addmethods",$1.filename,$1.line);
  1233. if ($4.node) {
  1234. Setattr($$,ATTR_CHILD,$4.node);
  1235. setparent($$,$4.node);
  1236. }
  1237. if ($2.text) {
  1238. DOH *cls;
  1239. Setattr($$,ATTR_NAME,$2.text);
  1240. /* A named addmethods directive. If not in a class. We have to save */
  1241. cls = Getattr(class_hash,$2.text);
  1242. if (cls) {
  1243. /* Hmmm. A class or addmethods directive was already found */
  1244. String *tag = Gettag(cls);
  1245. if (Cmp(tag,"swig:addmethods") == 0) {
  1246. /* We need to append our methods to previous methods */
  1247. Swig_node_append_child(cls,$4.node);
  1248. setparent(cls,$4.node);
  1249. $$ = 0;
  1250. } else {
  1251. /* No. This must be a class. We'll add ourselves to it */
  1252. Swig_node_append_child(cls,$$);
  1253. $$ = 0;
  1254. }
  1255. } else {
  1256. /* Nothing previously defined. Save ourselves */
  1257. Setattr(class_hash,$2.text,$$);
  1258. $$ = 0;
  1259. }
  1260. }
  1261. }
  1262. ;
  1263. opt_id : ID { $$ = $1; }
  1264. | empty { $$.text = 0; }
  1265. ;
  1266. /* =============================================================================
  1267. * -- Generic (admittedly poor) C Parsing --
  1268. * ============================================================================= */
  1269. /* -- Function parameter lists -- */
  1270. parms : parm ptail {
  1271. if ($2) {
  1272. Setattr($1,ATTR_NEXT,$2);
  1273. Setattr($2,ATTR_PREV,$1);
  1274. }
  1275. $$ = $1;
  1276. }
  1277. | empty { $$ = 0; }
  1278. ;
  1279. ptail : COMMA parm ptail {
  1280. if ($3) {
  1281. Setattr($2,ATTR_NEXT,$3);
  1282. Setattr($3,ATTR_PREV,$2);
  1283. }
  1284. $$ = $2;
  1285. }
  1286. | empty { $$ = 0; }
  1287. ;
  1288. parm : type pname {
  1289. $$ = new_node("parm",Getfile($2.name),Getline($2.name));
  1290. Setattr($$,ATTR_NAME,$2.name);
  1291. SwigType_push($1,$2.array);
  1292. if ($2.value)
  1293. Setattr($$,ATTR_VALUE,$2.value);
  1294. Setattr($$,ATTR_TYPE,$1);
  1295. }
  1296. | type stars pname {
  1297. $$ = new_node("parm",Getfile($3.name),Getline($3.name));
  1298. Setattr($$,ATTR_NAME,$3.name);
  1299. SwigType_push($1,$2);
  1300. SwigType_push($1,$3.array);
  1301. if ($3.value) {
  1302. Setattr($$,ATTR_VALUE,$3.value);
  1303. }
  1304. Setattr($$,ATTR_TYPE,$1);
  1305. }
  1306. | type AND pname {
  1307. $$ = new_node("parm",Getfile($3.name),Getline($3.name));
  1308. SwigType_add_reference($1);
  1309. SwigType_push($1,$3.array);
  1310. Setattr($$,ATTR_NAME,$3.name);
  1311. if ($3.value) {
  1312. Setattr($$,ATTR_VALUE,$3.value);
  1313. }
  1314. Setattr($$,ATTR_TYPE,$1);
  1315. }
  1316. | type LPAREN stars pname RPAREN LPAREN parms RPAREN {
  1317. $$ = new_node("parm",$2.filename, $2.line);
  1318. SwigType_add_function($1,$7);
  1319. SwigType_push($1,$3);
  1320. if ($4.array)
  1321. SwigType_push($1,$4.array);
  1322. Setattr($$,ATTR_NAME,$4.name);
  1323. if ($4.value)
  1324. Setattr($$,ATTR_VALUE,$4.value);
  1325. Setattr($$,ATTR_TYPE,$1);
  1326. }
  1327. | type stars LPAREN stars pname RPAREN LPAREN parms RPAREN {
  1328. $$ = new_node("parm",$3.filename, $3.line);
  1329. SwigType_push($1,$2);
  1330. SwigType_add_function($1,$8);
  1331. SwigType_push($1,$4);
  1332. if ($5.array)
  1333. SwigType_push($1,$5.array);
  1334. Setattr($$,ATTR_NAME,$5.name);
  1335. if ($5.value)
  1336. Setattr($$,ATTR_VALUE,$5.value);
  1337. Setattr($$,ATTR_TYPE,$1);
  1338. }
  1339. | PERIOD PERIOD PERIOD {
  1340. $$ = new_node("parm",$1.filename,$1.line);
  1341. Setattr($$,ATTR_NAME,"...");
  1342. Setattr($$,ATTR_TYPE,"?");
  1343. }
  1344. ;
  1345. pname : ID def_args {
  1346. $$.name = $1.text;
  1347. $$.value = $2.text;
  1348. $$.array = 0;
  1349. }
  1350. | ID array {
  1351. $$.name = $1.text;
  1352. $$.value = 0;
  1353. $$.array = $2;
  1354. }
  1355. | array {
  1356. $$.name = NewString("");
  1357. $$.value = 0;
  1358. $$.array = $1;
  1359. }
  1360. | empty {
  1361. $$.name = NewString("");
  1362. $$.value = 0;
  1363. $$.array = 0;
  1364. }
  1365. ;
  1366. def_args : EQUAL definetype { $$ = $2; }
  1367. | EQUAL AND ID {
  1368. $$.text = NewStringf("&%s", $3.text);
  1369. $$.ivalue = LPARSE_T_USER;
  1370. }
  1371. | EQUAL LBRACE {
  1372. LParse_skip_balanced('{','}');
  1373. $$.text = 0;
  1374. $$.ivalue = 0;
  1375. }
  1376. | COLON NUM_INT {
  1377. $$.text = 0;
  1378. $$.ivalue = 0;
  1379. }
  1380. | empty {
  1381. $$.text = 0;
  1382. $$.ivalue = 0;
  1383. }
  1384. ;
  1385. /* Declaration must be an identifier, possibly preceded by a * for pointer types */
  1386. declaration : ID {
  1387. $$.id = $1.text;
  1388. $$.decl = NewString("");
  1389. }
  1390. | stars ID {
  1391. $$.id = $2.text;
  1392. $$.decl = $1;
  1393. }
  1394. | AND ID {
  1395. $$.id = $2.text;
  1396. $$.decl = NewString("");
  1397. SwigType_add_reference($$.decl);
  1398. }
  1399. | AND stars ID {
  1400. $$.id = $3.text;
  1401. $$.decl = $2;
  1402. SwigType_add_reference($$.decl);
  1403. }
  1404. ;
  1405. /* Used for typenames with or without pointers */
  1406. starparm : stars pname {
  1407. $$.name = $2.name;
  1408. $$.array = $2.array;
  1409. $$.stars = $1;
  1410. }
  1411. | pname {
  1412. $$.name = $1.name;
  1413. $$.array = $1.array;
  1414. $$.stars = 0;
  1415. }
  1416. ;
  1417. stars : STAR empty {
  1418. $$ = NewString("");
  1419. SwigType_add_pointer($$);
  1420. }
  1421. | STAR stars {
  1422. $$ = $2;
  1423. SwigType_add_pointer($$);
  1424. }
  1425. ;
  1426. array : LBRACKET RBRACKET array2 {
  1427. $$ = $3;
  1428. SwigType_add_array($$,"");
  1429. }
  1430. | LBRACKET expr RBRACKET array2 {
  1431. $$ = $4;
  1432. SwigType_add_array($$,$2.text);
  1433. }
  1434. ;
  1435. array2 : array {
  1436. $$ = $1;
  1437. }
  1438. | empty { $$ = NewString(""); }
  1439. ;
  1440. type : TYPE_INT { $$ = NewString("int"); }
  1441. | TYPE_SHORT opt_int { $$ = NewString("short"); }
  1442. | TYPE_LONG opt_int { $$ = NewString("long"); }
  1443. | TYPE_CHAR { $$ = NewString("char"); }
  1444. | TYPE_BOOL { $$ = NewString("bool"); }
  1445. | TYPE_FLOAT { $$ = NewString("float"); }
  1446. | TYPE_DOUBLE { $$ = NewString("double"); }
  1447. | TYPE_VOID { $$ = NewString("void"); }
  1448. | TYPE_TYPESTRING { $$ = $1.text; }
  1449. | TYPE_SIGNED opt_signed {
  1450. if ($2) $$ = $2;
  1451. else {
  1452. $$ = NewString("signed");
  1453. }
  1454. }
  1455. | TYPE_UNSIGNED opt_unsigned {
  1456. if ($2) $$ = $2;
  1457. else {
  1458. $$ = NewString("unsigned");
  1459. }
  1460. }
  1461. | ID template_decl {
  1462. if ($2.text)
  1463. $$ = NewStringf("%s%s",$1.text,$2.text);
  1464. else
  1465. $$ = NewString($1.text);
  1466. }
  1467. | CONST type {
  1468. SwigType_add_qualifier($2,"const");
  1469. $$ = $2;
  1470. }
  1471. | cpptype ID {
  1472. $$ = NewStringf("%s %s", $1.text, $2.text);
  1473. }
  1474. | ID DCOLON ID {
  1475. $$ = NewStringf("%s::%s",$1.text,$3.text);
  1476. }
  1477. /* This declaration causes a shift-reduce conflict. Unresolved for now */
  1478. | DCOLON ID {
  1479. $$ = Copy($2.text);
  1480. }
  1481. | ENUM ID {
  1482. $$ = NewStringf("enum %s", $2.text);
  1483. }
  1484. ;
  1485. strict_type : TYPE_INT { $$ = NewString("int"); }
  1486. | TYPE_SHORT opt_int { $$ = NewString("short"); }
  1487. | TYPE_LONG opt_int { $$ = NewString("long"); }
  1488. | TYPE_CHAR { $$ = NewString("char"); }
  1489. | TYPE_BOOL { $$ = NewString("bool"); }
  1490. | TYPE_FLOAT { $$ = NewString("float"); }
  1491. | TYPE_DOUBLE { $$ = NewString("double"); }
  1492. | TYPE_VOID { $$ = NewString("void"); }
  1493. | TYPE_SIGNED opt_signed {
  1494. if ($2) $$ = $2;
  1495. else {
  1496. $$ = NewString("signed");
  1497. }
  1498. }
  1499. | TYPE_UNSIGNED opt_unsigned {
  1500. if ($2) $$ = $2;
  1501. else {
  1502. $$ = NewString("unsigned");
  1503. }
  1504. }
  1505. | TYPE_TYPEDEF template_decl {
  1506. if ($2.text) {
  1507. $$ = NewStringf("%s%s",$1.text,$2.text);
  1508. } else {
  1509. $$ = NewString($1.text);
  1510. }
  1511. }
  1512. | CONST type {
  1513. $$ = $2;
  1514. SwigType_add_qualifier($$,"const");
  1515. }
  1516. | cpptype ID {
  1517. $$ = NewStringf("%s %s", $1.text, $2.text);
  1518. }
  1519. | ENUM ID {
  1520. $$ = NewStringf("enum %s", $2.text);
  1521. }
  1522. ;
  1523. template_decl : LESSTHAN {
  1524. $$.text = LParse_skip_balanced('<','>');
  1525. }
  1526. | empty { $$.text = 0; }
  1527. ;
  1528. /* Optional signed types */
  1529. opt_signed : empty { $$ = 0; }
  1530. | TYPE_INT {
  1531. $$ = NewString("signed int");
  1532. }
  1533. | TYPE_SHORT opt_int {
  1534. $$ = NewString("signed short");
  1535. }
  1536. | TYPE_LONG opt_int {
  1537. $$ = NewString("signed long");
  1538. }
  1539. | TYPE_CHAR {
  1540. $$ = NewString("signed char");
  1541. }
  1542. ;
  1543. /* Optional unsigned types */
  1544. opt_unsigned : empty { $$ = 0;}
  1545. | TYPE_INT {
  1546. $$ = NewString("unsigned int");
  1547. }
  1548. | TYPE_SHORT opt_int {
  1549. $$ = NewString("unsigned short");
  1550. }
  1551. | TYPE_LONG opt_int {
  1552. $$ = NewString("unsigned long");
  1553. }
  1554. | TYPE_CHAR {
  1555. $$ = NewString("unsigned char");
  1556. }
  1557. ;
  1558. opt_int : TYPE_INT { }
  1559. | empty { }
  1560. ;
  1561. cpptype : CLASS { $$ = $1; }
  1562. | STRUCT { $$ = $1; }
  1563. | UNION { $$ = $1; }
  1564. ;
  1565. /* -----------------------------------------------------------------------------
  1566. * -- Expressions --
  1567. * ----------------------------------------------------------------------------- */
  1568. definetype : expr {
  1569. $$ = $1;
  1570. }
  1571. | STRING {
  1572. $$.text = $1.text;
  1573. $$.ivalue = LPARSE_T_STRING;
  1574. }
  1575. | ID {
  1576. $$.text = $1.text;
  1577. $$.ivalue = LPARSE_T_ERROR;

Large files files are truncated, but you can click here to view the full file