Accueil Ti-Gen Foire Aux Questions Chat sur le chan #tigcc sur IRC
Liste des membres Rechercher Aide
Bienvenue Invité !   Se connecter             Mes sujets   
Administrer
0 membre(s) et 1 visiteur(s) actif(s) durant les 5 dernières minutes Utilisateurs actifs : Aucun membre + 1 visiteur
Avant de poster sur le forum, il y a des régles de bases à respecter pour une bonne entente et un respect de tous.
Veuillez lire la charte du forum.
  :: Index » Forum Ti68K » Projets » GFA Basic oncalc (128 réponse(s))
./REPRISE DU POST PRECEDENT (post n°19)   Marquer comme non lu.
Sasume Ecrit le: Mardi 13 juillet 2004 à 19:19 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Ah, ça n'accélère rien ?
    
./Post n°20   Marquer comme non lu.
Sasume Ecrit le: Mardi 13 juillet 2004 à 19:20 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Ça doit compliquer un peu les calculs, mais peut-être que ça peut accélérer, par exemple si tu choisis deux registres pour les représenter, ce sera forcément plus rapide qu'un accès en mémoire, non ?
    
./Post n°21   Marquer comme non lu.
Sasume Ecrit le: Mardi 13 juillet 2004 à 19:21 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Sinon, un détail : quand tu tokenises 3*2+5, au lieu de représenter ça comme 32*5+, je te conseille de le représenter directement par 11 puisque tu peux le calculer en temps de compilation.
    
./Post n°22   Marquer comme non lu.
geogeo Ecrit le: Mardi 13 juillet 2004 à 20:48 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


En effet mais là faut faire une autre passe sur la pile d'expressions.
Ensuite j'abandonne les tampons car je ne peux pas gérer certains cas comme abc*+.
En effet passer par registres j'y pense mais j'en suis loin de la dernière phase. :)

Pour l'instant mon interpréteur est au stade de calculatriuce avec parenthèses :D
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°23   Marquer comme non lu.
Sasume Ecrit le: Mardi 13 juillet 2004 à 21:13 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

En effet, pour abc*+, ça devient compliqué. J'avais pensé à cette situation mais je ne m'y suis pas attardé, je pensais qu'on pourrait se débrouiller pour mettre c sur la pile, mais en fait ça complique pas mal de le parsing, ça rajoute des cas particuliers, ce n'est pas vraiment pratique.
    
./Post n°24   Marquer comme non lu.
geogeo Ecrit le: Mercredi 14 juillet 2004 à 00:29 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


Et de tout façon les tampons ça ralenti donc mieux vaut avoir 2 piles, une pour les réultats pour effectuer les calculs et une pile d'arguments.

Ainsi l'expression abc*+ devient

a-> Pile index 0
b-> Pile index 1
c-> Pile index 2
* Avec index 2 et index 1, résultat dans index 1
+ Avec index 1 et index 0, résultat dans index 0

Si je rencontre une virgule, il suffit normalement de stocker index0 de TSR dans indexn de la pile d'arguments...

Sinon je pense que je dois malheuresement faire une autre passe sur la pile pour optimiser les calculs comme 5+6...
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°25   Marquer comme non lu.
geogeo Ecrit le: Mercredi 14 juillet 2004 à 02:08 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


Un fichier 7391 octets s'analyse entièrement en 0.50 seconde.
Le programme fait pour l'instant une analyse complète de la grammaire du langage, respect des régles de bases, ensuiite définition des priorités des opérateurs, mise en ordre des éléments et ce à chaque ligne.

Les priorités des opérateurs sont les suivantes:

^ = Puissance
- = Négatif
* / = Multiplication et division
+ - = Addition et soustraction
+ = Concantenation de chaînes de caractères.
= < > <= >= <> = Signes de comparaison

Pour les variables elles sont considérés comme un nombre? Et pour les fonctions, elles sont la plus grande prioritée?
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°26   Marquer comme non lu.
geogeo Ecrit le: Mercredi 14 juillet 2004 à 02:31 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  



#define MAX_TAG_STACK          80              //Nombre de tag dans la pile d'expressions de base
#define MAX_OPERATOR_STACK    20              //Nombre d'opérateurs maximum dans la pile d'opérateurs
s_tag StackTag [MAX_TAG_STACK];               //Pile d'expressions de départ
s_tag TStackTag [MAX_TAG_STACK];               //Pile d'expressions triée
s_tag *OperatorStack [MAX_OPERATOR_STACK];     //Pile temporaire d'opérateurs
unsigned char StackTagPtr, TStackTagPtr;

//Liste des variables
lstring GFA_vars [256];
unsigned char GFA_indexvar=0;

#define MAX_SIZE_VAR      16

#define TAG_UNKNOWN        0x00
#define TAG_VAR            0x01
#define TAG_NUMBER        0x02
  #define TAG_INT            0x00
  #define TAG_BOOL          0x01
  #define TAG_FLOAT          0x02
  #define TAG_CHAR          0x03
#define TAG_NEG            0x03 
#define TAG_ADD            0x04
#define TAG_SUB            0x05
#define TAG_MUL            0x06
#define TAG_DIV            0x07
#define TAG_PUISS          0x08
#define TAG_EGAL          0x09
#define TAG_SUPERIOR      0x0A
#define TAG_INFERIOR      0x0B
#define TAG_SUPEGAL        0x0C
#define TAG_INFEGAL        0x0D
#define TAG_DIFF          0x0E
#define TAG_STRING        0x0F
#define TAG_VIRGULE        0x10
#define TAG_PARENTH0      0x11  //(
#define TAG_PARENTH1      0x12  //)

