Лексинг VHDL ' (галочка) Жетон

В VHDL это символ 'может использоваться для инкапсуляции символьного токена ie '.' или это может быть в качестве разделителя атрибутов (аналогично CPP's:: token) ie string'("hello"),

Проблема возникает при разборе имени атрибута, содержащего символ ie string'('a','b','c'), В этом случае наивный лексер будет неправильно токенизировать первый '(' как персонаж, и все последующие фактические символы будут испорчены.

В группе Google comp.lang.vhdl от 2007 года есть тема, в которой задается аналогичный вопрос под названием "Lexing the char", на который есть ответ пользователя diogratia.

        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, если это помогает.

1 ответ

Решение

Идея 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.

Nvc Ника Гассона использует flex, в котором он внедрил решение Issue Report 1045.

Смотрите nvc/src/lexer.l, который лицензирован под GPLv3.

Поиск 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;
   }
}

Расположение IR1045 изменилось после публикации сообщения comp.lang.vhdl.

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

Вы также захотите найти resol_ir1045 в lexer.l.

static int resolve_ir1045(void);

а также

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

Там, где мы находим, nvc использует функцию фильтрации для обнаружения первой одиночной кавычки символьного литерала.

Первоначально это была проблема Ады. IR-1045 никогда не был принят, но повсеместно использовался. Вероятно, существуют лексеры Ada flex, которые также демонстрируют неоднозначность.

Требование устранения неоднозначности обсуждается в журнале Ada User Journal, том 27, номер 3 от сентября 2006 года, в статье Lexical Analysis на страницах 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

В дополнение к префиксу имени атрибута, содержащему выбранное имя с буквенным суффиксом символа, существует требование, чтобы спецификация атрибута "украшала" объявленную сущность (класса entity_class, см. IEEE Std 1076-2008 7.2 Спецификация атрибута) в той же декларативной области юридическое лицо объявлено в.

Этот пример является синтаксически и семантически действительным VHDL. Вы можете заметить, что nvc не позволяет украшать именованную сущность литералом класса сущности. Это не в соответствии с 7.2.

Перечисленные литералы объявляются в объявлениях типов, здесь тип twovalue. Перечислимый тип, имеющий в качестве литерала перечисления хотя бы один символьный литерал, является символьным типом (5.2.2.1).

Другие вопросы по тегам