Permettez-moi de commencer par dire que je ne sais absolument rien sur la manière dont les analyseurs de travail. Cela dit, la ligne 296 de gramme.y définit les jetons suivants pour représenter affectation dans l' (YACC?) analyseur de R utilise:
%token LEFT_ASSIGN EQ_ASSIGN RIGHT_ASSIGN LBB
Ensuite, sur les lignes 5140 grâce à 5150 de gramme.c, cela ressemble le correspondant du code C:
case '-':
if (nextchar('>')) {
if (nextchar('>')) {
yylval = install_and_save2("<<-", "->>");
return RIGHT_ASSIGN;
}
else {
yylval = install_and_save2("<-", "->");
return RIGHT_ASSIGN;
}
}
Enfin, à partir de la ligne de 5044 de gramme.c, la définition de l' install_and_save2
:
/* Get an R symbol, and set different yytext. Used for translation of -> to <-. ->> to <<- */
static SEXP install_and_save2(char * text, char * savetext)
{
strcpy(yytext, savetext);
return install(text);
}
Encore une fois, l'ayant aucune expérience de travail avec des analyseurs, il semble qu' ->
et ->>
sont directement traduits en <-
et <<-
, respectivement, à un niveau très faible dans le processus d'interprétation.
Vous apporté un très bon point de se demander comment parser "sait" pour inverser la arguments au ->
- considérant qu' ->
semble être installé dans le R de la table des symboles en tant que <-
- et donc être capable d'interpréter correctement x -> y
comme y <- x
et pas x <- y
. Le mieux que je puisse faire est de fournir plus de la spéculation que je continue à trouver des "preuves" à l'appui de mes affirmations. J'espère que certains miséricordieux YACC expert tomberez sur cette question et de fournir un peu de perspicacité; je ne vais pas retenir mon souffle sur que si.
Retour à la lignes 383 et 384 de gramme.y, cela ressemble plus à une logique d'analyse des LEFT_ASSIGN
et RIGHT_ASSIGN
symboles:
| expr LEFT_ASSIGN expr { $$ = xxbinary($2,$1,$3); setId( $$, @$); }
| expr RIGHT_ASSIGN expr { $$ = xxbinary($2,$3,$1); setId( $$, @$); }
Bien que je ne peux pas vraiment faire des têtes ou queues de ce fou de la syntaxe, j'ai remarqué que les deuxième et troisième arguments au xxbinary
sont convertis en WRT LEFT_ASSIGN
(xxbinary($2,$1,$3)
) et RIGHT_ASSIGN
(xxbinary($2,$3,$1)
).
Voici ce que je nous vois dans ma tête:
LEFT_ASSIGN
Scénario: y <- x
-
$2
est la deuxième "argument" à l'analyseur dans l'expression ci-dessus, c'est à dire <-
-
$1
est la première, à savoir y
-
$3
est le troisième; x
Par conséquent, la suite (C?) appel xxbinary(<-, y, x)
.
L'application de cette logique d' RIGHT_ASSIGN
, c'est à dire x -> y
, combiné avec ma conjecture sur <-
et ->
se sont inversées,
-
$2
se traduit d' ->
de <-
-
$1
est x
-
$3
est y
Mais comme le résultat est xxbinary($2,$3,$1)
au lieu de xxbinary($2,$1,$3)
, le résultat est toujours xxbinary(<-, y, x)
.
Profitant de cela un peu plus loin, nous avons la définition de l' xxbinary
sur la ligne 3310 de gramme.c:
static SEXP xxbinary(SEXP n1, SEXP n2, SEXP n3)
{
SEXP ans;
if (GenerateCode)
PROTECT(ans = lang3(n1, n2, n3));
else
PROTECT(ans = R_NilValue);
UNPROTECT_PTR(n2);
UNPROTECT_PTR(n3);
return ans;
}
Malheureusement, je ne pouvais pas trouver une définition appropriée de l' lang3
(ou de ses variantes lang1
, lang2
, etc...) dans le R du code source, mais je suppose que c'est utilisé pour l'évaluation de fonctions spéciales (c'est à dire des symboles) d'une manière qui est synchronisé avec l'interprète.
Les mises à jour
Je vais essayer de répondre à certaines de vos questions dans les commentaires du mieux que je peux donné mon (très) limité de connaissances de l'analyse de processus.
1) Est-ce vraiment le seul objet dans la R qui se comporte comme ça??? (J'ai
obtenu dans l'esprit de John Chambers devis par Hadley du livre: "Tout
qui existe, c'est un objet. Tout ce qui arrive est un appel de fonction."
Ce bien se trouve en dehors de ce domaine -- est-il autre chose comme
cette?
Tout d'abord, je suis d'accord que cela se trouve à l'extérieur de ce domaine. Je crois Chambres de devis concerne la R de l'Environnement, c'est à dire des processus qui sont tous de prendre place après ce faible niveau de l'analyse de phase. Je reviendrai un peu plus loin, cependant. De toute façon, le seul autre exemple de ce genre de comportement que j'ai pu trouver est l' **
opérateur, qui est un synonyme pour le plus commun opérateur exponentiel ^
. Comme avec d'attribution de droits, **
ne semble pas être "reconnu" comme un appel de fonction, etc... par l'interprète:
R> `->`
#Error: object '->' not found
R> `**`
#Error: object '**' not found
J'ai trouvé ce parce que c'est le seul autre cas où l' install_and_save2
est utilisé par le C de l'analyseur:
case '*':
/* Replace ** by ^. This has been here since 1998, but is
undocumented (at least in the obvious places). It is in
the index of the Blue Book with a reference to p. 431, the
help for 'Deprecated'. S-PLUS 6.2 still allowed this, so
presumably it was for compatibility with S. */
if (nextchar('*')) {
yylval = install_and_save2("^", "**");
return '^';
} else
yylval = install_and_save("*");
return c;
2) Quand exactement est-ce possible? J'ai dans l'esprit que substitut(3
-> y) a déjà retournée à l'expression; je ne pouvais pas comprendre à partir de la source de ce substitut ne qui aurait ping la YACC...
Bien sûr, je suis toujours spéculer ici, mais oui, je pense que nous pouvons supposer que lorsque vous appelez substitute(3 -> y)
, du point de vue de la substitution de la fonction, l'expression a toujours été y <- 3
; par exemple, la fonction est complètement inconscients que vous avez tapé 3 -> y
. do_substitute
,, comme 99% de la C fonctions utilisées par R, ne gère SEXP
arguments - EXPRSXP
dans le cas d' 3 -> y
(== y <- 3
- )), je crois. C'est ce à quoi je faisais allusion ci-dessus, quand j'ai fait une distinction entre le R de l'Environnement et de l'analyse de processus. Je ne pense pas qu'il y a quelque chose qui déclenche spécifiquement l'analyseur de printemps dans l'action, mais plutôt tout ce que vous avez entrés dans l'interprète obtient analysée. J'ai fait un peu plus de lecture sur la YACC / Bison analyseur générateur de la nuit dernière, et comme je le comprends (un.k.un. ne pas parier la ferme sur ce point), le Bison utilise la grammaire que vous définissez (en .y
fichier(s)) pour générer un analyseur syntaxique en C - à-d. une fonction en C qui effectue l'analyse de l'entrée. À son tour, tout ce que vous avez saisie dans un R de session est d'abord traité par cette C fonction d'analyse syntaxique, qui ensuite les délégués les mesures à prendre dans le R de l'Environnement (j'utilise ce terme vaguement par la voie). Au cours de cette phase, lhs -> rhs
obtiendrez traduit rhs <- lhs
, **
de ^
, etc... Par exemple, c'est un extrait de l'une des tables de fonctions primitives dans les noms.c:
/* Language Related Constructs */
/* Primitives */
{"if", do_if, 0, 200, -1, {PP_IF, PREC_FN, 1}},
{"while", do_while, 0, 100, 2, {PP_WHILE, PREC_FN, 0}},
{"for", do_for, 0, 100, 3, {PP_FOR, PREC_FN, 0}},
{"repeat", do_repeat, 0, 100, 1, {PP_REPEAT, PREC_FN, 0}},
{"break", do_break, CTXT_BREAK, 0, 0, {PP_BREAK, PREC_FN, 0}},
{"next", do_break, CTXT_NEXT, 0, 0, {PP_NEXT, PREC_FN, 0}},
{"return", do_return, 0, 0, -1, {PP_RETURN, PREC_FN, 0}},
{"function", do_function, 0, 0, -1, {PP_FUNCTION,PREC_FN, 0}},
{"<-", do_set, 1, 100, -1, {PP_ASSIGN, PREC_LEFT, 1}},
{"=", do_set, 3, 100, -1, {PP_ASSIGN, PREC_EQ, 1}},
{"<<-", do_set, 2, 100, -1, {PP_ASSIGN2, PREC_LEFT, 1}},
{"{", do_begin, 0, 200, -1, {PP_CURLY, PREC_FN, 0}},
{"(", do_paren, 0, 1, 1, {PP_PAREN, PREC_FN, 0}},
Vous remarquerez qu' ->
, ->>
, et **
ne sont pas définis ici. Autant que je sache, R primitive des expressions telles que <-
et [
, etc... sont les plus proches de l'interaction de la R de l'Environnement a jamais avec tout C sous-jacente de code. Ce que je suggère, c'est que par cette étape dans le processus (de vous taper un ensemble de caractères dans l'interprète et la frappe de la touche 'Enter', jusqu'à la véritable évaluation valide de la R de l'expression), l'analyseur a déjà travaillé sa magie, qui est pourquoi vous ne pouvez pas obtenir une définition de fonction pour l' ->
ou **
en les entourant avec des backticks, comme vous pouvez généralement.