aboutsummaryrefslogtreecommitdiffstats
path: root/src/vhdl/vhdl-scanner-directive_protect.adb
blob: 3c65b55b5a47c53548f5dd1baf68212a8dd27a75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
--  Lexical analysis for protect directive.
--  Copyright (C) 2019 Tristan Gingold
--
--  This program is free software: you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation, either version 2 of the License, or
--  (at your option) any later version.
--
--  This program is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with this program.  If not, see <gnu.org/licenses>.

separate (Vhdl.Scanner)
package body Directive_Protect is
   function Scan_Expression_List return Boolean;

   --  Scan/parse a keyword expression.
   --  Initial spaces must have been skipped.
   --  Return False in case of error.
   function Scan_Keyword_Expression return Boolean is
   begin
      if Characters_Kind (Source (Pos)) not in Letter then
         Error_Msg_Scan ("identifier expected in protect directive");
         return False;
      end if;

      Scan_Identifier (False);
      if Current_Token /= Tok_Identifier then
         Error_Msg_Scan (+Get_Token_Location, "keyword must be an identifier");
         return False;
      end if;

      Skip_Spaces;
      if Source (Pos) /= '=' then
         return True;
      end if;

      --  Eat '='.
      Pos := Pos + 1;
      Skip_Spaces;

      case Source (Pos) is
         when 'A' .. 'Z' | 'a' .. 'z' =>
            Scan_Identifier (False);
         when '0' .. '9' =>
            Scan_Literal;
         when '"' =>
            Scan_String;
         when '(' =>
            --  Eat '('.
            Pos := Pos + 1;
            Skip_Spaces;

            if not Scan_Expression_List then
               return False;
            end if;

            Skip_Spaces;
            if Source (Pos) /= ')' then
               Error_Msg_Scan ("')' expected at end of protect keyword list");
               return False;
            end if;

            --  Eat ')'.
            Pos := Pos + 1;

         when others =>
            --  Ok, we don't handle all the letters, nor extended identifiers.
            Error_Msg_Scan ("literal expected in protect tool directive");
            return False;
      end case;

      return True;
   end Scan_Keyword_Expression;

   --  Scan: keyword_expression { , keyword_expression }
   function Scan_Expression_List return Boolean is
   begin
      loop
         if not Scan_Keyword_Expression then
            return False;
         end if;

         Skip_Spaces;

         if Source (Pos) /= ',' then
            return True;
         end if;

         --  Eat ','.
         Pos := Pos + 1;

         Skip_Spaces;
      end loop;
   end Scan_Expression_List;

   --  LRM08 24.1 Protect tool directives
   --  protect_directive ::=
   --    `PROTECT keyword_expression {, keyword_expression }
   procedure Scan_Protect_Directive is
   begin
      if Scan_Expression_List then
         if not Is_EOL (Source (Pos)) then
            Error_Msg_Scan ("end of line expected in protect directive");
         end if;
      end if;

      Skip_Until_EOL;
   end Scan_Protect_Directive;
end Directive_Protect;