Flex和Bison如何找到命令的深度级别

我在Bison中遇到了大问题 - 我需要在if语句中查找命令(P)的最大深度级别。所以我将它编码为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);
} 

而这对于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");

}

例如功能 - 当我写入begin if v then p; end. begin if v then p; end. 结果必须是:IF:1; P:2的最大深度级别; 要么:

begin
p;
if v then
if v then p;
p;
end. 

结果:IF:2; 最大深度:3;

我现在真的很绝望。 请用深度计数器帮助我:-((并非所有的英文都是对不起)


不要试图计算扫描仪的深度。 扫描仪不知道程序的结构。 解析器理解嵌套,所以它是你应该计算深度的地方。

由于您目前没有使用语义值进行任何操作,因此我冒昧地将它们用于统计。 如果您有真正的语义值,则可以将统计结构添加为成员,或使用位置值。

当解析器遇到if语句时,它知道还有一个if语句,并且当前的嵌套深度比if的目标的嵌套深度多一个。

我为块添加了if语句的语法,因为它很简单,并且使程序更有趣。 当解析器增加了一个语句块,它需要总结当前if算上为块和if新的语句数,并计算最大深度为最大的两个深度的。 函数merge_statistics做到这一点。

我不太了解你的嵌套深度应该是多少; 有可能{0, 0}应该是{0, 1} 。 (在空块的情况下,我认为嵌套深度为0,因为没有语句,但可能甚至不允许空块。)

你需要编译一个理解C99的编译器(如果你使用gcc, -std=c99-std=c11 ),因为我使用了复合文字。

我也从扫描仪中删除了yyterminate调用并修复它,以便它坚持令牌之间的空间,虽然也许你不关心它。

扫描器

%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);}

解析器

%{
  #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;
}

测试运行:

$ ./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/41751.html

上一篇: Flex and Bison how to find depth level of command

下一篇: Bison/Flex creating list