Est-il possible de rendre YACC (ou je suis mon cas MPPG) en sortie un arbre de syntaxe abstraite (AST). Toutes les choses que je suis en train de lire suggèrent qu'il est simple de faire YACC, mais j'ai du mal à voir comment savoir quand remonter un nœud dans l'arbre en le construisant.Rendre une sortie YACC un AST (arborescence de jetons)
Répondre
Avez-vous regardé the manual (cherchez "arbre d'analyse" pour trouver l'endroit)? Il suggère de mettre la création de noeuds dans une action avec vos descendants gauche et droit étant 1 $ et 3 $, ou quoi qu'ils puissent être. Dans ce cas, yacc se déplacerait vers le haut de l'arbre en votre nom plutôt que de le faire manuellement.
expansion sur le point de Hao et de the manual, vous voulez faire quelque chose comme ce qui suit:
En supposant que vous avez votre arbre de syntaxe abstraite avec fonction node
qui crée un objet dans l'arborescence:
expr : expr '+' expr
{
$$ = node('+', $1, $3);
}
Ce code se traduit par "Lors de l'analyse de l'expression avec un plus, prenez les descendants gauche et droit $1
/$3
et utilisez-les comme arguments pour le noeud.Enregistrer la sortie à $$
(la valeur de retour) de l'expression
$$ (du manuel):
Pour retourner une valeur, l'action normalement définit la pseudovariable `` $$ '' à une valeur .
Les autres réponses proposent de modifier la grammaire, ce n'est pas faisable lorsque vous jouez avec un C++ Grammer (plusieurs centaines de règles ..)
Heureusement, nous pouvons le faire automatiquement, en redéfinissant le débogage macros. Dans ce code, nous redéfinissons YY_SYMBOL_PRINT
actived avec YYDEBUG
:
%{
typedef struct tree_t {
struct tree_t **links;
int nb_links;
char* type; // the grammar rule
};
#define YYDEBUG 1
//int yydebug = 1;
tree_t *_C_treeRoot;
%}
%union tree_t
%start program
%token IDENTIFIER
%token CONSTANT
%left '+' '-'
%left '*' '/'
%right '^'
%%
progam: exprs { _C_treeRoot = &$1.t; }
|
| hack
;
exprs:
expr ';'
| exprs expr ';'
;
number:
IDENTIFIER
| '-' IDENTIFIER
| CONSTANT
| '-' CONSTANT
;
expr:
number
| '(' expr ')'
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '^' expr
;
hack:
{
// called at each reduction in YYDEBUG mode
#undef YY_SYMBOL_PRINT
#define YY_SYMBOL_PRINT(A,B,C,D) \
do { \
int n = yyr2[yyn]; \
int i; \
yyval.t.nb_links = n; \
yyval.t.links = malloc(sizeof *yyval.t.links * yyval.t.nb_links);\
yyval.t.str = NULL; \
yyval.t.type = yytname[yyr1[yyn]]; \
for (i = 0; i < n; i++) { \
yyval.t.links[i] = malloc(sizeof (YYSTYPE)); \
memcpy(yyval.t.links[i], &yyvsp[(i + 1) - n], sizeof(YYSTYPE)); \
} \
} while (0)
}
;
%%
#include "lexer.c"
int yyerror(char *s) {
printf("ERROR : %s [ligne %d]\n",s, num_ligne);
return 0;
}
int doParse(char *buffer)
{
mon_yybuffer = buffer;
tmp_buffer_ptr = buffer;
tree_t *_C_treeRoot = NULL;
num_ligne = 1;
mon_yyptr = 0;
int ret = !yyparse();
/////////****
here access and print the tree from _C_treeRoot
***///////////
}
char *tokenStrings[300] = {NULL};
char *charTokenStrings[512];
void initYaccTokenStrings()
{
int k;
for (k = 0; k < 256; k++)
{
charTokenStrings[2*k] = (char)k;
charTokenStrings[2*k+1] = 0;
tokenStrings[k] = &charTokenStrings[2*k];
}
tokenStrings[CONSTANT] = "CONSTANT";
tokenStrings[IDENTIFIER] = "IDENTIFIER";
extern char space_string[256];
for (k = 0; k < 256; k++)
{
space_string[k] = ' ';
}
}
les feuilles sont créés juste avant le retour dans le FLEX lexer
- 1. Recherche de jetons dans une chaîne Java
- 2. erreur jetons yacc/bison. « >>> » et « >> » à la fois numéro attribué 62
- 3. Traverser une arborescence de répertoires
- 4. Ayant une arborescence riche
- 5. Rendre un service Web ASP.NET en sortie Flux RSS
- 6. Créer une arborescence dans WPF
- 7. Existe-t-il un moyen d'analyser une arborescence de dépendances à partir d'une sortie de script de génération?
- 8. yacc, appliquer une seule fois la règle
- 9. Puis-je utiliser jquery pour sélectionner une sous-arborescence dans une arborescence xml?
- 10. Grammaires YACC multiples dans un programme
- 11. transformer la source de Jython/ast
- 12. Lisp grammar in yacc
- 13. Chaîne d'affichage jetons
- 14. Yacc Problème: Rendre les données disponibles dans la prochaine Non Terminal
- 15. Rendre les erreurs de sortie Firebug quelque part persistantes
- 16. Comment rendre la sortie d'une fonction différente de l'impression?
- 17. Impossible de rendre la sortie à l'écran en utilisant PHP?
- 18. Comment rendre la sortie de log4perl plus facile à lire?
- 19. Jetons réservés aux lignes de commande
- 20. À quoi devrait ressembler mon AST pour des transformations faciles?
- 21. yacc/bison problème combiné mot
- 22. Comment puis-je analyser une liste de paires nom = valeur dans un générateur d'analyseur (ANTLR, YACC, etc.)?
- 23. Yacc/Jay grammaire pour JavaScript?
- 24. Incorporation d'une arborescence YUI dans un menu
- 25. Traduire le code C# en AST?
- 26. NSTextView avec des jetons
- 27. Copier une arborescence de répertoires dans un seul répertoire sur une ligne de commande
- 28. Rendre la sortie pyunit show pour chaque assertion
- 29. Rendre un contrôle utilisateur à une chaîne
- 30. Existe-t-il un moyen de rendre la sortie PrintWriter au format UNIX?
Merci, j'avais vu auparavant dans le livre de lexx & yacc. Mais je l'ai en quelque sorte écrit comme une impasse. Pour que tout se bloque, vous devez modifier le LexType qui est défini dans l'étiquette d'union % union { private state state; ... LexValue (État de l'état, objet enfant1, objet enfant2) {...} } Cela vous permet de stocker un nœud d'arbre comme état. Vous pouvez ensuite lui affecter des données en utilisant l'alias $$ $$ = new LexValue (State.SchemaImport, $ 3, $ 5); Remarque: Le lexeur doit également insérer ses données de jeton dans cette structure. Facile quand vous savez comment ... – Sprotty