SEP  [ \t\n\r+\-*;:,\.()\[\]\{\}\\]+
BLANK [ \t\r]+
NUM  [0-9]+
STR  [a-zA-Z\_][a-zA-Z\_0-9]*

/* A note on parsing braces. Depending on context, a pair { } may enclose a block that should be parsed or a block that should be treated as text. The flag variable br_flag determines how the block between braces should be treated. There are three states which correspond to br_flag = 0, 1, and 3. If a block { } is encountered and br_flag = 0, the block is treated as text; otherwise, it is treated as a block of commands. The transitions between states are as follows. 
- br_flag is reset to 0 when { is encountered. 
- If br_flag = 3 and '\n' or ';' is returned, then br_flag = 1.
- Any command that does not expect a block of commands enclosed between braces makes br_flag = 0.
- Any command that may be followed by a block of commands enclosed between braces makes br_flag = 3.
- In any other case in which the lexer returns a symbol to a parser, the RETURN_BR macro is used, which makes br_flag = 0 if br_flag == 1. 
- Exception: CBLOCK does not need the RETURN_BR, since br_flag is always 0 in the context of CBLOCK.*/

%{

#include"read.h"
#include"read.tab.h"

  extern unsigned char first_pass; // defined in actions.c
  int parseline; // the line number
  static int line1; // first line of a block of C code
  static int bcount; // to count braces
  static struct myinsert buffer; // for text that should not be parsed (C code)
  static char br_flag = 0; // if 0, next brace starts block of text

#define str_append_to_buf(x) \
  if(!first_pass) \
    buffer = SInsert(x, buffer);

#define char_append_to_buf(x) \
  if(!first_pass) \
    buffer = CInsert(x, buffer);

#define RESET_BR \
  if(br_flag == 1) \
    br_flag = 0;
%}

%x brace
%x c_comment
%x comment

%%

<brace>\{  { bcount++; char_append_to_buf(yytext[0]); }
<brace>\}  { 
  bcount--; 
  if (bcount < 1) {
    if(!first_pass) 
      yylval.p = GetInsertBuf(&buffer);
    yylval.line = line1;
    yylval.lastline = parseline;
    BEGIN(INITIAL);
    return C_BLOCK;
  }
  else if(!first_pass)
    buffer = CInsert(yytext[0], buffer);
}
<brace>\/\/[^\n]*\n  { str_append_to_buf(yytext); parseline++; } // comments
<brace,c_comment>[\n\r]  { char_append_to_buf(yytext[0]); parseline++; }
<brace,c_comment>.       { char_append_to_buf(yytext[0]); }
<brace>\/\*          { str_append_to_buf(yytext); BEGIN(c_comment); }
<c_comment>\*\/      { str_append_to_buf(yytext); BEGIN(brace); }

\/\*               BEGIN(comment);
<comment>[\n\r]    parseline++;
<comment>.         ;
<comment>\*\/      BEGIN(INITIAL); 

build/{SEP} { yylval.i = 0; br_flag = 0; return MAIN; }
include/{SEP} { yylval.i = 1; br_flag = 0; return MAIN; }
initialize/{SEP} { br_flag = 0; return INIT; }
live/{SEP} { br_flag = 0; yylval.i = 0; return LIVE; }
main/{SEP} { yylval.i = 2; br_flag = 0; return MAIN; }
places/{SEP}  { br_flag = 0; return PLACES; }
process/{SEP} { yylval.i = 0; br_flag = 3; return PROCESS; }
select/{SEP} { br_flag = 0; return SELECT; }
supervisor/{SEP} { yylval.i = 2; br_flag = 3; return PROCESS; }
sync/{SEP} { br_flag = 3; return SYNC; }
thread/{SEP} { yylval.i = 1; br_flag = 3; return PROCESS; }
to/{SEP} { RESET_BR return TO; }
transitions/{SEP} { br_flag = 0; return TRANSITIONS; }
uncontrollable/{SEP} { br_flag = 0; yylval.i = 1; return LIVE; }
unobservable/{SEP} { br_flag = 0; yylval.i = 2; return LIVE; }


{STR}/{SEP} {
  yylval.p = tmalloc((yyleng+1)*sizeof(char));
  strcpy(yylval.p, yytext);
  yylval.line = parseline;
  //printf("\nReturning var (%s) ", yytext);
  RESET_BR
  return VAR;
}


{NUM} {
  yylval.i = atoi(yytext);
  yylval.line = parseline;
  RESET_BR
  return INTEGER;
}


[.][ \t]*\{ { 
  br_flag = 0;
  buffer = InitInsert(64);
  line1 = parseline;
  bcount = 1;
  BEGIN(brace); 
}

[\{]  { 
  if(!br_flag) {
    bcount = 1;
    buffer = InitInsert(64);
    line1 = parseline;
    BEGIN(brace);
  } 
  else {
    //printf("\nbr_flag = %d", br_flag);
    br_flag = 0; 
    return *yytext; 
  }
} 

[;] { 
  yylval.line = parseline; 
  br_flag = br_flag & 0xFD; // reset bit 1
  return ';'; }

[\n] {
  yylval.line = parseline; 
  parseline++;
  br_flag = br_flag & 0xFD; // reset bit 1
  return '\n'; }

\\[ \t\r]*\n  parseline++; // allow instruction to continue on next line

\/\/[^\n]*  ; // ignore comments

{BLANK} ;

\r ;

. { RESET_BR return *yytext;}

%%

int yywrap(void) {
          return 1;
          }

