
./59 Donc ce n’est pas une expression ^^
Operande Stack Operator Stack Assert OpcRef == OpRef or Opcrec == OpRef-1 Add Operande (op): Op[OpRef++] = op Add Operator (opc): While OpcRef>=1 && Priority(opc) <= Priority(Opc[OpcRef]) code = Opc[--OpcRef] op = code( Op[--OpRef], Op[--OpRef]) OpRef[OpRef++] = op 3 Prio: +,- *,/ ^ Finish: While OpcRef>=1 func = Opc[--OpcRef] op = func( Op[--OpRef], Op[--OpRef]) OpRef[OpRef++] = op ASSERT (OpRef == 1)
Folco (./61) :Ah, donc c’est une expression ^^Sasume (./60) :
./59 Donc ce n’est pas une expression ^^
Sauf que :move.l #kernel::LibsBegin+42,d0 est une expression comme une autre.
Sasume (./63) :
Ah, donc c’est une expression ^^
Dans ce cas le symbole donne son adresse, non ?
Sasume (./63) :
Le pseudo code explique comment empiler les opérateurs de façon à respecter leurs priorités respectives.
Sasume (./57) :
Déjà, est-ce que c’est vraiment nécessaire de considérer que expr(identificateur) corresponde au produit expr × identificateur ? Si oui, le plus simple serait d’interdire l’utilisation de a0 comme identificateur, c’est un mot réservé.
squalyl (./56) :
l'idéal c'est d'arriver à transformer une expression 1 * ( 2 + 3 ) en RPN
MainEval( EXPR ) Si (EXPR n'a pas d'opétateur) Alors EXPR Sinon Eval( arg1 OP arg2 ) // EXPR == arg1 OP arg2 // arg1 est la première valeur numérique trouvée // arg2 est le reste de l'expression, et peut contenir // lui-même plusieurs opérations // OP est l'opérateur qui les sépare Eval( arg1 OP arg2 ) Si (arg2 n'a pas d'opérateurs) Alors OP( arg1 , arg2 ) Sinon Si Priorite( OP1 ) > Priorite( OP2 ) // On décompose alors arg2 == arg3 OP2 arg4 Alors OP1( arg1 , arg3 ) -> arg1 // On résoud l'opérateur prioritaire Eval( arg1 OP2 arg4 ) // Récursion terminale, vu qu'on a déjà // le premier résultat Sinon OP1( arg1 , Eval( arg3 OP2 arg4 )) // Là on a Priorite( OP1 ) < Priorite( OP2 ) // Récursion profonde, vu qu'on a pas encore le // résultat de arg1 OP arg2
squalyl (./73) :
Ecoute, je sais pas si c'est exactement ça, mais en tout cas tu chauffes, c'est clair.
squalyl (./73) :
C'est là qu'il te faudrait connaitre des langages pratiques pour pouvoir tester ça avant de l'implémenter en asm ^^
Chiffres : $~0123456789abcdefABCDEF Opérateurs unaires, à résoudre immédiatement : ~ - Opérateurs, par ordre de priorité : [+ -] [* /] [<< >>] [& |] Opérateur mettant un flag global : # IMM MainEval( EXPR ) Si (EXPR n'a pas d'opétateur) Alors EXPR -> IMM // Il ne s'agit que d'un chiffre ou d'un symbole à lire Sinon EXPR -> arg1 OP arg2 // On décompose EXPR // arg1 est la première valeur numérique trouvée // arg2 est le reste de l'expression, et peut contenir // lui-même plusieurs opérations // OP est l'opérateur qui les sépare Eval( arg1 OP arg2 ) IMM Eval( arg1 OP arg2 ) Si (arg2 commence par une parenthèse) Alors Eval( arg1 OP MainEval( arg2 )) // récursion terminale Si (arg2 n'a pas d'opérateur) Alors OP( arg1, arg2 ) Sinon arg2 -> arg3 OP2 arg4 // On décompose alors arg2 == arg3 OP2 arg4 Si Priorite( OP1 ) > Priorite( OP2 ) Alors OP1( arg1 , arg3 ) -> arg1 // On résoud l'opérateur prioritaire Eval( arg1 OP2 arg4 ) // Récursion terminale, vu qu'on a déjà // le premier résultat Sinon OP1( arg1 , Eval( arg3 OP2 arg4 )) // Là on a Priorite( OP1 ) < Priorite( OP2 ) // Récursion profonde, vu qu'on a pas encore le // résultat de arg1 OP arg2 arg1 est une valeur numérique arg2 est un pointeur la suite de l'expression OP est un tag
Sasume (./76) :
Je ne suis pas sûr de voir comment ce sera appelé avec, mettons, l’expression a + b * c en entrée ? Que vaudra arg1 ? Et que vaudra arg2 ?
Sasume (./76) :
À chaque fois tu seras obligé d’aller jeter un coup d’œil en avance dans les arguments pour voir s’ils contiennent des expressions compliquées
Sasume (./76) :
Enfin, peut-être que ton idée marche, mais pourquoi ne pas suivre l’algorithme plus simple donné dans wikipedia ?
Sasume (./76) :
Et, surtout, est-ce qu’une telle méthode te permettra de gérer les expressions contenant des labels encore inconnus ?
/* We can have: + an operator: + - * / ^ + a variable: starts with a letter + a function: starts with a lettre, finished by a '(' + an int: starts with a number. + a float: starts with a number. Contains 'E' and '.'. + a list: starts with '{' + a parenthesis: starts with '(' We use: + a stack of operande + a stack of operator. Read a char: Phase 1: Get the new operand. Skip SPACE Read negate operator, and skip it. If it is a letter, scans for variable/function. If it is a variable, push it in the operand stack. If it is a function, parse the arguments as a list - allow list- and push it in the operand stack. If it is a number, scans for 'E' or '.' while there are digits, and then: Build Int and push in the operand stack. Build Float and push in the operand stack. If it is a parenthesis, parse the sub-express recursively, check for and ending ')' and push in the operand stack. Else stop parsing (Pop last Operator before finishing). If there was a negate operator, negate the pushed operator (Well in fact, it is a little big more complicated due to -x^-2 ;) ) Phase 2: Evaluate the old operators if needed and push the new one. Skip SPACE. If it is an operator, add it in the operator stack so that all pushed operators have bigger priority than this one. If an already pushed operator has higher or equal priority Then eval the operator (pop it) over the two pushed operands (pop them), and push the new evaluated operand. Else stop parsing. Go to Phase 1 to read the new operand. Phase Finish: Finish by evaluating the pushed operators: While OpcRef>=1 func = Opc[--OpcRef] op = func( Op[--OpRef], Op[--OpRef]) OpRef[OpRef++] = op
Folco (./84) :
T'as une taille de pile fixe ?
IMM , Ptr_apres_EXPR MainEval( EXPR ) Si (EXPR n'a pas d'opetateur) Alors Si (EXPR termine par une parenthese fermante) BR_COUNT-- // Erreur si <0 EXPR -> IMM // Il ne s'agit que d'un chiffre ou d'un symbole à lire Sinon EXPR -> arg1 OP arg2 // On décompose EXPR // arg1 est la premiere valeur numerique trouvee // arg2 est le reste de l'expression, et peut contenir // lui-meme plusieurs opérations // OP est l'operateur qui les sépare Eval( arg1 OP arg2 ) IMM Eval( arg1 OP arg2 ) Si (arg2 commence par une parenthese) Alors BR_COUNT++ MainEval( arg2 ) -> arg2 // On stocke le resultat Si (Operateur_apres_parenthese) // Du boulot apres la parenthese ? Alors Si( Priorite( OP ) < Priorite(Operateur_apres_parenthese) // Si c'est prioritaire Alors arg2 -> arg3 OP2 arg4 // On decompose OP( arg1, Eval( arg3 OP2 arg4 )) // Et on appelle dans le bon ordre Sinon Eval( OP1( arg1, arg2 ) OP2 arg3) // Sinon on resoud la premiere operande // avec le resultat de la parenthese Sinon OP( arg, arg2 ) // Si il n'y a rien apres la parenthese, // on a une simple operation a faire Si (arg2 n'a pas d'opérateur) Alors OP( arg1, arg2 ) Sinon arg2 -> arg3 OP2 arg4 // On decompose alors arg2 == arg3 OP2 arg4 Si Priorite( OP1 ) > Priorite( OP2 ) Alors OP1( arg1 , arg3 ) -> arg1 // On resoud l'operateur prioritaire Eval( arg1 OP2 arg4 ) // Recursion terminale, vu qu'on a deja // le premier resultat Sinon OP1( arg1 , Eval( arg3 OP2 arg4 )) // La on a Priorite( OP1 ) < Priorite( OP2 ) // Recursion profonde, vu qu'on a pas encore le // resultat de arg1 OP arg2 arg1 est une valeur numerique arg2 est un pointeur la suite de l'expression OP est un tag