Flex and Bison how to find depth level of command
I have Big problem in Bison - I need to find maximum depth level of command (P) in if statement.. So i code this for language.l (FLEX)
%{
#include "jazyk.tab.h"
int max = 0;
int j = 0;
%}
%%
[ t]+
[Bb][Ee][Gg][Ii][Nn] return(LBEGIN);
[Ee][Nn][Dd] return(LEND);
[Ii][Ff] {j++; if(j>max)max=j; return(LIF);}
[Tt][Hh][Ee][Nn] return(LTHEN);
// command to find max depth level in If statement
[Pp] return(LP);
// V is statement
[Vv] return(LV);
[.] return(.);
[;] return(;);
[-+&~|^/%*(),!] { printf("unknown character in input: %cn", *yytext);}
[n] yyterminate();
%%
void maximum()
{
printf("Maximum depth level of command(P): %in", max);
}
And this for language.y (BISON)
%{
#include <stdio.h>
#define YYSTYPE float
void koniec(YYSTYPE);
extern char *yytext;
int counterIf;
int counterP;
%}
// define the "terminal symbol" token types (in CAPS by convention)
%token LBEGIN
%token LEND
%token LIF
%token LTHEN
%token LP
%token LV
%token .
%token ;
%start PROGRAM
%%
// the first rule defined is the highest-level rule
PROGRAM: LBEGIN prikazy LEND .
prikazy: prikaz ; prikazy
prikaz: LIF LV LTHEN prikaz {counterIf++;}
prikaz:
prikaz: LP
%%
int main() {
counterIf = 0;
counterP = 0;
printf("Examples to better copy in console: n");
printf("begin p; p; end. n");
printf("begin if v then p; end.n");
printf("begin p; if v then if v then p; p; end.n");
printf("n");
if (yyparse()==0){
printf("Sucesfull n");
printf("If counter: n");
printf("%d n", counterIf);
printf("Maximal depth level of command(P): n");
printf("%d n", counterP);
maximum();
}
else
printf("Wrong n");
}
For example of functionality - when i write begin if v then p; end.
begin if v then p; end.
Result must be: IF: 1; Max depth level of P: 2; Or:
begin
p;
if v then
if v then p;
p;
end.
Result: IF: 2; max depth: 3;
Im really desperate right now. Please help me with depth counter :-( (And im sorry its not all in English)
Don't try to compute the depth in the scanner. The scanner has no idea about the structure of the program. The parser understands the nesting, so it is where you should count the depth.
Since you're not currently using semantic values for anything, I took the liberty of using them for the statistics. If you had real semantic values, you could add the statistics structure as a member, or use the location value.
When the parser encounters an if
statement, it knows that there is one more if
statement and that the current nesting depth is one more than the nesting depth of the target of the if
.
I added a syntax for if
statements with blocks because it was trivial and it makes the program a bit more interesting. When the parser adds a statement to a block, it needs to sum the current if
count for the block and the if
count for the new statement, and compute the maximum depth as the maximum of the two depths. The function merge_statistics
does that.
I didn't really understand what your nesting depth should be; it's possible that the {0, 0}
should be {0, 1}
. (In the case of an empty block, I assumed that the nesting depth is 0 because there are no statements. But maybe you won't even allow empty blocks.)
You'll need to compile with a compiler which understands C99 ( -std=c99
or -std=c11
if you use gcc) because I use compound literals.
I also removed the yyterminate
call from your scanner and fixed it so that it insists on spaces between tokens, although maybe you don't care about that.
scanner
%option noinput nounput noyywrap yylineno nodefault
%{
#include "jazyk.tab.h"
%}
%%
[[:space:]]+
[Bb][Ee][Gg][Ii][Nn] return(LBEGIN);
[Ee][Nn][Dd] return(LEND);
[Ii][Ff] return(LIF);
[Tt][Hh][Ee][Nn] return(LTHEN);
[Pp] return(LP);
[Vv] return(LV);
[[:alpha:]]+ { printf("Unknown token: %sn", yytext); }
[.;] return(*yytext);
. { printf("unknown character in input: %cn", *yytext);}
parser
%{
#include <stdio.h>
typedef struct statistics {
int if_count;
int max_depth;
} statistics;
statistics merge_statistics(statistics a, statistics b) {
return (statistics){a.if_count + b.if_count,
a.max_depth > b.max_depth ? a.max_depth : b.max_depth};
}
#define YYSTYPE statistics
extern int yylineno;
int yylex();
void yyerror(const char* message);
%}
%token LIF "if" LTHEN "then" LBEGIN "begin" LEND "end"
%token LV
%token LP
%start program
%%
program: block '.' { printf("If count: %d, max depth: %dn",
$1.if_count, $1.max_depth); }
block: "begin" statements "end" { $$ = $2; }
statements: /* empty */ { $$ = (statistics){0, 0}; }
| statements statement ';' { $$ = merge_statistics($1, $2); }
statement : LP { $$ = (statistics){0, 1}; }
| block
| "if" LV "then" statement { $$ = (statistics){$4.if_count + 1,
$4.max_depth + 1}; }
%%
void yyerror(const char* message) {
printf("At %d: %sn", yylineno, message);
}
int main(int argc, char** argv) {
int status = yyparse();
/* Unnecessary because yyerror will print an error message */
if (status != 0) printf("Parse failedn");
return status;
}
Test run:
$ ./jazyk <<<'begin if v then p; end.'
If count: 1, max depth: 2
$ ./jazyk <<<'begin p; if v then if v then p; p; end.'
If count: 2, max depth: 3
$ ./jazyk <<<'begin if v then begin if v then p; p; end; end.'
If count: 2, max depth: 3
$ ./jazyk <<<'begin if v then begin p; if v then p; end; end.'
If count: 2, max depth: 3
$ ./jazyk <<<'begin if v then begin if v then p; if v then p; end; end.'
If count: 3, max depth: 3
链接地址: http://www.djcxy.com/p/41752.html