%{
int var = 0;

#include <string.h>
#define eq(X,Y) (strcmp(X,Y) == 0)
#define ne(X,Y) (strcmp(X,Y) != 0)
#define par(X,Y) { printf(X); yysval.str=strdup(yytext);\
                   yylval.str=yysval.str;yysetvalue(Y);}

extern YYSEMTYPE yysval;
extern YYSTYPE yylval;
%}
%{
#include <stdio.h>
#include <string.h>
#include "jslib.h"

#ifdef NL_DECL
#define YY_DECL NL_DECL
#endif
static char nltext[255];

#define MAX_FEAT_TEXT 20
typedef char feature[MAX_FEAT_TEXT];

#define DIC_NAME "port"

#define PRED_DEFS 3
#define NFEAT 14
char st_feat[NFEAT][50] = {"ROOT","LETT","nltext","CAT","G","N","TR","P","T","SEM","I","Prep","Art","FSEM"};

feature feats_ori[NFEAT];

#define ROOT feats_ori[0]
#define LETT feats_ori[1]
#define nltext feats_ori[2]
#define CAT feats_ori[3]
#define G feats_ori[4]
#define N feats_ori[5]
#define TR feats_ori[6]
#define P feats_ori[7]
#define T feats_ori[8]
#define SEM feats_ori[9]
#define I feats_ori[10]
#define Prep feats_ori[11]
#define Art feats_ori[12]
#define FSEM feats_ori[13]

#define NFILTS 18


#define NFILTS2 2


#define LUNDEF -1


typedef struct par {
   feature conds[NFEAT];
} par;

par pares[NFILTS];
par pares2[NFILTS2];
int npares, inited=0;

static char buf[4096];
static char *pbuf;

init_pares()
{
   cut_feat("CAT=nc", pares[0].conds);
   cut_feat("CAT=cp", pares[1].conds);
   cut_feat("CAT=np,LETT=u", pares[2].conds);
   cut_feat("CAT=prep", pares[3].conds);
   cut_feat("CAT=v,T=i", pares[4].conds);
   cut_feat("CAT=v,T=inf", pares[5].conds);
   cut_feat("CAT=v,T=ppa", pares[6].conds);
   cut_feat("CAT=v,ROOT=ser", pares[7].conds);
   cut_feat("CAT=v,ROOT=estar", pares[8].conds);
   cut_feat("CAT=v,ROOT=ter", pares[9].conds);
   cut_feat("CAT=v", pares[10].conds);
   cut_feat("CAT=art", pares[11].conds);
   cut_feat("CAT=pind", pares[12].conds);
   cut_feat("CAT=a_nc", pares[13].conds);
   cut_feat("CAT=adj", pares[14].conds);
   cut_feat("CAT=adv", pares[15].conds);
   cut_feat("", pares[16].conds);
   cut_feat("", pares[17].conds);
   cut_feat("", pares2[0].conds);
   cut_feat("", pares2[1].conds);
}

char * get_case(char *s) 
    /* u = uppercase; l = lower; a = all upper */
{ 
  return (isupper(s[0])?(isupper(s[1])?"a":"u"):"l");
}
/*----------------------- cut_feat --------------------------------*/

int i_afeat;
char feat_text[MAX_FEAT_TEXT];

char *get_i_afeature(char *p)
{
   int i;
   char act_feat[10];

   i = 0;
   while (*p != '=' && *p != '\0') {
      act_feat[i] = *p;
      i++;
      p++;
   }
   act_feat[i] = '\0';
   if (*p == '\0') return(0);   /* error */

   i = 0;
   while (i < NFEAT && strcmp(st_feat[i], act_feat))
      i++;
   if (i == NFEAT) return(0);   /* not found */
   i_afeat = i;
   return(p);
}

char *get_feat_text(char *p)
{
   int i;

   i = 0;
   while (*p != ',' && *p != ']' && *p != '\0') {
      feat_text[i] = *p;
      i++;
      p++;
   }
   feat_text[i] = '\0';
   return(p);
}

char *get_feature(char *p, char *st)
{
   if (*p == ']' || *p == '\0') return(0);   /* end of string */
   p = get_i_afeature(p);
   if (p == 0) {
      fprintf(stderr, "Erro em get_feature() - %s\n", st);    /**/
      return(0);
   }
   p++;   /* advance = */
   p = get_feat_text(p);
   if (*p == ',') p++;   /* advance ',' */
   while (*p == ' ') p++;   /* advance spaces */
   return(p);
}

void init_zero(feature features[])
{
   int i;

   for (i = PRED_DEFS; i < NFEAT; i++)
      features[i][0] = '\0';
}

cut_feat(char *st_features, feature *features)
{
   char *p;

   init_zero(features);
   p = st_features;
   if ((*p) == '[')
      p++;   /* advance [ */
   while (p = get_feature(p, st_features))
      strcpy(features[i_afeat], feat_text);
}

/*-------------------------------------------------------------------------*/

int matches(feature *test, feature *filt)
{
   int i, mat, comp_tes;

   mat = 0;
   for (i = 0; i < NFEAT; i++)
      if (filt[i][0]) {  /* se o filtro original tinha uma feature, 
                            este tb tem que ter */
         if (strcmp(filt[i], "_") == 0 && test[i][0] ){/* Se o filtro original
                            tem _ qq valor nao vazio de test serve */ } 
         else if (strcmp(test[i], filt[i])) { /* sa~o diferentes */
            /*puts("cond diferente, vou sair");*/   /* DEB */
            return(0);
         }
         mat++;
      }
   /* printf("mat = %d\n", mat);*/   /* DEB */
   return(mat);
}


int da_num_accao(feature *feats_ori,par pares[])
{
   int max_hits, i_max, i, hits;

   max_hits = 0;
   i_max = -1;
   for(i = 0; i < NFILTS; i++) 
      if ((hits = matches(feats_ori, pares[i].conds)) > max_hits) {
             max_hits = hits; i_max = i; }
   return(i_max);
}

/*-------------------------------------------------------------------------*/

void da_raiz(char *st, char *raiz)
{
   int i = 0;

   while(*(st++) != '(') ; 
   while (st[i] != ' ' && st[i] != ',' && st[i] != '\0') {
      raiz[i] = st[i];
      i++;
   }
   raiz[i] = '\0';
}

void trata(char *word)
{ }

/*--------------------------------------------------------------------------*/
%}
W [a-zA-ZáéíóúãçàèõâêôÁÉÍÓÚÇÀÈÃÕÂÊÔ-]+
S ([ 	]*\n[ 	]*|[ 	]+)
P ([ 	]*\n[ 	]*\n)
%%
   sols_type solut, near_misses;
   char raiz[255], st_compr[255];
   int num_accao, i;
   char  init_options[80];
   static char *ok;
   if (!inited) {
      sprintf(init_options, "-d %s -W 0 -y -a", DIC_NAME);
      init_jspell(init_options);
      /* puts("Ja' iniciei o jspell"); */  /* DEB */
      init_pares();
      buf[0] = '\0';
      pbuf = NULL;
      inited = 1;
   }
{S}  ;
{W}   { pbuf = get_next_word(yytext, nltext); {
            strcpy(LETT, get_case(nltext));
            ROOT[0] = '\0' ;
            word_info(nltext, solut, near_misses);
            if (exis_sol(solut[0]))                 /* Is not undef  */
             {   /* ha' pelo menos uma sol. */ 
               for (i = 0; exis_sol(solut[i]); i++) 
                 {                       /**/
                  gclass(solut[i], st_compr);                        /**/
                  da_raiz(solut[i], ROOT);                           /**/
                  cut_feat(st_compr, feats_ori);
                  num_accao = da_num_accao(feats_ori,pares);
                  /* printf("num_accao=%d\n", num_accao); */   /* DEB */
                  switch (num_accao) 
                     {    /* accoes normais) */
   case 0:
  {
{ par("(nome)", NOUN); }
 break;}
   case 1:
  {
{ par("(prep)", PREP); }
 break;}
   case 2:
  {
{ par("(pn)", PN); }
 break;}
   case 3:
  {
{ par("(prep)", PREP); }
 break;}
   case 4:
  {
{ ;  }
 break;}
   case 5:
  {
{ par("(inf)", INF); }
 break;}
   case 6:
  {
{ par("(ppa)", PPA); }
 break;}
   case 7:
  {
{ par("(ser)", SER); }
 break;}
   case 8:
  {
{ par("(ser)", SER); }
 break;}
   case 9:
  {
{ par("(ter)", TER); }
 break;}
   case 10:
  {
{ par("(v)", VERB); }
 break;}
   case 11:
  {
{ par("(art)", DET); }
 break;}
   case 12:
  {
{ par("(pind)", PIND); }
 break;}
   case 13:
  {
{ par("(nome)", NOUN);
                        par("(adj)", ADJ); }
 break;}
   case 14:
  {
{ par("(adj)", ADJ); }
 break;}
   case 15:
  {
{ par("(adv)", ADV); }
 break;}
 default: { printf("[%s]", yytext); yysetvalue(UNDEF); } break;
                     }
                 } /* EOWord: */
{ printf(".\n"); return 0; }
             } /* Undef: */
            else { 
            if (exis_sol(near_misses[0])) 
             {
               for (i = 0; exis_sol(near_misses[i]); i++) 
                 {                   
                  gclass(near_misses[i], st_compr);  
                  da_raiz(near_misses[i], ROOT);    
                  cut_feat(st_compr, feats_ori);
                  num_accao = da_num_accao(feats_ori,pares2);
                  switch (num_accao) 
                     {   
 default: { par("???", UNDEF); } break;
                     }
                 } /* EOWord: */
{ printf(".\n"); return 0; }
 /* }}*/         } else 
             {
                  init_zero(feats_ori);
                  num_accao = da_num_accao(feats_ori,pares2);
                  switch (num_accao) 
                     {   
                  /* } */
 default: { par("???", UNDEF); } break;
                     }
{ printf(".\n"); return 0; }
       }
      }
     }
    }

[0-9]+  {par("(int)",INTEIRO);  return 0; }
[A-Z]\. {par("(abrev)",ABR);    return 0; }
\;      {par("(PUNCT)",PUNCT);  return 0; }
\.      {par("(EOF)",EOF);      return 0; }
<<EOF>> {par("(EOF)",EOF);      return 0; }
«{P}»   {par("(pn_a)",PN);      return 0; }

%%