#define TAG_PRIORITY_0    0x00
#define TAG_PRIORITY_1    0x01
#define TAG_PRIORITY_2    0x02
#define TAG_PRIORITY_3    0x03
#define TAG_PRIORITY_4    0x04
#define TAG_PRIORITY_5    0x05
#define TAG_PRIORITY_6    0x06
#define TAG_PRIORITY_7    0x07


//********************************************
//Analyse un programme et le transforme en Tags
//*********************************************
BOOL GFA_Scanner_ReadFile (lstring source)
{  
  char *ptr = source.data;
  long size = source.size;
  
  s_tag tag;
  GFA_Scanner_NextTag (&tag, ptr);
  unsigned char preview_tag = TAG_UNKNOWN;
  
  error_line = 1;
  
  GFA_indexvar = 0;    //Pointeur de variables type int
  StackTagPtr = 0;
  
  while (size-->0 && error_code==ERROR_NOERROR)
  {
    //Variable
    if ((*ptr>='A' && *ptr<='Z') || (*ptr>='a' && *ptr<='z') || *ptr=='_')
    {
      if (preview_tag==TAG_STRING || tag.type==TAG_NUMBER 
      || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT)
      || (preview_tag==TAG_VAR && tag.string.size==0)) 
        {error_code = ERROR_SYNTAX; break;}    
      else if (tag.string.size==MAX_SIZE_VAR) 
        {error_code = ERROR_VARTOOLONG; break;}
      
      //)var ajouter signe multiplier
      if (preview_tag==TAG_PARENTH1) GFA_Scanner_ADD_TagInStack (TAG_MUL, TAG_UNKNOWN, NULL, 0);
      
      if (tag.string.size==0) {tag.type = TAG_VAR; tag.subtype = TAG_FLOAT;} 
      tag.string.size++; preview_tag = TAG_VAR;
    }
    //Nombre
    else if (*ptr>='0' && *ptr<='9')
    {
      if (preview_tag==TAG_STRING 
      || (preview_tag==TAG_VAR && tag.string.size==0))
        {error_code = ERROR_SYNTAX; break;}
      else if (tag.type==TAG_VAR && tag.string.size==MAX_SIZE_VAR) 
        {error_code = ERROR_VARTOOLONG; break;}
      
      //)var ajouter signe multiplier
      if (preview_tag==TAG_PARENTH1) GFA_Scanner_ADD_TagInStack (TAG_MUL, TAG_UNKNOWN, NULL, 0);

      if (tag.string.size==0) {tag.type = TAG_NUMBER; tag.subtype = TAG_INT;}
      else if (tag.type==TAG_UNKNOWN) tag.type = TAG_NUMBER;  
      tag.string.size++;  preview_tag = tag.type;
    }
    //Virgule flottante
    else if (*ptr=='.')
    {
      if ((preview_tag==TAG_VAR || preview_tag==TAG_STRING || tag.subtype==TAG_FLOAT)) 
        {error_code = ERROR_SYNTAX; break;}
      
      //Forme ). ajouter signe multiplier
      if (preview_tag==TAG_PARENTH1) GFA_Scanner_ADD_TagInStack (TAG_MUL, TAG_UNKNOWN, NULL, 0);
      tag.subtype = TAG_FLOAT;
      tag.string.size++; preview_tag = TAG_FLOAT;
    }
    //Typage
    else if (*ptr=='%' || *ptr=='$' || *ptr=='!')
    {
      unsigned char code = TAG_UNKNOWN;
      switch (*ptr)
      {
        case '!':code = TAG_BOOL; break;
        case '$':code = TAG_CHAR; break;
        case '%':code = TAG_INT; break;
      }
      
      if (preview_tag!=TAG_VAR 
      || (preview_tag==TAG_VAR && tag.string.size==0)) 
        {error_code = ERROR_SYNTAX; break;}
      
      GFA_Scanner_ADD_TagInStack (tag.type, code, tag.string.data, tag.string.size);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_VAR;
    }
    //Signes
    else if (*ptr=='+' || *ptr=='-' || *ptr=='*' || *ptr=='/' || *ptr=='^')
    {
      unsigned char code = TAG_UNKNOWN;
      switch (*ptr)
      {
        case '+':code = TAG_ADD; break; //Utiliser pour concantaner des chaînes de caractères
        case '-':code = TAG_SUB; break;
        case '*':code = TAG_MUL; break;
        case '/':code = TAG_DIV; break;
        case '^':code = TAG_PUISS; break;
      }
      
      if ((tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_PARENTH1) 
       || (code!=TAG_ADD && preview_tag==TAG_STRING)
       || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT))
        {error_code = ERROR_SYNTAX; break;}
      else if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);
      GFA_Scanner_ADD_TagInStack (code, TAG_UNKNOWN, ptr, 1);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = code;
    }
    //Egalité, affectation, signes
    else if (*ptr=='=' || *ptr=='<' || *ptr=='>')
    {
      unsigned char code = TAG_UNKNOWN;
      switch (*ptr)
      {
        case '=':code = TAG_EGAL; break;
        case '<':code = TAG_INFERIOR; break;
        case '>':code = TAG_SUPERIOR; break;
        
        //Caractère provisoire
        case 22: code = TAG_EGAL; break;
      }
      
      if ((tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_SUPERIOR && preview_tag!=TAG_INFERIOR && preview_tag!=TAG_PARENTH1) 
       || (code==TAG_INFERIOR && (preview_tag==TAG_EGAL || preview_tag==TAG_SUPERIOR || preview_tag==TAG_INFERIOR))
       || (code==TAG_SUPERIOR && preview_tag==TAG_SUPERIOR)
       || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT))
      {error_code = ERROR_SYNTAX; break;}
      
      //Condition type >= ou <= ou <>
      if ((code==TAG_EGAL || code==TAG_SUPERIOR) && (preview_tag==TAG_SUPERIOR || preview_tag==TAG_INFERIOR))
      {
        //>= ou <=
        if (code==TAG_EGAL)
        {
          if (preview_tag==TAG_SUPERIOR) code = TAG_SUPEGAL;
          else code = TAG_INFEGAL;
        }
        //<>
        else code = TAG_DIFF;
        
        //Modification de la pile d'instructions double signe
        StackTag [StackTagPtr].type = code;
        StackTag [StackTagPtr].string.size++; 
      }
      //Simple caractère 
      else 
      {
        if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);
        GFA_Scanner_ADD_TagInStack (code, TAG_UNKNOWN, ptr, 1);
      }
      
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = code;
    }
    //Négatif
    else if (*(unsigned char *)ptr==173)
    {
      if (tag.string.size!=0 || preview_tag==TAG_VAR || preview_tag==TAG_NEG || preview_tag==TAG_STRING) 
        {error_code = ERROR_SYNTAX; break;}
      
      //Forme )- ajouter signe multiplier 
      if (preview_tag==TAG_PARENTH1) GFA_Scanner_ADD_TagInStack (TAG_MUL, TAG_UNKNOWN, NULL, 0);
      GFA_Scanner_ADD_TagInStack (TAG_NEG, TAG_UNKNOWN, ptr, 1);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_NEG;
    }
    //Virgule
    else if (*ptr==',')
    {
      //Caractère de début
      if ((tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_VIRGULE && preview_tag!=TAG_PARENTH1 && preview_tag!=TAG_UNKNOWN) 
       || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT)) 
        {error_code = ERROR_SYNTAX; break;}
      
      if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);
      GFA_Scanner_ADD_TagInStack (TAG_VIRGULE, TAG_UNKNOWN, ptr, 1);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_VIRGULE;
    }
    //Parenthèse ouverte TAG_PARENTH0
    else if (*ptr=='(')
    {
      if (preview_tag==TAG_STRING
      || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT))
        {error_code = ERROR_SYNTAX; break;}
      
      //Forme x( ajouter signe multiplier
      if (preview_tag==TAG_NUMBER || preview_tag==TAG_PARENTH1)  GFA_Scanner_ADD_TagInStack (TAG_MUL, TAG_UNKNOWN, NULL, 0);
      
      if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);
      GFA_Scanner_ADD_TagInStack (TAG_PARENTH0, TAG_UNKNOWN, ptr, 1);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_PARENTH0;
    }
    //Parenthèse fermée TAG_PARENTH1
    else if (*ptr==')')
    {
      if (tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_PARENTH0 && preview_tag!=TAG_PARENTH1)
        {error_code = ERROR_SYNTAX; break;}
        
      if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);
      GFA_Scanner_ADD_TagInStack (TAG_PARENTH1, TAG_UNKNOWN, ptr, 1);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_PARENTH1;
    }
    //Espace
    else if (*ptr==32)
    {
      //Caractère de début
      if ((tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_PARENTH1 && preview_tag!=TAG_UNKNOWN) 
       || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT)) 
        {error_code = ERROR_SYNTAX; break;}
        
      if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_UNKNOWN;
    }
    //Commentaires 'comment
    else if (*ptr==39)
    {      
      if ((tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_PARENTH1 && preview_tag!=TAG_UNKNOWN)
      || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT)) 
        {error_code = ERROR_SYNTAX; break;}
      
      if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size);

      //Cherche caractère 13 ou fin du fichier
      while (--size && *++ptr!=13);
      error_line++;
      GFA_Scanner_NextTag (&tag, ++ptr+1); size--;
      preview_tag = TAG_UNKNOWN;
    }
    //Chaîne de caractères
    else if (*ptr==34)
    {
      if (tag.string.size!=0 || preview_tag==TAG_VAR || preview_tag==TAG_SUB || preview_tag==TAG_MUL || preview_tag==TAG_DIV || preview_tag==TAG_PUISS || preview_tag==TAG_STRING || preview_tag==TAG_PARENTH1) 
        {error_code = ERROR_SYNTAX; break;}
      
      do
      {
        ptr++;
        //Fin d'une châine de caractères
        if (*ptr==34) break;
        //Saut à la ligne
        else if (*ptr==13) {error_code = ERROR_SYNTAX; break;}
        
        tag.string.size++; 
      } while (--size);
      
      //Fin du fichier
      if (size--==0) error_code = ERROR_SYNTAX;
      
      GFA_Scanner_ADD_TagInStack (TAG_STRING, TAG_UNKNOWN, ++tag.string.data, tag.string.size);
      GFA_Scanner_NextTag (&tag, ptr+1);
      preview_tag = TAG_STRING;
    }
    //Caractère inconnu
    else if (*ptr!=13) error_code = ERROR_UNKNOWNCHAR;
    
    //Aller à la ligne
    if (*ptr==13 || !size)
    {
      if (error_code!=ERROR_NOERROR) break;  
      else if ((tag.string.size==0 && preview_tag!=TAG_VAR && preview_tag!=TAG_STRING && preview_tag!=TAG_PARENTH1 && preview_tag!=TAG_UNKNOWN)
       || (tag.type==TAG_UNKNOWN && tag.subtype==TAG_FLOAT)) 
        {error_code = ERROR_SYNTAX; break;}  
      
      if (tag.string.size!=0) GFA_Scanner_ADD_TagInStack (tag.type, tag.subtype, tag.string.data, tag.string.size); 
      
      //Analyse
      if (!GFA_Scanner_SET_TagInStack ()) break;
      
      //Ligne suivante
      if (*ptr==13) {error_line++; ptr++; size--;}
      
      GFA_Scanner_NextTag (&tag, ptr+1); 
      preview_tag = TAG_UNKNOWN;
    }
    
    
    ptr++;
  }
  
  if (error_code!=ERROR_NOERROR) {error_ptr = size; return FALSE;}
  return TRUE;
}


