home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #27 / NN_1992_27.iso / spool / comp / compiler / 1942 < prev    next >
Encoding:
Text File  |  1992-11-24  |  4.9 KB  |  149 lines

  1. Newsgroups: comp.compilers
  2. Path: sparky!uunet!world!iecc!compilers-sender
  3. From: bliss@sp64.csrd.uiuc.edu (Brian Bliss)
  4. Subject: Re: byacc help needed
  5. Reply-To: bliss@sp64.csrd.uiuc.edu (Brian Bliss)
  6. Organization: UIUC Center for Supercomputing Research and Development
  7. Date: Mon, 23 Nov 1992 18:04:36 GMT
  8. Approved: compilers@iecc.cambridge.ma.us
  9. Message-ID: <92-11-134@comp.compilers>
  10. References:  <92-11-127@comp.compilers>
  11. Keywords: yacc, errors
  12. Sender: compilers-sender@iecc.cambridge.ma.us
  13. Lines: 134
  14.  
  15. thewalt@ce.Berkeley.EDU (C. Thewalt) writes:
  16. |> It appears that the parse state in y.tab.c is controlled by a few scalar
  17. |> variables.  If this is the case, it would seem possible to squirrel away
  18. |> copies and do a setjmp whenever we are in an acceptable state, and when
  19. |> syntax errors occur do a longjmp back to the saved state and reset the
  20. |> variables. ...
  21.  
  22. |> [It might be possible, but I'd think it'd be a lot easier to use the yacc
  23. |> ``error'' token.
  24.  
  25. Here is code to do it in bison, which is also works with regular yacc; the
  26. internal vars all have the same name in both; I wouldn't doubt if this
  27. works fine with byacc, also (but certainly check out a generated source
  28. file to make sure I haven't missed any internal byacc-specific vars):
  29.  
  30. typedef struct MY_JMP_BUF {
  31.    jmp_buf buf;
  32.    union STACK *semantic_stack_next;  /* I didn't use yacc's semantic stack */
  33.    int level;
  34.    int block_no;
  35.  
  36.    /* the rest are yacc internal vars */
  37.    int state;
  38.    int n;
  39.    short *ssp;
  40.    int *vsp;
  41.    short *ss;
  42.    int *vs;
  43.    int len;
  44. } my_jmp_buf;
  45.  
  46. #define parse_setjmp(_val,_buffer) \
  47.     {                                \
  48.        (_buffer).semantic_stack_next = semantic_stack_next;        \
  49.        (_buffer).level = level;                    \
  50.        (_buffer).block_no = block_no;                \
  51.        (_buffer).state = yystate;                    \
  52.        (_buffer).n = yyn;                        \
  53.        (_buffer).ssp = yyssp;                    \
  54.        (_buffer).vsp = yyvsp;                    \
  55.        (_buffer).ss = yyss;                        \
  56.        (_buffer).vs = yyvs;                        \
  57.        (_buffer).len = yylen;                    \
  58.        (_val) = setjmp ((_buffer).buf);                \
  59.        if ((_val) != 0) {                        \
  60.           semantic_stack_next = (_buffer).semantic_stack_next;    \
  61.           yystate = (_buffer).state;                \
  62.           yyn = (_buffer).n;                    \
  63.           yyssp = (_buffer).ssp;                    \
  64.           yyvsp = (_buffer).vsp;                    \
  65.           yyss = (_buffer).ss;                    \
  66.           yyvs = (_buffer).vs;                    \
  67.           yylen = (_buffer).len;                    \
  68.           yynerrs = 0;                        \
  69.        }                                \
  70.     }
  71.  
  72. /*
  73. this must be coded as a macro; a subroutine would return and the
  74. jmp_buf would no longer contain info for a valid stack frame.
  75. */
  76.  
  77. #define parse_longjmp(_val,_buffer) \
  78.     longjmp ((_buffer).buf, (_val))
  79.  
  80. /*
  81. generally, you #define (or code) yyerror () to print out "syntax error",
  82. and then do a longjmp.
  83. */
  84.  
  85.  
  86. points to keep in mind:
  87.  
  88. 1) between the time you perform the setjmp and longjmp, the semantic stack
  89.    (or any of yacc's internal stacks) must not shrink past the level they
  90.    were at when the setjmp was performed.  actually, since we've already
  91.    stored the action to be performed by yacc after executing this imbedded
  92.    code, you can cheat and allow a reduction right after the setjmp, but
  93.    the stack may not shrink further than it does then. i.e.
  94.  
  95.    stmt: empty {
  96.            parse_setjmp (val, buffer);
  97.            if (val) { recover_from_error; }
  98.          } stmt2;
  99.    stmt2: for_stmt | dec_stmt ...
  100.  
  101.    works fine, as does (now we're cheating):
  102.  
  103.    stmt: do_setjmp stmt2;
  104.    do_setjmp: empty {
  105.                 parse_setjmp (val, buffer);
  106.                 if (val) { recover_from_error; }
  107.               };
  108.    stmt2: for_stmt | dec_stmt ...
  109.  
  110. 2) since the block of code where the setjmp was performed (normally) is
  111.    exited before the longjmp takes place, neither val (in the above example)
  112.    or the jmp buffer itself may be declared local to the block where the
  113.    setjmp is performed.  you can either insert them local to yyparse(),
  114.    or else statically allocate them.
  115.  
  116. 3) note we did not store the value of yychar, the input token.
  117.    the following code would replace recover_from_error in the above
  118.    example, if we were writing a C compiler, and wished to scan ahead
  119.    to the next statement in the current block (you should also check
  120.    for '{' and '}'):
  121.  
  122.       int nest = 0;
  123.       while ((yychar = yylex ()) != 0) {
  124.          if (yychar == ')') {
  125.             nest--;
  126.          }
  127.          else if (yychar == '(') {
  128.             nest++;
  129.          }
  130.          else if ((yychar == ';') && (nest <= 0)) {
  131.             break;
  132.          }
  133.       }
  134.       if (yychar == 0) return;
  135.  
  136. 4) this has several advantages over yacc's error recovery mechanism:
  137.    you know exactly what state you are resetting the parser to, you
  138.    can jump to different states depending upon what tokens you find
  139.    in the input stream, and I've found it easy enough to use that I've
  140.    never had occasion to use yacc's built-in error token in a "real"
  141.    parser.
  142.  
  143. bb
  144.  
  145.  
  146. -- 
  147. Send compilers articles to compilers@iecc.cambridge.ma.us or
  148. {ima | spdcc | world}!iecc!compilers.  Meta-mail to compilers-request.
  149.