我目前正在使用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 */
\<[^>]*\> { 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 %}
答案 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); }