//****************************
//Prepare instruction suivante
//****************************
void GFA_Scanner_NextTag (s_tag *tag, void *ptr)
{
  tag->type = TAG_UNKNOWN;
  tag->subtype = TAG_UNKNOWN;  
  tag->string.data = ptr;
  tag->string.size = 0;
}


//*******************************
//Ajoute instructions sur la pile
//*******************************
BOOL GFA_Scanner_ADD_TagInStack (unsigned char type, unsigned char subtype, void *data, unsigned short size)
{
  //Dépassement de la pile
  if (StackTagPtr+1==MAX_TAG_STACK) {
    error_code = ERROR_LINETOOLONG;
    return FALSE;}
  
  //Ajoute instruction dans la pile
  StackTag [StackTagPtr].type = type;
  StackTag [StackTagPtr].subtype = subtype;
  StackTag [StackTagPtr].string.data = data;
  StackTag [StackTagPtr].string.size = size;
  
  GFA_Scanner_SetPriority_TagInStack (StackTagPtr++);
  return TRUE;
}


//********************************
//Attribution priorité
//********************************
void GFA_Scanner_SetPriority_TagInStack (unsigned char ptr)
{
  unsigned char type = StackTag [ptr].type;
  
  if (type==TAG_INFERIOR || type==TAG_SUPERIOR || type==TAG_EGAL || type==TAG_SUPEGAL || type==TAG_INFEGAL || type==TAG_DIFF)
    StackTag [ptr].priority = TAG_PRIORITY_0;
  else if (type==TAG_ADD || type==TAG_SUB)
  {
    if (ptr && type==TAG_ADD && StackTag [ptr-1].type==TAG_STRING) 
      StackTag [ptr].priority = TAG_PRIORITY_1;
    else 
      StackTag [ptr].priority = TAG_PRIORITY_2;
  }
  else if (type==TAG_MUL || type==TAG_DIV)
    StackTag [ptr].priority = TAG_PRIORITY_3;
  else if (type==TAG_NEG)
    StackTag [ptr].priority = TAG_PRIORITY_4;
  else if (type==TAG_PUISS)
    StackTag [ptr].priority = TAG_PRIORITY_5;
}


