PCCTSAST.cpp
上传用户:itx_2006
上传日期:2007-01-06
资源大小:493k
文件大小:16k
源码类别:

编译器/解释器

开发平台:

Others

  1. /*
  2.  * PCCTSAST.C
  3.  *
  4.  * SOFTWARE RIGHTS
  5.  *
  6.  * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public
  7.  * domain.  An individual or company may do whatever they wish with
  8.  * source code distributed with SORCERER or the code generated by
  9.  * SORCERER, including the incorporation of SORCERER, or its output, into
  10.  * commerical software.
  11.  *
  12.  * We encourage users to develop software with SORCERER.  However, we do
  13.  * ask that credit is given to us for developing SORCERER.  By "credit",
  14.  * we mean that if you incorporate our source code into one of your
  15.  * programs (commercial product, research project, or otherwise) that you
  16.  * acknowledge this fact somewhere in the documentation, research report,
  17.  * etc...  If you like SORCERER and have developed a nice tool with the
  18.  * output, please mention that you developed it using SORCERER.  In
  19.  * addition, we ask that this header remain intact in our source code.
  20.  * As long as these guidelines are kept, we expect to continue enhancing
  21.  * this system and expect to make other tools available as they are
  22.  * completed.
  23.  *
  24.  * SORCERER 1.00B14 and ANTLR 1.33
  25.  * Terence Parr
  26.  * Parr Research Corporation
  27.  * AHPCRC, University of Minnesota
  28.  * 1992-1998
  29.  */
  30. #define ANTLR_SUPPORT_CODE
  31. #include "pcctscfg.h"
  32. #include "PCCTSAST.h"
  33. #include PCCTS_STDARG_H
  34. PCCTS_NAMESPACE_STD
  35. #include <ctype.h>
  36. //#include "SList.h"
  37.                /* String Scanning/Parsing Stuff */
  38. char *PCCTS_AST::scan_token_tbl[] = {
  39. "invalid", /* 0 */
  40. "LPAREN", /* 1 */
  41. "RPAREN", /* 2 */
  42. "PERCENT", /* 3 */
  43. "INT", /* 4 */
  44. "COLON", /* 5 */
  45. "POUND", /* 6 */
  46. "PERIOD", /* 7 */
  47. };
  48. void PCCTS_AST::
  49. addChild(PCCTS_AST *t)
  50. {
  51. if ( t==NULL ) return;
  52. PCCTS_AST *s = down();
  53. if ( s!=NULL )
  54. {
  55. while ( s->right()!=NULL ) s = s->right();
  56. s->setRight(t);
  57. }
  58. else
  59. this->setDown(t);
  60. }
  61. void PCCTS_AST::
  62. lisp(FILE *f)
  63. {
  64. if ( down() != NULL ) fprintf(f," (");
  65. lisp_action(f);
  66. if ( down()!=NULL ) down()->lisp(f);
  67. if ( down() != NULL ) fprintf(f," )");
  68. if ( right()!=NULL ) right()->lisp(f);
  69. }
  70. /* build a tree (root child1 child2 ... NULL)
  71.  * If root is NULL, simply make the children siblings and return ptr
  72.  * to 1st sibling (child1).  If root is not single node, return NULL.
  73.  *
  74.  * Siblings that are actually sibling lists themselves are handled
  75.  * correctly.  For example #( NULL, #( NULL, A, B, C), D) results
  76.  * in the tree ( NULL A B C D ).
  77.  *
  78.  * Requires at least two parameters with the last one being NULL.  If
  79.  * both are NULL, return NULL.
  80.  *
  81.  * The down() and right() down/right pointers are used to make the tree.
  82.  */
  83. PCCTS_AST *PCCTS_AST::
  84. make(PCCTS_AST *rt, ...)
  85. {
  86. va_list ap;
  87. register PCCTS_AST *child, *sibling=NULL, *tail, *w;
  88. PCCTS_AST *root;
  89. va_start(ap, rt);
  90. root = rt;
  91. if ( root != NULL )
  92. if ( root->down() != NULL ) return NULL;
  93. child = va_arg(ap, PCCTS_AST *);
  94. while ( child != NULL )
  95. {
  96. /* find end of child */
  97. for (w=child; w->right()!=NULL; w=w->right()) {;}
  98. if ( sibling == NULL ) {sibling = child; tail = w;}
  99. else {tail->setRight(child); tail = w;}
  100. child = va_arg(ap, PCCTS_AST *);
  101. }
  102. if ( root==NULL ) root = sibling;
  103. else root->setDown(sibling);
  104. va_end(ap);
  105. return root;
  106. }
  107. /* The following push and pop routines are only used by ast_find_all() */
  108. void PCCTS_AST::
  109. _push(PCCTS_AST **st, int *sp, PCCTS_AST *e)
  110. {
  111. (*sp)--;
  112. require((*sp)>=0, "stack overflow");
  113. st[(*sp)] = e;
  114. }
  115. PCCTS_AST *PCCTS_AST::
  116. _pop(PCCTS_AST **st, int *sp)
  117. {
  118. PCCTS_AST *e = st[*sp];
  119. (*sp)++;
  120. require((*sp)<=MaxTreeStackDepth, "stack underflow");
  121. return e;
  122. }
  123. /* Find all occurrences of u in t.
  124.  * 'cursor' must be initialized to 't'.  It eventually
  125.  * returns NULL when no more occurrences of 'u' are found.
  126.  */
  127. PCCTS_AST *PCCTS_AST::
  128. ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor)
  129. {
  130. PCCTS_AST *sib;
  131. static PCCTS_AST *template_stack[MaxTreeStackDepth];
  132. static int tsp = MaxTreeStackDepth;
  133. static int nesting = 0;
  134. if ( *cursor == NULL ) return NULL;
  135. if ( *cursor!=this ) sib = *cursor;
  136. else {
  137. /* else, first time--start at top of template 't' */
  138. tsp = MaxTreeStackDepth;
  139. sib = this;
  140. /* bottom of stack is always a NULL--"cookie" indicates "done" */
  141. _push(template_stack, &tsp, NULL);
  142. }
  143. keep_looking:
  144. if ( sib==NULL ) /* hit end of sibling list */
  145. {
  146. sib = _pop(template_stack, &tsp);
  147. if ( sib == NULL ) { *cursor = NULL; return NULL; }
  148. }
  149. if ( sib->type() != u->type() )
  150. {
  151. /* look for another match */
  152. if ( sib->down()!=NULL )
  153. {
  154. if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());
  155. sib=sib->down();
  156. goto keep_looking;
  157. }
  158. /* nothing below to try, try next sibling */
  159. sib=sib->right();
  160. goto keep_looking;
  161. }
  162. /* found a matching root node, try to match what's below */
  163. if ( match_partial(sib, u) )
  164. {
  165. /* record sibling cursor so we can pick up next from there */
  166. if ( sib->down()!=NULL )
  167. {
  168. if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());
  169. *cursor = sib->down();
  170. }
  171. else if ( sib->right()!=NULL ) *cursor = sib->right();
  172. else *cursor = _pop(template_stack, &tsp);
  173. return sib;
  174. }
  175. /* no match, keep searching */
  176. if ( sib->down()!=NULL )
  177. {
  178. if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right());
  179. sib=sib->down();
  180. }
  181. else sib = sib->right(); /* else, try to right if zip below */
  182. goto keep_looking;
  183. }
  184. /* are two trees exactly alike? */
  185. int PCCTS_AST::
  186. match(PCCTS_AST *u)
  187. {
  188. PCCTS_AST *t = this;
  189. PCCTS_AST *sib;
  190. if ( u==NULL ) return 0;
  191. for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())
  192. {
  193. if ( sib->type() != u->type() ) return 0;
  194. if ( sib->down()!=NULL )
  195. if ( !sib->down()->match(u->down()) ) return 0;
  196. }
  197. return 1;
  198. }
  199. /* Is 'u' a subtree of 't' beginning at the root? */
  200. int PCCTS_AST::
  201. match_partial(PCCTS_AST *t, PCCTS_AST *u)
  202. {
  203. PCCTS_AST *sib;
  204. if ( u==NULL ) return 1;
  205. if ( t==NULL ) if ( u!=NULL ) return 0; else return 1;
  206. for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())
  207. {
  208. if ( sib->type() != u->type() ) return 0;
  209. if ( sib->down()!=NULL )
  210. if ( !match_partial(sib->down(), u->down()) ) return 0;
  211. }
  212. return 1;
  213. }
  214. /* Walk the template tree 't' (matching against 'this'), filling in the
  215.  * 'labels' array, and setting 'n' according to how many labels were matched.
  216.  */
  217. int PCCTS_AST::
  218. scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n)
  219. {
  220. ScanAST *sib;
  221. PCCTS_AST *u = this;
  222. if ( u==NULL ) return 0;
  223. for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right())
  224. {
  225. /* make sure tokens match; token of '0' means wildcard match */
  226. if ( sib->type() != u->type() && sib->type()!=0 ) return 0;
  227. /* we have a matched token here; set label pointers if exists */
  228. if ( sib->label_num>0 )
  229. {
  230. require(labels!=NULL, "label found in template, but no array of labels");
  231. (*n)++;
  232. *(labels[sib->label_num-1]) = u;
  233. }
  234. /* match what's below if something there and current node is not wildcard */
  235. if ( sib->down()!=NULL && sib->type()!=0 )
  236. {
  237. if ( sib->down()==NULL ) if ( u->down()!=NULL ) return 0; else return 1;
  238. if ( !u->down()->scanmatch(sib->down(), labels, n) ) return 0;
  239. }
  240. }
  241. return 1;
  242. }
  243. void PCCTS_AST::
  244. insert_after(PCCTS_AST *b)
  245. {
  246. PCCTS_AST *end;
  247. if ( b==NULL ) return;
  248. /* find end of b's child list */
  249. for (end=b; end->right()!=NULL; end=end->right()) {;}
  250. end->setRight(this->right());
  251. this->setRight(b);
  252. }
  253. void PCCTS_AST::
  254. append(PCCTS_AST *b)
  255. {
  256. PCCTS_AST *end;
  257. require(b!=NULL, "append: NULL input tree");
  258. /* find end of child list */
  259. for (end=this; end->right()!=NULL; end=end->right()) {;}
  260. end->setRight(b);
  261. }
  262. PCCTS_AST *PCCTS_AST::
  263. tail()
  264. {
  265. PCCTS_AST *end;
  266. /* find end of child list */
  267. for (end=this; end->right()!=NULL; end=end->right()) {;}
  268. return end;
  269. }
  270. PCCTS_AST *PCCTS_AST::
  271. bottom()
  272. {
  273. PCCTS_AST *end;
  274. /* find end of child list */
  275. for (end=this; end->down()!=NULL; end=end->down()) {;}
  276. return end;
  277. }
  278. PCCTS_AST *PCCTS_AST::
  279. cut_between(PCCTS_AST *a, PCCTS_AST *b)
  280. {
  281. PCCTS_AST *end, *ret;
  282. if (a==NULL||b==NULL) return NULL;
  283. /* find node pointing to b */
  284. for (end=a; end->right()!=NULL&&end->right()!=b; end=end->right())
  285. {;}
  286. if (end->right()==NULL) return NULL; //ast_cut_between: a,b not connected
  287. end->setRight(NULL); /* don't want it point to 'b' anymore */
  288. ret = a->right();
  289. a->setRight(b);
  290. return ret;
  291. }
  292. #ifdef NOT_YET
  293. SList *PCCTS_AST::
  294. to_slist()
  295. {
  296. SList *list = new SList;
  297. PCCTS_AST *p;
  298. for (p=this; p!=NULL; p=p->right())
  299. {
  300. list->add(p);
  301. }
  302. return list;
  303. }
  304. #endif
  305. void PCCTS_AST::
  306. tfree()
  307. {
  308. PCCTS_AST *t = this;
  309.     if ( t->down()!=NULL ) t->down()->tfree();
  310.     if ( t->right()!=NULL ) t->right()->tfree();
  311.     delete t;
  312. }
  313. int PCCTS_AST::
  314. nsiblings()
  315. {
  316. PCCTS_AST *t = this;
  317. int n=0;
  318. while ( t!=NULL )
  319. {
  320. n++;
  321. t = t->right();
  322. }
  323. return n;
  324. }
  325. PCCTS_AST *PCCTS_AST::
  326. sibling_index(int i)
  327. {
  328. PCCTS_AST *t = this;
  329. int j=1;
  330. require(i>0, "sibling_index: i<=0");
  331. while ( t!=NULL )
  332. {
  333. if ( j==i ) return t;
  334. j++;
  335. t = t->right();
  336. }
  337. return NULL;
  338. }
  339. /* Assume this is a root node of a tree--
  340.  * duplicate that node and what's below; ignore siblings of root node.
  341.  */
  342. // MR9 23-Sep-97 RJV
  343. // MR9
  344. // MR9 RJV: Original version only duplicated the node and down elements.
  345. // MR9      Made copies of the pointers to sibling.
  346. // MR9      Changed call "down()->deepCopy()" to "down()->deepCopyBushy()"
  347. // MR9
  348. PCCTS_AST *PCCTS_AST::
  349. deepCopy()
  350. {
  351. PCCTS_AST *u = this->shallowCopy();
  352. if ( down()!=NULL ) u->setDown(down()->deepCopyBushy());
  353.     u->setRight(NULL);
  354. return u;
  355. }
  356. /* Copy all nodes including siblings of root. */
  357. PCCTS_AST *PCCTS_AST::
  358. deepCopyBushy()
  359. {
  360. PCCTS_AST *u = this->shallowCopy();
  361. /* copy the rest of the tree */
  362. if ( down()!=NULL ) u->setDown(down()->deepCopyBushy());
  363. if ( right()!=NULL ) u->setRight(right()->deepCopyBushy());
  364. return u;
  365. }
  366. void PCCTS_AST::
  367. scanast_free(ScanAST *t)
  368. {
  369.     if ( t == NULL ) return;
  370.     scanast_free( t->down() );
  371.     scanast_free( t->right() );
  372.     free( (char *) t ); // MR1
  373. }
  374. /*
  375.  * scan
  376.  *
  377.  * This function is like scanf(): it attempts to match a template
  378.  * against an input tree.  A variable number of tree pointers
  379.  * may be set according to the '%i' labels in the template string.
  380.  * For example:
  381.  *
  382.  *   t->ast_scan("#( 6 #(5 %1:4 %2:3) #(1 %3:3 %4:3) )",
  383.  *            &w, &x, &y, &z);
  384.  *
  385.  * Naturally, you'd want this converted from
  386.  *
  387.  *  t->ast_scan("#( RangeOp #(Minus %1:IConst %2:Var) #(Plus %3:Var %4Var) )",
  388.  *   &w, &x, &y, &z);
  389.  *
  390.  * by SORCERER.
  391.  *
  392.  * This function call must be done withing a SORCERER file because SORCERER
  393.  * must convert the token references to the associated token number.
  394.  *
  395.  * This functions parses the template and creates trees which are then
  396.  * matched against the input tree.  The labels are set as they are
  397.  * encountered; hence, partial matches may leave some pointers set
  398.  * and some NULL.  This routines initializes all argument pointers to NULL
  399.  * at the beginning.
  400.  *
  401.  * This function returns the number of labels matched.
  402.  */
  403. int PCCTS_AST::
  404. ast_scan(char *templ, ...)
  405. {
  406. va_list ap;
  407. ScanAST *tmpl;
  408. int n, i, found=0;
  409. PCCTS_AST ***label_ptrs=NULL;
  410. va_start(ap, templ);
  411. /* make a ScanAST tree out of the template */
  412. tmpl = stringparser_parse_scanast(templ, &n);
  413. /* make an array out of the labels */
  414. if ( n>0 )
  415. {
  416. label_ptrs = (PCCTS_AST ***) calloc(n, sizeof(PCCTS_AST **));
  417. require(label_ptrs!=NULL, "scan: out of memory");
  418. for (i=1; i<=n; i++)
  419. {
  420. label_ptrs[i-1] = va_arg(ap, PCCTS_AST **);
  421. *(label_ptrs[i-1]) = NULL;
  422. }
  423. }
  424. /* match the input tree against the template */
  425. scanmatch(tmpl, label_ptrs, &found);
  426. scanast_free(tmpl);
  427. free( (char *) label_ptrs); // MR1
  428. return found;
  429. }
  430. ScanAST *PCCTS_AST::
  431. new_scanast(int tok)
  432. {
  433.     ScanAST *p = (ScanAST *) calloc(1, sizeof(ScanAST));
  434. //
  435. //  7-Apr-97 133MR1
  436. //
  437.     if ( p == NULL ) { // MR1
  438.         fprintf(stderr, "out of memn"); // MR1
  439.          exit(PCCTS_EXIT_FAILURE); // MR1
  440.     }; // MR1
  441. p->_token = tok;
  442. return p;
  443. }
  444. ScanAST *PCCTS_AST::
  445. stringparser_parse_scanast(char *templ, int *num_labels)
  446. {
  447. StringLexer lex;
  448. StringParser parser;
  449. ScanAST *t;
  450. stringlexer_init(&lex, templ);
  451. stringparser_init(&parser, &lex);
  452. t = stringparser_parse_tree(&parser);
  453. *num_labels = parser.num_labels;
  454. return t;
  455. }
  456. void PCCTS_AST::
  457. stringparser_match(StringParser *parser, int token)
  458. {
  459. if ( parser->token != token ) panic("bad tree in scan()");
  460. }
  461. /*
  462.  * Match a tree of the form:
  463.  * (root child1 child2 ... childn)
  464.  * or,
  465.  * node
  466.  *
  467.  * where the elements are integers or labeled integers.
  468.  */
  469. ScanAST *PCCTS_AST::
  470. stringparser_parse_tree(StringParser *parser)
  471. {
  472. ScanAST *t=NULL, *root, *child, *last;
  473. if ( parser->token != __POUND )
  474. {
  475. return stringparser_parse_element(parser);
  476. }
  477. stringparser_match(parser,__POUND);
  478. parser->token = stringscan_gettok(parser->lexer);
  479. stringparser_match(parser,__LPAREN);
  480. parser->token = stringscan_gettok(parser->lexer);
  481. root = stringparser_parse_element(parser);
  482. while ( parser->token != __RPAREN )
  483. {
  484. child = stringparser_parse_element(parser);
  485. if ( t==NULL ) { t = child; last = t; }
  486. else { last->_right = child; last = child; }
  487. }
  488. stringparser_match(parser,__RPAREN);
  489. parser->token = stringscan_gettok(parser->lexer);
  490. root->_down = t;
  491. return root;
  492. }
  493. ScanAST *PCCTS_AST::
  494. stringparser_parse_element(StringParser *parser)
  495. {
  496. static char ebuf[100];
  497. int label = 0;
  498. if ( parser->token == __POUND )
  499. {
  500. return stringparser_parse_tree(parser);
  501. }
  502. if ( parser->token == __PERCENT )
  503. {
  504. parser->token = stringscan_gettok(parser->lexer);
  505. stringparser_match(parser,__INT);
  506. label = atoi(parser->lexer->text);
  507. parser->num_labels++;
  508. if ( label==0 ) panic("%%0 is an invalid label");
  509. parser->token = stringscan_gettok(parser->lexer);
  510. stringparser_match(parser,__COLON);
  511. parser->token = stringscan_gettok(parser->lexer);
  512. /* can label tokens and wildcards */
  513. if ( parser->token != __INT && parser->token != __PERIOD )
  514. panic("can only label tokens");
  515. }
  516. if ( parser->token == __INT )
  517. {
  518. ScanAST *p = new_scanast(atoi(parser->lexer->text));
  519. parser->token = stringscan_gettok(parser->lexer);
  520. p->label_num = label;
  521. return p;
  522. }
  523. if ( parser->token == __PERIOD )
  524. {
  525. ScanAST *p = new_scanast(0); /* token of 0 is wildcard */
  526. parser->token = stringscan_gettok(parser->lexer);
  527. p->label_num = label;
  528. return p;
  529. }
  530. sprintf(ebuf, "mismatch token in scan(): %s", scan_token_str(parser->token));
  531. panic(ebuf);
  532. return NULL;
  533. }
  534. void PCCTS_AST::
  535. stringparser_init(StringParser *parser, StringLexer *input)
  536. {
  537. parser->lexer = input;
  538. parser->token = stringscan_gettok(parser->lexer);
  539. parser->num_labels = 0;
  540. }
  541. void PCCTS_AST::
  542. stringlexer_init(StringLexer *scanner, char *input)
  543. {
  544. scanner->text[0]='';
  545. scanner->input = input;
  546. scanner->p = input;
  547. stringscan_advance(scanner);
  548. }
  549. void PCCTS_AST::
  550. stringscan_advance(StringLexer *scanner)
  551. {
  552. if ( *(scanner->p) == '' ) scanner->c = __StringScanEOF;
  553. scanner->c = *(scanner->p)++;
  554. }
  555. int PCCTS_AST::
  556. stringscan_gettok(StringLexer *scanner)
  557. {
  558. char *index = &scanner->text[0];
  559. static char ebuf[100];
  560. while ( isspace(scanner->c) ) { stringscan_advance(scanner); }
  561. if ( isdigit(scanner->c) )
  562. {
  563. int tok = __INT;
  564. while ( isdigit(scanner->c) ) {
  565. *index++ = scanner->c;
  566. stringscan_advance(scanner);
  567. }
  568. *index = '';
  569. return tok;
  570. }
  571. switch ( scanner->c )
  572. {
  573. case '#' : stringscan_advance(scanner); return __POUND;
  574. case '(' : stringscan_advance(scanner); return __LPAREN;
  575. case ')' : stringscan_advance(scanner); return __RPAREN;
  576. case '%' : stringscan_advance(scanner); return __PERCENT;
  577. case ':' : stringscan_advance(scanner); return __COLON;
  578. case '.' : stringscan_advance(scanner); return __PERIOD;
  579. case '' : return __StringScanEOF;
  580. case __StringScanEOF : return __StringScanEOF;
  581. default  :
  582. sprintf(ebuf, "invalid char in scan: '%c'", scanner->c);
  583. panic(ebuf);
  584. }
  585. return __StringScanEOF; // never reached
  586. }
  587. char *PCCTS_AST::
  588. scan_token_str(int t)
  589. {
  590. if ( VALID_SCAN_TOKEN(t) ) return scan_token_tbl[t];
  591. else if ( t==__StringScanEOF ) return "<end-of-string>";
  592. else return "<invalid-token>";
  593. }