如何使用 Flex 仅扫描上下文中的令牌?

发布于 2024-12-07 07:01:27 字数 686 浏览 0 评论 0原文

我想使用 Flex & 创建模板引擎的解析器。野牛。问题是我只想解析 {{..}} 和 ${..} 中的表达式。

模板可以是带有嵌入标记的任意文本,代码如下:

        </table:table-row>
        {{$(/report/row.xml).embed()}}
        {{$(//Accreditation/AccreditationDocument/Report).each(fragment(row) """
            <table:row>
                <table:table-cell office:value-type="string" office:string-value="${row["name"]}" />
            </table:row>
        """)}}
        <table:table-row table:number-rows-repeated="1048574" table:style-name="ro1">
            <table:table-cell table:number-columns-repeated="16384"/>
        </table:table-row>
    </table:table>

I want to create a parser of template engine using Flex & Bison. The thing is that I would like to parse only expressions within {{..}} and ${..}.

The template can be any arbitrary text with embedded tokens with code like this:

        </table:table-row>
        {{$(/report/row.xml).embed()}}
        {{$(//Accreditation/AccreditationDocument/Report).each(fragment(row) """
            <table:row>
                <table:table-cell office:value-type="string" office:string-value="${row["name"]}" />
            </table:row>
        """)}}
        <table:table-row table:number-rows-repeated="1048574" table:style-name="ro1">
            <table:table-cell table:number-columns-repeated="16384"/>
        </table:table-row>
    </table:table>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绝對不後悔。 2024-12-14 07:01:27

我自己找到了解决方案。 Flex 有一个名为启动条件的功能。

下面是 lexer.l 代码,它仅从 {{ }} 返回令牌。其他文本作为 GENERAL_BODY 返回。

%{
#include "bisondef.h"
%}

%option reentrant noyywrap never-interactive nounistd
%option bison-bridge

WS [ \t\n]+
ID [A-z_][[:alnum:]]*

%x stmt

%%
    int stmt_level = 0;

"{{"    { stmt_level = 0; BEGIN(stmt); }

<stmt>{
    "{{"    { stmt_level++; printf("stmt {{\n"); }
    "}}"    {
        if (0 == stmt_level) BEGIN(INITIAL);
        else stmt_level--;
    }
    {WS}    {}
    [0-9]+  { yylval->num = atoi(yytext); return NUM; }
    "+"|"-"|"*"|"/"|"("|")" { return *yytext; }
    ";"     { return SEMICOLON; }
    {ID}    { yylval->str = strdup(yytext); return ID; }
}

.  {
    yylval->str = strdup(yytext);
    return GENERAL_BODY;
}

%%

int yyerror(const char *msg) { fprintf(stderr,"Error: %s\n",msg); return 0; }

I have found the solution myself. Flex has a feature called Start Conditions.

Below is the lexer.l code which returns tokens only from {{ }}. Other text is returned as GENERAL_BODY.

%{
#include "bisondef.h"
%}

%option reentrant noyywrap never-interactive nounistd
%option bison-bridge

WS [ \t\n]+
ID [A-z_][[:alnum:]]*

%x stmt

%%
    int stmt_level = 0;

"{{"    { stmt_level = 0; BEGIN(stmt); }

<stmt>{
    "{{"    { stmt_level++; printf("stmt {{\n"); }
    "}}"    {
        if (0 == stmt_level) BEGIN(INITIAL);
        else stmt_level--;
    }
    {WS}    {}
    [0-9]+  { yylval->num = atoi(yytext); return NUM; }
    "+"|"-"|"*"|"/"|"("|")" { return *yytext; }
    ";"     { return SEMICOLON; }
    {ID}    { yylval->str = strdup(yytext); return ID; }
}

.  {
    yylval->str = strdup(yytext);
    return GENERAL_BODY;
}

%%

int yyerror(const char *msg) { fprintf(stderr,"Error: %s\n",msg); return 0; }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文