//********************************
//Mise en ordre de la pile
//********************************
BOOL GFA_Scanner_SET_TagInStack ()
{
  unsigned char OperatorStackPtr=0;
  TStackTagPtr = 0; //Vide la pile temporaire
  
  //OperatorStack
  unsigned char tag_type = TAG_UNKNOWN;
    
  //Parcours la pile d'expression de base
  for (int i=0; i<StackTagPtr; i++)
  {
    tag_type = StackTag .type;
    
    //Simple nombre ou variable, ajoute dans la pile d'expressions finale
    if (tag_type==TAG_NUMBER || tag_type==TAG_VAR || tag_type==TAG_STRING)
      memcpy (&TStackTag [TStackTagPtr++], &StackTag [i], sizeof (s_tag)); 
  
    //Parenthèse ouverte, ajoute dans la pile d'opérateurs  
    else if (tag_type==TAG_PARENTH0)
      OperatorStack [OperatorStackPtr++] = &StackTag [i];
      
    //Parenthèse fermée, ajouter dernier signe dans pile d'expreesions finale puis tester si parenthèse ouverte
    else if (tag_type==TAG_PARENTH1)
    {
      //Ajoute signe opérateur dans la pile d'expressions
      while (OperatorStackPtr-- && OperatorStack [OperatorStackPtr]->type!=TAG_PARENTH0)  
        memcpy (&TStackTag [TStackTagPtr++], OperatorStack [OperatorStackPtr], sizeof (s_tag));
      
      //Parenthèse non trouvée
      if (OperatorStack [OperatorStackPtr]->type!=TAG_PARENTH0) 
        {error_code = ERROR_SYNTAX; break;}
    }
    
    //Opérateurs
    else if (tag_type!=TAG_VIRGULE)
    {
      //Ajoute signe opérateur dans la pile d'expressions
      if (OperatorStackPtr && OperatorStack [OperatorStackPtr-1]->type!=TAG_PARENTH0)
      {
        //Echange opérateurs
        if (StackTag [i].priority<=OperatorStack [OperatorStackPtr-1]->priority) 
          memcpy (&TStackTag [TStackTagPtr++], OperatorStack [--OperatorStackPtr], sizeof (s_tag));
      }   
      
      //Ajoute signe dans la pile d'opérateurs
      OperatorStack [OperatorStackPtr++] = &StackTag [i];
    }
    
    //Ligne trop longue
    if (OperatorStackPtr==MAX_OPERATOR_STACK)
      {error_line = ERROR_LINETOOLONG; break;}
  }
  
  //Dépiler la pile d'opérateurs
  while (OperatorStackPtr--)
  {
    if (OperatorStack [OperatorStackPtr]->type==TAG_PARENTH0)
      {error_code = ERROR_SYNTAX; break;}
    
    memcpy (&TStackTag [TStackTagPtr++], OperatorStack [OperatorStackPtr], sizeof (s_tag));
  }
  
  
  /*char buffer[51] = {};
  
  for (int i=0; i<TStackTagPtr; i++)
    strncat (buffer, TStackTag [i].string.data, TStackTag [i].string.size);

  ClrScr ();
  printf_xy (0, 30, "%s", buffer);

  ngetchx ();*/
  
  
  StackTagPtr = 0; //Vide la pile
  if (error_code!=ERROR_NOERROR) return FALSE;
  return TRUE;
}


