%{
  /* A test lexical analyser for a CIF file 
  /* This is a prototype of a scanner that is automatically
     produced by Perl */
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include "cifsiv.tab.h"
extern char blockname[80];
  char nosdnum[80];
  char *sdbeg;
  int firstpt,secondpt,dp;  /* variables for getting standard deviation */
%}

%x inputtext ourblock
%option nomain
%option noyywrap

DNUM -?(([0-9]+)|([0-9]*[.][0-9]+))([(][0-9]+[)])?([eE][+-]?[0-9]+)?
INUM [+\-]*[[:digit:]]+
CHARS [<>a-zA-Z!~`@#$%^&_|\\:;,\.]

%%
<*>"data_"[[:graph:]]+    {if(strncmp(yytext,blockname,strlen(blockname))==0) 
                           /* is our block */
                          BEGIN(ourblock);
                          else BEGIN(INITIAL);}
<ourblock>^;             BEGIN(inputtext);
<inputtext>^;            {BEGIN(ourblock); return(DATASTRING);}/* finished text */
<inputtext>.*                {strncpy(yylval.item,yytext,80); 
                                   yylval.item[80] = 0x00;} /* save this */
<inputtext>\n/[^;]       /* do nothing */      
<ourblock>"#".*$             /* do nothing (comment) */
<ourblock>"loop_"         return(LOOP);
<ourblock>"_atom_site_aniso_label" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_LABEL;}
<ourblock>"_atom_site_aniso_ratio" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_RATIO;}
<ourblock>"_atom_site_aniso_U_11" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_U_11;}
<ourblock>"_atom_site_aniso_U_12" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_U_12;}
<ourblock>"_atom_site_aniso_U_13" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_U_13;}
<ourblock>"_atom_site_aniso_U_22" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_U_22;}
<ourblock>"_atom_site_aniso_U_23" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_U_23;}
<ourblock>"_atom_site_aniso_U_33" {strncpy(yylval.item, yytext, 80);
                        return C_ATOM_SITE_ANISO_U_33;}
<ourblock>"_refine_ls_extinction_method" {strncpy(yylval.item, yytext, 80);
                        return C_REFINE_LS_EXTINCTION_METHOD;}
<ourblock>"_reflns_number_total" {strncpy(yylval.item, yytext, 80);
                        return C_REFLNS_NUMBER_TOTAL;}
<ourblock>"_reflns_number_observed" {strncpy(yylval.item, yytext, 80);
                        return C_REFLNS_NUMBER_OBSERVED;}
<ourblock>"_"[[:graph:]]+  {strncpy(yylval.item,yytext,80);/* for debugging */
                                    yylval.item[79] = 0x00;
                                    return NAME;} 
<ourblock>"'".*"'"        {firstpt = strcspn(yytext+1,"'");
                           strncpy(yylval.item, yytext+1, firstpt);
                           yylval.item[firstpt] = 0x00;
                           return DATASTRING;}
<ourblock>{DNUM}          { /* we need to extract standard deviations before
                            converting */
                           if((sdbeg = strchr(yytext,'('))==NULL)
                           {
                              yylval.number[0] = strtod(yytext,NULL); 
                              yylval.number[1] = -1;
                              return DNUM;
                            }
                           else
                           {
                              firstpt = strcspn(yytext,"()");
                              secondpt = strcspn(sdbeg,")");
                              strncpy(nosdnum, yytext,firstpt);
                              nosdnum[firstpt]= 0x00;  /* terminate string*/
                              strcat(nosdnum, sdbeg+secondpt+1);
                              yylval.number[0] = strtod(nosdnum, NULL);
                              yylval.number[1] = strtod(sdbeg+1, NULL);
                              /* get esd in proper scale */
                              if((dp = strcspn(yytext,".("))<firstpt-1) /*has dpt */
                              {
                                yylval.number[1] = yylval.number[1] * pow(10,(double)(dp-firstpt+1));
                              }
                              yylval.number[1] = yylval.number[1] * (yylval.number[0]/strtod(yytext,NULL));  /* account for exponent */
                              return DNUM;
                           }
                       }
<ourblock>"?"             {return QUESTION;}
<ourblock>[^[:space:]]+   {strncpy(yylval.item, yytext,80);
                           yylval.item[80] = 0x00;
                           return DATASTRING;}
<*>[[:space:]]+           /* do nothing */
