【问题标题】:Space issue with Flex/BisonFlex/Bison 的空间问题
【发布时间】:2010-08-26 18:22:48
【问题描述】:

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

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

p>

输出


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

【问题讨论】:

  • 这里有问题吗?语法和词法分析器编译良好并接受示例输入就好了,产生预期描述的输出......

标签: bison lex flex-lexer


【解决方案1】:

您似乎没有在此行返回任何内容:

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

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

不过,我不能 100% 确定。我对您使用变量“context”(这似乎也是一个有效的令牌?)有点困惑,但无论如何这可能是您的问题。

【讨论】:

  • context 只是我用来临时存储值的本地 const char,因此我可以将其写回文件以维护空间、制表符和 html 的文件结构。另外感谢回复,我没有返回任何内容的原因是因为我仍然想忽略空格,但我应该返回 *yytext 之类的内容吗?
【解决方案2】:

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

野牛文件:

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

弹性文件:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    • 2016-05-30
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 2011-07-11
    相关资源
    最近更新 更多