Si vous avez des idées d'optimisation, n'hésitez pas ou encore des noms de fonctions bien plus pratique. :)
-Edité le Mercredi 14 juillet 2004 à 02:32 par geogeo-
-Edité le Mercredi 14 juillet 2004 à 02:50 par geogeo-
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°27   Marquer comme non lu.
Sasume Ecrit le: Jeudi 15 juillet 2004 à 08:52 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

J'ai l'impression que dans une expression parenthésée par exemple, on peut mettre un peu ce que l'on veut (déclaration de variable par exemple).

Ta fonction pour remettre de l'ordre dans la pile est assez obscure pour moi, à mon avis elle est assez lente en plus, enfin, il faut voir...

Sinon, quelques idées de choses qui pourraient accélérer le parsing :
Pour savoir si un caractère est une lettre, un opérateur, un chiffre, etc... tu pourrais utiliser un tableau de bits.
Par exemple :
char tab_num[256]={0,0,0,0,...,1,1,...,0,00};
#define isnum(c) tab_num[c]

Et pour éviter de dépenser un tableau de 256 octets à chaque fois, vu que tu n'utilises qu'un bit à chaque fois, tu peux les concaténer :
typedef struct
{
unsigned char alpha:1,num:1,operator:1,...
}bits;

bits tab[256]={...};

#define isalpha(c) tab[c] & 0x80
#define isnum(c) tab[c] & 0x40
#define isop(c) tab[c] & 0x20

Bien sûr, ça n'est avantageux que pour les classes de tokens qui peuvent être reconnus à partir de plusieurs caractères différents (pour la virgule, l'espace, la parenthèse ouvrante/fermante ça devient inutile).

Sinon, deuxième idée : pour les tokens d'un caractère et un seul, je te conseill d'utiliser la valeur de ce caractère lui-même comme valeur de TAG, par exemple pour les opérateurs *,/,+,-,^, ça te donnerait ce code :

#define TAG_MUL '*'
#define TAG_DIV '/'

...

if(isop(*ptr)) // +, -, /, *, ^
{
unsigned char code = *ptr;
...
}

Voilà pour mes idées :)
    
./Post n°28   Marquer comme non lu.
Sasume Ecrit le: Jeudi 15 juillet 2004 à 10:38 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Sinon, je ne sais pas si c'est mieux, mais moi j'aurais plutôt analysé le texte token par token plutôt que caractère par caractère.

Et puis j'aurais construit un arbre syntaxique d'où aurait découlé presque directement ta pile d'expressions.
Mais c'est peut-être plus compliqué à implémenter et je ne sais pas si ça aurait été plus efficace, je ne me rends pas compte si ton code pour réorganiser la pile est efficace ou non.

Sinon, tu fais comment pour gérer les accès aux variables ?
    
./Post n°29   Marquer comme non lu.
geogeo Ecrit le: Jeudi 15 juillet 2004 à 12:28 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


J'ai l'impression que dans une expression parenthésée par exemple, on peut mettre un peu ce que l'on veut (déclaration de variable par exemple).


Oui on peut faire beaucoup de chose.

Ta fonction pour remettre de l'ordre dans la pile est assez obscure pour moi, à mon avis elle est assez lente en plus, enfin, il faut voir...


Lente? Comment ça? Tu as une méthode plus rapide que l'algo de l'aiguillage?

Sinon, quelques idées de choses qui pourraient accélérer le parsing :
Pour savoir si un caractère est une lettre, un opérateur, un chiffre, etc... tu pourrais utiliser un tableau de bits.
Par exemple :
char tab_num[256]={0,0,0,0,...,1,1,...,0,00};
#define isnum(c) tab_num[c]

Et pour éviter de dépenser un tableau de 256 octets à chaque fois, vu que tu n'utilises qu'un bit à chaque fois, tu peux les concaténer :
typedef struct
{
unsigned char alpha:1,num:1,operator:1,...
}bits;

bits tab[256]={...};

#define isalpha(c) tab[c] & 0x80
#define isnum(c) tab[c] & 0x40
#define isop(c) tab[c] & 0x20

