词法化VHDL';(勾选)代币

词法化VHDL';(勾选)代币,vhdl,flex-lexer,grammar-kit,Vhdl,Flex Lexer,Grammar Kit,在VHDL中,“字符可用于封装字符标记ie.”或作为属性分隔符(类似于CPP的::标记)ie字符串”(“hello”) 解析包含字符的属性名时会出现问题,例如字符串“('a'、'b'、'c')。在这种情况下,一个简单的lexer将错误地将第一个(“标记为一个字符,并且下面所有的实际字符都将被弄乱 2007年的comp.lang.vhdl google组中有一个线程提出了类似的问题 标题为,由用户Diograsia提供答案 case'\'':/*IR1045检查*/ 如果(最后一个标记==DELI

在VHDL中,“字符可用于封装字符标记
ie.”
或作为属性分隔符(类似于CPP的::标记)
ie字符串”(“hello”)

解析包含字符
的属性名时会出现问题,例如字符串“('a'、'b'、'c')
。在这种情况下,一个简单的lexer将错误地将第一个
(“
标记为一个字符,并且下面所有的实际字符都将被弄乱

2007年的comp.lang.vhdl google组中有一个线程提出了类似的问题 标题为,由用户Diograsia提供答案

case'\'':/*IR1045检查*/
如果(最后一个标记==DELIM\u RIGHT\u PAREN||
最后一个标记==DELIM\u右括号||
最后一个\u标记==KEYWD\u ALL||
最后一个\u标记==标识符\u标记||
最后一个标记==STR\U LIT\U标记||

last_token==CHAR_LIT_token | | | |!(buff_ptrIR1045背后的想法是,在不向前看或回溯的情况下,可以判断单个引号/撇号是否是字符文字的一部分。如果您错了,请尝试:

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;

即:

%%

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位置已更改。现在

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

static int resolve_ir1045(void);

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

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

消除歧义的要求在Ada用户杂志2006年9月的第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;
第一次使用带有选定名称前缀(后缀为字符文字)的属性表明不准确,第二次报告语句表明这可能很重要:

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

这个例子在语法和语义上都是有效的VHDL。你可以注意到nvc不允许用实体类文字修饰命名实体。这不符合7.2


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

为什么这些问题在21世纪初突然出现,而语言功能:文字、类型限定和具有一个字符名的属性要老得多?据我所知,大多数VHDL解析器都是手工编写的,不依赖解析器/词法生成器。在大多数情况下,您最终编写了许多特殊规则来规避VHDL的特殊情况。你可以数一数从1991年左右开始,用一只手从零开始的商业VHDL实现的数量,但仍然有剩余的手指。通常是冒险者发现事情不正常,没有人在文档中留下痕迹。我过去认为这是零和竞争-有人必须失去市场份额才能让其他人获得市场份额,这样你才能避免提供帮助。现在最先进的技术是多语言模拟和合成。一个初创企业无论如何都无法竞争,这个领域拥有丰富的专利。@Paebbels Ada也是这样。上一次有新的Ada编译器是什么时候?有一个Visual Studio插件d一个Eclipse插件(Sigasi)。然后还有这个新的VHDL前端提供程序被其他几个供应商使用。我正在开发一个Python版本的VHDL解析器(.我知道很多大公司都有自己的内部VHDL工具,这些工具不是公开的,也买不到。Oh和Xilinx为第三家公司开发的Vivado购买了一个新的前端。这解释了与XST相比支持的功能减少的原因。我想不同HDL之间的共性是导致功能下降的原因自XST以来,随着系统级合成的发展,Pork(Verilog)和beef(VHDL)被迫通过同一个绞肉机。这是使用相同工具支持多语言的副作用。
#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;
   }
}
static int resolve_ir1045(void);
{CHAR}            { if (resolve_ir1045()) {
                       yylval.s = strdup(yytext);
                       TOKEN(tID);
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