Answer:
Name (of a species), number (of observed animals), and the keywords species, declarations, done, observation and observations.
Answer:
Answer:
input -> manydeclarations declarations done manyobservations observations done
manydeclarations -> onedeclaration manydeclarations | ε
onedeclaration -> species name
manyobservations -> oneobservation manyobservations | ε
oneobservation -> observation name number
Download a solution: animals.l
%{ #include "animals.tab.h" %} %% [\n\t ] { /* Ignore whitespace */ } "species" { return SPECIES; } "declarations" { return DECLARATIONS; } "done" { return DONE; } "observation" { return OBSERVATION; } "observations" { return OBSERVATIONS; } [A-ZÅÄÖa-zåäö]+ { return NAME; } [0-9]+ { return NUMBER; } . { fprintf(stderr, "[scanner: ignoring unknown character: '%c' (%d)]\n", *yytext, *yytext); } %%
Download a solution: animals.y
This Makefile might be useful: Makefile. Type "make animals" to build the Flex- and Bison-based program. Type "make animalsparser" to build the program based on the hand-coded parser in question 7 below.
%{ #include <stdio.h> extern void yyerror(const char *); extern int yylex(void); %} %token SPECIES DECLARATIONS DONE NAME OBSERVATION OBSERVATIONS NUMBER %define parse.error verbose %start input %% input : manydeclarations DECLARATIONS DONE manyobservations OBSERVATIONS DONE { printf("Done!\n"); } ; manydeclarations : onedeclaration manydeclarations | %empty ; onedeclaration : SPECIES NAME ; manyobservations : oneobservation manyobservations | %empty ; oneobservation : OBSERVATION NAME NUMBER ; %% int main() { printf("Enter a complete animal input. End with the keyword \"done\" and EOF.\n"); yyparse(); printf("Ok!\n"); return 0; } void yyerror(const char *s) { printf("Incorrect animal input! Error message: %s\n", s); } int yywrap(void) { return 1; }
Download a solution: animalsparser.c
Since the grammar given as a solution above already is suitable for constructing a predictive recursive-descent parser, we can use it as is. Otherwise, we would have had to make some transformations.
int lookahead; void match(int expected) { if (lookahead != expected) error(); else lookahead = scan(); } void input(void) { manydeclarations(); match(DECLARATIONS); match(DONE); manyobservations(); match(OBSERVATIONS); match(DONE); } void manydeclarations(void) { if (lookahead == SPECIES) { onedeclaration(); manydeclarations(); } else { /* Empty */ } } void onedeclaration(void) { match(SPECIES); match(NAME); } void manyobservations(void) { if (lookahead == OBSERVATION) { oneobservation(); manyobservations(); } else { /* Empty */ } } void oneobservation(void) { match(OBSERVATION); match(NAME); match(NUMBER); } void parse() { lookahead = scan(); input(); printf("Ok.\n"); }