Bien sûr, ça n'est avantageux que pour les classes de tokens qui peuvent être reconnus à partir de plusieurs caractères différents (pour la virgule, l'espace, la parenthèse ouvrante/fermante ça devient inutile).


Je vois, pourquoi pas mais je trouve ça un peu lourd.


Sinon, deuxième idée : pour les tokens d'un caractère et un seul, je te conseill d'utiliser la valeur de ce caractère lui-même comme valeur de TAG, par exemple pour les opérateurs *,/,+,-,^, ça te donnerait ce code :

#define TAG_MUL '*'
#define TAG_DIV '/'

...

if(isop(*ptr)) // +, -, /, *, ^
{
unsigned char code = *ptr;
...
}

Voilà pour mes idées


Oui c'est pas bête ça. :)

Sinon, je ne sais pas si c'est mieux, mais moi j'aurais plutôt analysé le texte token par token plutôt que caractère par caractère.


Comment veux-tu faire? Un texte est une suite de caractères, il faut obligatoirement lire caractère après caractère.

Et puis j'aurais construit un arbre syntaxique d'où aurait découlé presque directement ta pile d'expressions.
Mais c'est peut-être plus compliqué à implémenter et je ne sais pas si ça aurait été plus efficace, je ne me rends pas compte si ton code pour réorganiser la pile est efficace ou non.


