4

在 VHDL 中,' 字符可用于封装字符标记ie '.',也可以用作属性分隔符(类似于 CPP 的 :: 标记)ie string'("hello")

解析包含字符的属性名称时会出现问题ie string'('a','b','c')。在这种情况下,一个天真的词法分析器会错误地将第一个字符标记'('为一个字符,并且所有后面的实际字符都会被弄乱。

从 2007 年开始,comp.lang.vhdl google 组中有一个线程,它提出了一个名为“Lexing the ' char”的类似问题 ,该问题由用户 digratia 回答

        case '\'':                          /* IR1045 check */

            if (    last_token == DELIM_RIGHT_PAREN ||
                    last_token == DELIM_RIGHT_BRACKET ||
                    last_token == KEYWD_ALL ||
                    last_token == IDENTIFIER_TOKEN ||
                    last_token == STR_LIT_TOKEN ||
                    last_token == CHAR_LIT_TOKEN || ! (buff_ptr<BUFSIZ-2) )
                token_flag = DELIM_APOSTROPHE;
            else if (is_graphic_char(NEXT_CHAR) &&
                    line_buff[buff_ptr+2] == '\'') { CHARACTER_LITERAL:
                buff_ptr+= 3;               /* lead,trailing \' and char */
                last_token = CHAR_LIT_TOKEN;
                token_strlen = 3;
                return (last_token);
            }
            else token_flag = DELIM_APOSTROPHE;
            break;

请参阅问题报告 IR1045: http ://www.eda-twiki.org/isac/IRs-VHDL-93/IR1045.txt

从上面的代码片段可以看出,最后一个标记可以被捕获并用来区分类似的东西:

  foo <= std_logic_vector'('a','b','c');

没有大的向前看或回溯。

但是,据我所知, flex 不会跟踪被解析的最后一个标记。

无需手动跟踪最后解析的标记,是否有更好的方法来完成此词法分析任务?

如果有帮助,我正在使用 IntelliJ GrammarKit。

4

1 回答 1

5

IR1045 背后的想法是能够判断单引号/撇号是否是字符文字的一部分,而无需向前看或在错误时回溯,请尝试:

library ieee;
use ieee.std_logic_1164.all;

entity foo is
    port (
        a:      in      std_logic;
        b:      out     std_logic_vector (3 downto 0)
    );
end entity;

architecture behave of foo is
    begin
    b <= std_logic_vector'('0','1','1','0')     when a = '1' else
         (others =>'0')                         when a = '0' else
         (others => 'X');
end architecture behave;

你愿意向前看多远?

然而,有一个用于 VHDL 的撇号和字符文字的灵活消歧的实际示例。

Nick Gasson 的 nvc 使用 flex,他在其中实施了 Issue Report 1045 解决方案。

请参阅根据 GPLv3 许可的nvc/src/lexer.l 。

搜索 last_token:

#define TOKEN(t) return (last_token = (t))

#define TOKEN_LRM(t, lrm)                                       \
   if (standard() < lrm) {                                      \
      warn_at(&yylloc, "%s is a reserved word in VHDL-%s",      \
              yytext, standard_text(lrm));                      \
      return parse_id(yytext);                                  \
   }                                                            \
   else                                                         \
      return (last_token = (t));

一个附加的功能来检查它:

static int resolve_ir1045(void);

static int last_token = -1;

这是:

%%

static int resolve_ir1045(void)
{
   // See here for discussion:
   //   http://www.eda-stds.org/isac/IRs-VHDL-93/IR1045.txt
   // The set of tokens that may precede a character literal is
   // disjoint from that which may precede a single tick token.

   switch (last_token) {
   case tRSQUARE:
   case tRPAREN:
   case tALL:
   case tID:
      // Cannot be a character literal
      return 0;
   default:
      return 1;
   }
}

自 comp.lang.vhdl 发布以来,IR1045 位置已更改

http://www.eda-twiki.org/isac/IRs-VHDL-93/IR1045.txt

您还需要在 lexer.l 中搜索 resolve_ir1045。

static int resolve_ir1045(void);

{CHAR}            { if (resolve_ir1045()) {
                       yylval.s = strdup(yytext);
                       TOKEN(tID);

我们发现 nvc 使用该函数来过滤检测字符文字的第一个单引号。

这最初是一个 Ada 问题。IR-1045 从未被采用,但被普遍使用。可能有 Ada flex 词法分析器也证明了歧义。

Ada User Journal 第27 卷第 3期自 2006 年 9 月的一篇文章Lexical Analysis on PDF 第 30 页和第 31 页(第 27 卷第 159 和 160 页)中讨论了消除歧义的要求,我们发现解决方案并不为人所知。

字符文字不在单引号之前的注释是不准确的:

entity ir1045 is
end entity;

architecture foo of ir1045 is
begin
THIS_PROCESS:
    process
        type twovalue is ('0', '1');  
        subtype string4 is string(1 to 4);
        attribute a: string4;
        attribute a of '1' : literal is "TRUE";
    begin
        assert THIS_PROCESS.'1''a /= "TRUE"
            report "'1''a /= ""TRUE"" is FALSE";
        report "This_PROCESS.'1''a'RIGHT = " &
            integer'image(This_PROCESS.'1''a'RIGHT);
        wait;
    end process;
end architecture;

第一次使用具有选定名称前缀且后缀为字符文字的属性证明了不准确,第二个报告语句表明它可能很重要:

ghdl -a ir1045.vhdl
ghdl -e ir1045
ghdl -r ir1045
ir1045.vhdl:13:9:@0ms:(assertion error): '1''a /= "TRUE" is FALSE
ir1045.vhdl:15:9:@0ms:(report note): This_PROCESS.'1''a'RIGHT = 4

除了包含带有字符文字后缀的选定名称的属性名称前缀之外,还要求属性规范“装饰”同一声明区域中的声明实体(实体类的,请参见 IEEE Std 1076-2008 7.2 属性规范)实体在中声明。

这个例子在句法和语义上都是有效的 VHDL。您可能会注意到 nvc 不允许使用实体类文字装饰命名实体。这不是根据 7.2。

枚举字面量在类型声明中声明,这里类型为 twovalue。具有至少一个字符文字作为枚举文字的枚举类型是字符类型 (5.2.2.1)。

于 2017-04-01T18:50:31.273 回答