如何转义flex关键字

问题描述 投票:0回答:2

我在Linux上使用Flex&bison。我有以下设置:

//令牌CREATE {return token :: CREATE;} SCHEMA {return token :: SCHEMA; } RECORD {return token :: RECORD;} [_a-zA-Z0-9] [_ a-zA-Z0-9] * {yylval-> strval = strdup(yytext);返回TOKEN :: NAME;} ... //规则创建模式名称... 创建记录名称......

一切都很好。但是如果用户输入:“create schema record ...”(其中'record'是要创建的模式的名称),Flex将报告错误,因为它将'record'与令牌匹配,并且它正在查找规则“创建计划记录”。我了解关键字可以转义,但这会让用户体验变得尴尬。我的问题是:

“我如何设计上述规则,使其接受'创建模式记录...'并将此输入与'CREATE SCHEMA NAME ...'相匹配?”

谢谢!

bison flex-lexer
2个回答
4
投票

“半保留”字在具有大量保留字的语言中很常见。 (即使是现代C ++也有几个:overridefinal。)但是它们给传统扫描仪带来了一些困难,通常认为关键字是一个关键字。

柠檬解析器生成器并非巧合地用于解析SQL,它有一个有用的"fallback" feature,其中在上下文中无效的令牌可以被另一个令牌替换(不改变语义值)。不幸的是,野牛没有实现这个功能,也没有我知道的任何其他解析器生成器。但是,在许多情况下,可以在Bison语法中实现该功能。例如,在这里介绍的简单案例中,我们可以替代:

create_statement: CREATE RECORD NAME ...
                | CREATE SCHEMA NAME ...

有:

create_statement: CREATE RECORD name
                | CREATE SCHEMA name
name: NAME
    | CREATE
    | RECORD
    | SCHEMA
    | ...

显然,需要注意name备选列表中的(半)关键字在使用name的上下文中无效。这可能需要定义各种name作品,适用于不同的背景。 (这是柠檬式后备更方便的地方。)

如果这样做,重要的是通过扫描仪或name非终端的缩减规则正确设置关键字的语义值。如果只有一个name非终端,那么在减少操作中执行它可能更有效(因为它避免了不必要的字符串分配和释放,其中解除分配会使关键字出现的其他语法规则复杂化),所以name规则实际上看起来像这样:

name: NAME
    | CREATE   { $$ = strdup("CREATE"); }
    | RECORD   { $$ = strdup("RECORD"); }
    | SCHEMA   { $$ = strdup("SCHEMA"); }
    | ...

当然,还有许多其他可能的方法来处理语义价值问题。


0
投票

你不应该这样做,因为你不能在C ++中有一个名为forwhileclass的变量。但如果你真的想,请看看Start Conditions(这将是凌乱的)。

© www.soinside.com 2019 - 2024. All rights reserved.