Oula un arbre, faut même pas y penser, sur PC ou une machine bien plus rapide, pourquoi pas mais là sur TI. :(
Ensuite l'algo de l'aiguillage est très puissant puisqu'il est capable de sortir presque sans tests d'erreur une pile d'expressions utilisable directement.

Sinon, tu fais comment pour gérer les accès aux variables ?


Je sais pas encore mais je pense qu'une variable sera un index d'une table, la technique sera adoptée seulement pour les variable type nombre et non les chaîne de caractères.
-Edité le Jeudi 15 juillet 2004 à 12:33 par geogeo-
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°30   Marquer comme non lu.
Sasume Ecrit le: Jeudi 15 juillet 2004 à 14:51 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

geogeo :
J'ai l'impression que dans une expression parenthésée par exemple, on peut mettre un peu ce que l'on veut (déclaration de variable par exemple).


Oui on peut faire beaucoup de chose.

Je voulais par là dire que j'ai l'impression qu'on mettre un peu n'importe quoi, non ?

Ta fonction pour remettre de l'ordre dans la pile est assez obscure pour moi, à mon avis elle est assez lente en plus, enfin, il faut voir...


Lente? Comment ça? Tu as une méthode plus rapide que l'algo de l'aiguillage?

Je ne sais pas, je n'ai jamais touché à ce genre de trucs.
En voyant tes memcpy, je me suis dit que ça risquait d'être assez lent (au niveau des appels).
On peut appliquer l'algo de l'aiguillage sans memcpy, mais avec une pile (je crois que j'ai vu ça dans le topic de yN traitant de ce sujet).

Sinon, quelques idées de choses qui pourraient accélérer le parsing :
Pour savoir si un caractère est une lettre, un opérateur, un chiffre, etc... tu pourrais utiliser un tableau de bits.
Par exemple :

[...]

Bien sûr, ça n'est avantageux que pour les classes de tokens qui peuvent être reconnus à partir de plusieurs caractères différents (pour la virgule, l'espace, la parenthèse ouvrante/fermante ça devient inutile).


Je vois, pourquoi pas mais je trouve ça un peu lourd.

Je pense que ça pourrait accélérer un peu. Faut tester.
En tout cas, ce n'est pas vraiment lourd.
Mais bien sûr, ce n'est pas le plus important à optimiser, vaut mieux regarder ton algo.

Sinon, je ne sais pas si c'est mieux, mais moi j'aurais plutôt analysé le texte token par token plutôt que caractère par caractère.


Comment veux-tu faire? Un texte est une suite de caractères, il faut obligatoirement lire caractère après caractère.

Pardon, je me suis mal exprimé, je voulais dire qu'à chaque itération de ta boucle, reconnaître un token.
Je pense que ça peut simplifier les choses. Rendre le code plus clair en tout cas (mais pas significativement plus rapide à mon avis - ni plus lent).
Par exemple, si le premier caractère que tu lis est une lettre, tu continues à lire jusqu'à tomber sur un opérateur ou un chiffre, enfin n'importe quoi qui ne ferait pas partie d'un identificateur.

Et puis j'aurais construit un arbre syntaxique d'où aurait découlé presque directement ta pile d'expressions.
Mais c'est peut-être plus compliqué à implémenter et je ne sais pas si ça aurait été plus efficace, je ne me rends pas compte si ton code pour réorganiser la pile est efficace ou non.


Oula un arbre, faut même pas y penser, sur PC ou une machine bien plus rapide, pourquoi pas mais là sur TI. :(
Ensuite l'algo de l'aiguillage est très puissant puisqu'il est capable de sortir presque sans tests d'erreur une pile d'expressions utilisable directement.

OK, je n'y connais pas grand chose dans ce domaine, je te laisse expérimenter :)

Sinon, tu fais comment pour gérer les accès aux variables ?


Je sais pas encore mais je pense qu'une variable sera un index d'une table, la technique sera adoptée seulement pour les variable type nombre et non les chaîne de caractères.

Les variables doivent-elles impérativement être déclarées dans le code avant d'être utilisées ?
Je pense que le mieux serait de construire la table des symboles au moment de la tokenisation, comme ça, tu stockes tes variables dans une liste toute simple et quand tu continues de tokeniser, à chaque fois que tu vois un accès à une variable, tu la remplaces par son indice dans le tableau.
L'exécution sera vraiment rapide ainsi.
Le code tokenisé sera également plus petit.

Sinon, est-il possible d'écrire des fonctions dans le langage GFA basic ?
Et comptes-tu écrire une sorte de préprocesseur ?
    
./Post n°31   Marquer comme non lu.
geogeo Ecrit le: Jeudi 15 juillet 2004 à 16:48 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


Je voulais par là dire que j'ai l'impression qu'on mettre un peu n'importe quoi, non ?


Oui c'est ça.

Je ne sais pas, je n'ai jamais touché à ce genre de trucs.
En voyant tes memcpy, je me suis dit que ça risquait d'être assez lent (au niveau des appels).
On peut appliquer l'algo de l'aiguillage sans memcpy, mais avec une pile (je crois que j'ai vu ça dans le topic de yN traitant de ce sujet).


memcpy est là pour copier le contenu entier de la structure dans l'autre pile mais s'est probisoire puisque déplacer les pointeurs serait plus judicieux. Mais il y a quand même une pile, OperatorStack et TSTackTag.


Je pense que ça pourrait accélérer un peu. Faut tester.
En tout cas, ce n'est pas vraiment lourd.
Mais bien sûr, ce n'est pas le plus important à optimiser, vaut mieux regarder ton algo.


Ouai enfin de compte tu as raison. :)


Pardon, je me suis mal exprimé, je voulais dire qu'à chaque itération de ta boucle, reconnaître un token.
Je pense que ça peut simplifier les choses. Rendre le code plus clair en tout cas (mais pas significativement plus rapide à mon avis - ni plus lent).
Par exemple, si le premier caractère que tu lis est une lettre, tu continues à lire jusqu'à tomber sur un opérateur ou un chiffre, enfin n'importe quoi qui ne ferait pas partie d'un identificateur.


Je vois. Mon code sera plus lisible et donc c'est pas négligeable.


Les variables doivent-elles impérativement être déclarées dans le code avant d'être utilisées ?
Je pense que le mieux serait de construire la table des symboles au moment de la tokenisation, comme ça, tu stockes tes variables dans une liste toute simple et quand tu continues de tokeniser, à chaque fois que tu vois un accès à une variable, tu la remplaces par son indice dans le tableau.
L'exécution sera vraiment rapide ainsi.
Le code tokenisé sera également plus petit


Il n'y a pas besoin de déclaration, c'est un avantage non négligeable. Ensuite la méthode que tu décrits c'est la méthode auquel j'ai pensé.


Sinon, est-il possible d'écrire des fonctions dans le langage GFA basic ?


Plutôt procédures si elles sont internes au programme, quand aux fonctions en ASM/C ça sera un jeu d'enfant pour en importer. Le GFA Basic est d'une puissance impressionante. ;)

Et comptes-tu écrire une sorte de préprocesseur ?


Je ne sais pas encore, je verrai pas la suite.
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°32   Marquer comme non lu.
Sasume Ecrit le: Jeudi 15 juillet 2004 à 17:34 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

geogeo :
Je ne sais pas, je n'ai jamais touché à ce genre de trucs.
En voyant tes memcpy, je me suis dit que ça risquait d'être assez lent (au niveau des appels).
On peut appliquer l'algo de l'aiguillage sans memcpy, mais avec une pile (je crois que j'ai vu ça dans le topic de yN traitant de ce sujet).


memcpy est là pour copier le contenu entier de la structure dans l'autre pile mais s'est probisoire puisque déplacer les pointeurs serait plus judicieux. Mais il y a quand même une pile, OperatorStack et TSTackTag.

J'ai la flemme de vérifier en regardant ton code, mais il me semble que toi, tu utilises une pile d'expressions pour la sortie tokenisée de ton code, non ?
Moi je parlais d'une pile temporaire où tu empiles les opérateurs que tu dépiles quand c'est nécessaire.

Pardon, je me suis mal exprimé, je voulais dire qu'à chaque itération de ta boucle, reconnaître un token.
Je pense que ça peut simplifier les choses. Rendre le code plus clair en tout cas (mais pas significativement plus rapide à mon avis - ni plus lent).
Par exemple, si le premier caractère que tu lis est une lettre, tu continues à lire jusqu'à tomber sur un opérateur ou un chiffre, enfin n'importe quoi qui ne ferait pas partie d'un identificateur.


Je vois. Mon code sera plus lisible et donc c'est pas négligeable.

L'autre avantage que je vois est que tu pourras facilement autoriser les chiffres dans les identificateurs (j'ai la flemme de vérifier dans ton code si c'est le cas où non, mais en tout cas, c'est très simple à faire avec la méthode où on reconnaît un token à la fois).


Sinon, est-il possible d'écrire des fonctions dans le langage GFA basic ?


Plutôt procédures si elles sont internes au programme, quand aux fonctions en ASM/C ça sera un jeu d'enfant pour en importer. Le GFA Basic est d'une puissance impressionante. ;)

Bof, ça me paraît assez compliqué... Tu comptes faire comment ? Importer les libs dynamiques façon PreOs ?
Et cela n'a pas grand chose à voir avec la puissance du langage GFA Basic... #roll#
    
./Post n°33   Marquer comme non lu.
Sasume Ecrit le: Jeudi 15 juillet 2004 à 17:38 Déconnecté(e)    Voir le profil de Sasume Envoyer un email à Sasume Visiter le site WEB de Sasume Envoyer un message privé à Sasume  

