Космическая проблема с Flex / Bison - PullRequest
0 голосов
/ 26 августа 2010

В настоящее время я работаю над HTML-парсером / библиотекой шаблонов, используя Flex / Bison.У меня есть некоторые проблемы с моим заявлением if.Выражение хорошо разбирается (если вы> я), но когда дело доходит до утверждения между тегами начала и конца 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 ]

1 голос
/ 26 августа 2010

Похоже, что вы ничего не возвращаете в этой строке:

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

Не возвращая ничего, не кажется, что это будет распознаваться как токен и, следовательно, будет игнорироваться.

Однако я не уверен на 100%.Меня немного смущает использование вами переменной "context" (которая также кажется допустимым токеном?), Но в любом случае это может быть вашей проблемой.

0 голосов
/ 07 июля 2018

Может быть, вам следует добавить токен пробела в ваше правило команды.

файл зубра:

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

файл флекс:

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