Hi Laura, if you want multiple different parsers (i.e. different .y files) in one binary, use renaming. See the "%name-prefix"-Option.
In this case, I guess you could stick with globals to store the parsing result. If you want to use multiple instances of the same parser simultaneously, turn the parser into a reentrant one. See the "%define api.pure full"-Option. In this case, I would add a function parameter to yyparse() to hand back the parsing result. The following example generates a reentrant parser (with renamed prefix) that stores the linked list of parsed words in a new function parameter to yyparse() and counts the number of parsed WORDS after yyparse() has finished. ================ %{ #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct elem { char *val; struct elem *next; } elem_t; elem_t *add_word(elem_t *words, char *val) { elem_t *word = (elem_t *)malloc(sizeof(elem_t)); if (word == NULL) { fprintf (stderr, "%s", "malloc failed"); exit(1); } word->val = val; word->next = words; return word; } %} %output "parser.c" %defines "parser.h" %name-prefix "yy1" %define api.pure full %parse-param { elem_t **words }; %union { char *str; } %token <str> WORD %start Input %% Input : WORD { *words = add_word(NULL, $1); printf("word: %s\n", yylval.str); } | Input WORD { *words = add_word(*words, $2); printf("word: %s\n", yylval.str); } ; %% int main() { elem_t *words = NULL; yy1parse(&words); int i = 0; while (words != NULL) { i++; words = words->next; } fprintf(stdout, "Parsed %d WORDS\n", i); } void yy1error(char *error) { fprintf(stderr, "%s", error); } int yy1lex(YYSTYPE *lvalp) { static int i = 0; while (i++ < 100) { lvalp->str = "testWord"; return WORD; } return 0; } ================ Yours, Alex On 04/02/2017 03:21 PM, Laura Morales wrote: > Thanks a lot Alex, this works great. > There is one more thing that I'd like to do. I'd like to have multiple > parsers available in the same codebase, such that I can invoke parser1() or > parser2() or parser-n(), and in turn get some data structure back depending > on the parser I called. Just as an example, let's say I want two parser: one > that returns an array of numbers (ignoring all other tokens), and another one > that only returns words (ignoring all other tokens). This soon gets messy > with global variables. > I've read in the documentation about the "prefix" option that allows me to > replace the "yy" namespace with something else, but if I understand correctly > there's another better option available: pure/reentrant parsers. This I > suppose, would get rid of globals, although I don't fully understand how this > "pure/reentrant" option work. > My question thus is how can I include multiple parsers together (in the same > program) while avoiding globals and also avoiding to turn my code into > spaghetti code? > > Thanks once more. > > ======================================================== > > Hi Laura, > > I would start with a global linked list that is filled in the semantic > actions. Building on your example: > > ================ > %{ > #include <stdio.h> > #include <stdlib.h> > > typedef struct elem { > char *val; > struct elem *next; > } elem_t; > > elem_t *words = NULL; > > void add_word(char *val) { > elem_t *word = (elem_t *)malloc(sizeof(elem_t)); > if (word == NULL) { > fprintf (stderr, "%s", "malloc failed"); > exit(1); } > word->val = val; > word->next = words; > words = word; > } > %} > > %output "parser.c" > %defines "parser.h" > > %union { char *str; } > > %token <str> WORD > > %start Input > > %% > > Input > : WORD { add_word(yylval.str); > printf("word: %s\n", yylval.str); } > | Input WORD { add_word(yylval.str); > printf("word: %s\n", yylval.str); } > ; > > %% > ================ > > Yours, Alex > _______________________________________________ help-bison@gnu.org https://lists.gnu.org/mailman/listinfo/help-bison