Flex / Bison的空间问题

时间:2010-08-26 18:22:49

标签: bison lex flex-lexer

我目前正在使用Flex / Bison开发HTML解析器/模板库。我的if语句存在一些问题。表达式解析很好(如果你>我)但是当涉及到标签的开头和结尾之间的语句时,它只获得第一个单词并在它们之间的空间上死亡。只是想知道如何确保我获得标签之间的所有内容,而不是让它在遇到的第一个空间中死亡。

我基本上做的是使用变量({{var}})中的新值和语句结果重建文件(如{%if expression%} blah {%endif%})(即djangoish)

输出


you > me

If Statement: 
if(you) {
    Do
}

示例模板


%{
#include <stdio.h>
#include "ink.tab.h"

using namespace std;

extern "C" {
   int yyparse(void);
   int yylex(void);
   int yywrap();
}

extern void yyerror(char *err);
extern int LINENO;

const char *context;
%}

%%

   /* Open/Close template tags */
"{{"     { return OPENPRINT;   }
"}}"     { return CLOSEPRINT;  }
"{%"     { return OPENACTION;  }
"%}"     { return CLOSEACTION; }


   /* Conditionals */
"!"   { return BANG;  }
"<"   { return LT;    }
">"   { return GT;    }
"=="  { return EQ;    }
"!="  { return NEQ;   }
"<="  { return LTEQ;  }
">="  { return GTEQ;  }
"&&"  { return ANDOP; }
"||"  { return OROP;  }

   /* IF/ELSE handler */
"if"     { return IF_TOKEN;    }
"else"   { return ELSE_TOKEN;  }
"endif"  { return ENDIF_TOKEN; }

   /* FOR handler */
"for"    { return FOR_TOKEN;    }
"in"     { return IN_TOKEN;     }
"endfor" { return ENDFOR_TOKEN; }

   /* Context grab */
[a-zA-Z0-9_]*   { yylval.strval = strdup(yytext); return CONTEXT; }

   /* Excuse the HTML tags */
\&lt;[^>]*\>    { context = strdup(yytext); fwrite(context, sizeof(char), strlen(context), yyout); }

   /* Some catch alls */
[ \t]+     { context = strdup(yytext); fwrite(context, sizeof(char), strlen(context), yyout); }

\n           { LINENO++; context = "\n"; fwrite(context, sizeof(char), strlen(context), yyout); }
.            ;

%%

void yyerror(char *err)
{
   printf("\nLine:\t%d\nError:\t%s\nText:\t%s\n", LINENO, err, yytext);
}

int yywrap()
{
   return 1;
}

int main()
{
   yyout = fopen("test.out", "w");
   yyin = fopen("test.jhtml", "r");
   yyparse();
}

野牛

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <v8.h>

using namespace std;
using namespace v8;

extern "C" {
   int yyparse(void);
   int yylex(void);
   int yywrap();
}

int LINENO = 1;
void yyerror(char *err);

extern FILE *yyout;
%}


%union {
   int inval;
   char *strval;
}

%token OPENPRINT
%token CLOSEPRINT
%token OPENACTION
%token CLOSEACTION
%token <strval> CONTEXT
%token IF_TOKEN
%token ELSE_TOKEN
%token ENDIF_TOKEN
%token FOR_TOKEN
%token IN_TOKEN
%token ENDFOR_TOKEN
%token TAGS

%token BANG
%token LT
%token GT
%token EQ
%token NEQ
%token LTEQ
%token GTEQ
%token ANDOP
%token OROP

%type <strval> context
%type <strval> expression
%type <strval> contexts

%%

commands:
         command
         |
         commands command
         ;

command:
         OPENPRINT echo CLOSEPRINT
         |
         expression
         |
         stmt
         ;

echo:
         context { 
            char *context = $1;
            fwrite(context, sizeof(char), strlen(context), yyout); 
         }
         ;

stmt:
         OPENACTION IF_TOKEN expression CLOSEACTION contexts OPENACTION ENDIF_TOKEN CLOSEACTION { 
            printf("\nIf Statement: \n");
            printf("if(%s) {\n\t%s\n}\n", $3, $5);
         }
         ;

contexts:
         context
         |
         contexts context
         ;

context:
         CONTEXT { $$ = $1; }
         ;

expression:
         context
         |
         context GT context   { printf("\n%s > %s\n", $1, $3); }
         |
         context LT context      {}
         |
         context EQ context      {}
         |
         context NEQ context     {}
         |
         context LTEQ context    {}
         |
         context GTEQ context    {}
         |
         context ANDOP context   {}
         |
         context OROP context    {}
         |
         BANG context            {}
         ;
%%

示例HTML模板

{% if you > me %}
     Do something here
{% endif %}

2 个答案:

答案 0 :(得分:1)

好像你没有在这一行返回任何内容:

[ \t]+     { context = strdup(yytext); fwrite(context, sizeof(char), strlen(context), yyout); }

如果没有返回任何内容,它似乎不会被识别为令牌,因此会被忽略。

但是,我不是百分百肯定的。我对你使用变量“context”(它似乎也是一个有效的令牌?)感到有点困惑,但无论如何这可能是你的问题。

答案 1 :(得分:0)

也许您应该在命令规则中添加一个空格标记。

野牛文件:

command:
    WHITESPACE {/*do nothing to skip whitespace */}
    | 
    OPENPRINT echo CLOSEPRINT
    |
    expression
    |
    stmt
    ;

flex文件:

[ \t\v\n\f]     { count(); return(WHITESPACE); }