28 votes

Pourquoi l'analyseur PHP comprend-il "$x++-++$x", mais échoue sur "$x+++++$x" ?

J'ai un moteur qui effectue certaines opérations mathématiques et logiques en prenant des formules, des opérandes et des opérateurs dans un fichier. Toutes les opérations sont exécutées dans un eval et le résultat final est enregistré dans un autre fichier.

Ces fichiers sont souvent transférés via un réseau, j'essaie donc de les minimiser en supprimant tous les espaces avant et après les opérations. Pour autant que je sache, il n'y a pas de règles strictes à ce sujet, mais je suis tombé sur ce comportement :

$x = 1;
$result = $x++-++$x; // works
$result = $x+++++$x; // fails
$result = $x++ + ++$x; // works again
  1. Pourquoi PHP est-il confus par la syntaxe "+++++", mais accepte "++-++" ? En quoi le "plus" est-il meilleur que le "moins" ?

  2. Existe-t-il une liste d'opérateurs sensibles aux espaces ? aux espaces ?

35voto

Dekel Points 41575

L'analyseur syntaxique de PHP recherche l'élément ++ avant le dernier + et la syntaxe ($x++)++ n'a aucun sens, du fait que l'opérateur d'incrémentation doit être appliqué à une variable (et non à un entier, qui est le résultat de la première fonction $x++ ).

La préséance des opérations de l'opérateur se trouve ici :
http://php.net/manual/en/language.operators.precedence.php

$x+++++$x;
^ php parser starts here, find $x++
    ^ here there is a new ++, which has hight precedence to the next + char
      ^ here is the last +, which the php parser will find last.

Quand les deux ++ , ++ séparé par un signe moins, le code est en fait $x++ - ++$x un que le parseur PHP peut comprendre.

C'est aussi la raison pour laquelle $x++ + ++$x travaux.

12voto

DannyNiu Points 363

La réponse est que l'analyseur syntaxique recherche les tokens les plus longs avant de rechercher les plus courts. Par conséquent, ++++++ devient ++ ++ +, ce qui est insupportable pour l'interpréteur.

PHP est l'un des nombreux langages qui emprunte sa grammaire d'expression au C, donc cette note peut vous intéresser. Sur le projet C11 La section 6.4, clause 6, donne un exemple :

Le fragment de programme x+++++y est analysé comme x ++ ++ + y, ce qui viole une contrainte sur les opérateurs d'incrémentation, même si l'analyse x ++ + ++ y peut donner une expression correcte.

10voto

Sharon Levy Points 19

Un petit complément d'information. Lorsqu'un script PHP est "lexé", c'est-à-dire lorsqu'il est scanné, les tokens composant le script sont examinés. Une paire de caractères comme "++" signifie un jeton d'incrémentation, comme suit :

<ST_IN_SCRIPTING>"++" {
    RETURN_TOKEN(T_INC);
}

Cette "règle" se trouve dans le fichier Zend/language_scanner.l qui accompagne PHP lorsque vous le téléchargez et l'installez. La seule façon pour qu'un script, lorsqu'il est scanné, devienne intelligible pour le lexer en ce qui concerne les variables de pré- ou post-incrémentation est s'il y a une sorte de démarcation telle que l'espacement afin que chaque "+" soit correctement évalué dans son contexte.

Notez qu'il est déconseillé d'écrire un code comme celui qui suit :

  <?php

  $x=0;
  echo $x++ + ++$x;

même s'il sera lexé correctement. La raison pour laquelle nous nous opposons à ce style de codage est qu'il peut être moins qu'apparent pour les cerveaux humains quant à ce qui se passe réellement. L'ordre d'évaluation n'est pas ce qu'il semble être, c'est-à-dire qu'une variable est post-incrémentée et ensuite ajoutée à elle-même avec sa valeur pré-incrémentée.

Par le opcodes les pré- et post-incrémentations se produisent avant l'addition a lieu. Notez également que la post-incrémentation renvoie la valeur d'une variable et l'incrémente ensuite. Ainsi, initialement, la valeur 0 est attribuée à $x, qui est ensuite post-incrémenté de sorte qu'une variable temporaire est renvoyée avec une valeur de zéro. Ensuite, $x est incrémenté pour acquérir une valeur de un. Ensuite, $x est préincrémenté, et ainsi $x passe de la valeur un à deux et sa variable temporaire est évaluée à deux. Enfin, les deux variables temporaires sont ajoutées, de sorte que 0 + 2 == 2 ; voir aquí ainsi que aquí .

Aussi, une excellente lecture aquí .

Par ailleurs, dans ce cas, PHP se conforme à son prédécesseur, le langage de programmation C ; cf. aquí .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X