Pour la reconnaissance token par token, j'ai cité un avantage qui me passait par la tête, mais je viens de penser que si par exemple, tu as la suite de caractères '!=' qui représente l'opérateur 'différent de' et l'opérateur '!' qui représente l'opérateur 'non booléen' (comme en C quoi), la reconnaissance des tokens serait probablement plus facile à coder avec cette technique qu'avec celle que tu utilises actuellement.
Je me trompe ?
    
./Post n°34   Marquer comme non lu.
geogeo Ecrit le: Jeudi 15 juillet 2004 à 20:15 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


J'ai la flemme de vérifier en regardant ton code, mais il me semble que toi, tu utilises une pile d'expressions pour la sortie tokenisée de ton code, non ?
Moi je parlais d'une pile temporaire où tu empiles les opérateurs que tu dépiles quand c'est nécessaire.


Bah OperatorStack es tlà pour ça. #confus#

L'autre avantage que je vois est que tu pourras facilement autoriser les chiffres dans les identificateurs (j'ai la flemme de vérifier dans ton code si c'est le cas où non, mais en tout cas, c'est très simple à faire avec la méthode où on reconnaît un token à la fois).


Oui, je vais modifier mon code...

Bof, ça me paraît assez compliqué... Tu comptes faire comment ? Importer les libs dynamiques façon PreOs ?
Et cela n'a pas grand chose à voir avec la puissance du langage GFA Basic...


Je ne sais pas encore mais pourquoi pas.

Et si la puissance du langage permet d'avoir une porte de sortie, executer des extensions, du code machine et non pas seulement se limiter aux fonctions fournis.

Pour la reconnaissance token par token, j'ai cité un avantage qui me passait par la tête, mais je viens de penser que si par exemple, tu as la suite de caractères '!=' qui représente l'opérateur 'différent de' et l'opérateur '!' qui représente l'opérateur 'non booléen' (comme en C quoi), la reconnaissance des tokens serait probablement plus facile à coder avec cette technique qu'avec celle que tu utilises actuellement.
Je me trompe ?


Ca change pas grand chose puisque dans mon cas les signes sont déjà tokenisé. Ca va alléger le code en 2 fonctions.
Une fonction pour établir les tokens comme <=, les chaînes de caractères, les nombres...
Une fonction pour définir les régles grammaticales du langage et générer une erreur si il le faut.
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
./Post n°35   Marquer comme non lu.
Ephyx Ecrit le: Jeudi 15 juillet 2004 à 20:55 Déconnecté(e)    Voir le profil de Ephyx Envoyer un email à Ephyx Visiter le site WEB de Ephyx Envoyer un message privé à Ephyx  


Un scanner et un parser :)
Lemuria & Sirius-B, chouette :D
    
./Post n°36   Marquer comme non lu.
Onur Ecrit le: Vendredi 16 juillet 2004 à 08:21 Déconnecté(e)    Voir le profil de Onur Envoyer un email à Onur Visiter le site WEB de Onur Envoyer un message privé à Onur  


geogeo :
Enfin de compte les tampons sont inutiles :D

ca je ne suis pas sur... demande aux filles
Je ne veux pas faire quelque chose de bien, je cherche l'excellence:ETP Studio...


et autres projets à finir avant 2010
    
./Post n°37   Marquer comme non lu.
Kevin Kofler Ecrit le: Vendredi 16 juillet 2004 à 11:52 Déconnecté(e)    Voir le profil de Kevin Kofler Envoyer un email à Kevin Kofler Visiter le site WEB de Kevin Kofler Envoyer un message privé à Kevin Kofler  


LOL
Membre de l'équipe de TIGCC: http://tigcc.ticalc.org
Mainteneur du portage Linux/Unix de TIGCC: http://tigcc.ticalc.org/linux/
Membre de l'équipe de CalcForge: http://www.calcforge.org:70/

Participez à la reprise de Ti-Gen!
    
./Post n°38   Marquer comme non lu.
geogeo Ecrit le: Vendredi 16 juillet 2004 à 12:15 Déconnecté(e)    Voir le profil de geogeo Envoyer un email à geogeo Visiter le site WEB de geogeo Envoyer un message privé à geogeo  


LOL
Webmaster du site.
Programmeur sur TI68K. Arkanoid, Nebulus, GFA-Basic.

Plus d'informations sur GFA-Basic (un langage Basic pour TI68K).
http://www.tigen.org/gfabasic
    
  :: Index » Forum Ti68K » Projets » GFA Basic oncalc (128 réponse(s))
Pages : 2/7     « 1 [2] 3 4 5 6 7 » »|

.Répondre à ce sujet
Les boutons de code
[B]old[I]talic[U]nderline[S]trikethrough[L]ine Flip Hori[Z]ontallyFlip [V]erticallySha[D]ow[G]low[S]poilerCode [G][C]ite
Bullet [L]istList Item [K] Link [H][E]mail[P]icture SmileysHelp
Couleurs :
Saisissez votre message
Activer les smileys
     

Forum de Ti-Gen v3.0 Copyright ©2004 by Geoffrey ANNEHEIM
Webmaster: Kevin KOFLER, Content Admins: list, Server Admins: Tyler CASSIDY and Kevin KOFLER, DNS Admin: squalyl
Page générée en 58.38ms avec 18 requetes