Flex/Bison 的空间问题
我目前正在使用 Flex/Bison 开发 HTML 解析器/模板库。我的 if 语句有一些问题。该表达式解析得很好( if you > me ),但是当涉及到开始和结束 if 标签之间的语句时,它只是获取第一个单词并在它们之间的空格上消失。只是想知道如何确保获得标签之间的所有内容,而不是让它在遇到的第一个空格上消失。
我基本上做的是用变量({{var}})的新值和语句的结果(如{% if expression %} blah {% endif %})重建文件(即djangoish)
输出< /strong>
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();
}
Bison
%{
#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 %}
Im currently working on an HTML parser/template library using Flex/Bison. I am having some issues with my if statement. The expression parses fine ( if you > me ) but when it comes to the statement between the beginning and ending if tags, it is only getting the first word and dying on the space between them. Just wondering how I can ensure that I get all the content between the tags and not have it die on the first space it encounters.
What Im basically doing is rebuilding the file with the new values from variables ({{var}}) and results from statements (like {% if expression %} blah {% endif %}) (ie. djangoish)
Output
you > me
If Statement:
if(you) {
Do
}
Example Template
%{
#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();
}
Bison
%{
#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 {}
;
%%
Example HTML Template
{% if you > me %}
Do something here
{% endif %}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
看起来好像您没有在这一行返回任何内容:
如果不返回任何内容,它似乎不会被识别为令牌,因此会被忽略。
不过我不是100%确定。我对您使用变量“上下文”(这似乎也是一个有效的令牌?)感到有点困惑,但无论如何这可能是您的问题。
It appears as though you are not returning anything on this line:
Without returning anything, it doesn't seem as though it would be recognized as a token, and thus would be ignored.
I'm not 100% sure however. I'm a little confused by your use of the variable "context" (which also seems to be a valid token?), but at any rate that may be your problem.
也许您应该在命令规则中添加一个空格标记。
野牛文件:
Flex 文件:
Maybe you should add a whitespace token within your command rule.
bison file:
flex file: