aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ghdldrv/ghdlprint.adb14
-rw-r--r--src/std_names.adb12
-rw-r--r--src/std_names.ads203
-rw-r--r--src/vhdl/disp_vhdl.adb1
-rw-r--r--src/vhdl/parse.adb513
-rw-r--r--src/vhdl/parse.ads18
-rw-r--r--src/vhdl/parse_psl.adb22
-rw-r--r--src/vhdl/tokens.ads21
8 files changed, 377 insertions, 427 deletions
diff --git a/src/ghdldrv/ghdlprint.adb b/src/ghdldrv/ghdlprint.adb
index f95e266ee..531d6125a 100644
--- a/src/ghdldrv/ghdlprint.adb
+++ b/src/ghdldrv/ghdlprint.adb
@@ -378,23 +378,11 @@ package body Ghdlprint is
Disp_Text;
Put ("</tt>");
end case;
- when Tok_Access .. Tok_Elsif
- | Tok_Entity .. Tok_With
- | Tok_Mod .. Tok_Rem
- | Tok_And .. Tok_Not =>
- Disp_Reserved;
- when Tok_End =>
+ when Tok_Mod .. Tok_Parameter =>
Disp_Reserved;
when Tok_Semi_Colon =>
Disp_Spaces;
Disp_Text;
- when Tok_Xnor .. Tok_Ror =>
- Disp_Reserved;
- when Tok_Protected =>
- Disp_Reserved;
- when Tok_Context
- | Tok_Parameter =>
- Disp_Reserved;
when Tok_Across .. Tok_Tolerance =>
Disp_Reserved;
when Tok_Psl_Default
diff --git a/src/std_names.adb b/src/std_names.adb
index ffee4645e..dfe322136 100644
--- a/src/std_names.adb
+++ b/src/std_names.adb
@@ -31,12 +31,6 @@ package body Std_Names is
Def ("mod", Name_Mod);
Def ("rem", Name_Rem);
- Def ("and", Name_And);
- Def ("or", Name_Or);
- Def ("xor", Name_Xor);
- Def ("nand", Name_Nand);
- Def ("nor", Name_Nor);
-
Def ("abs", Name_Abs);
Def ("not", Name_Not);
@@ -131,6 +125,12 @@ package body Std_Names is
Def ("while", Name_While);
Def ("with", Name_With);
+ Def ("and", Name_And);
+ Def ("or", Name_Or);
+ Def ("xor", Name_Xor);
+ Def ("nand", Name_Nand);
+ Def ("nor", Name_Nor);
+
-- VHDL93 reserved words.
Def ("xnor", Name_Xnor);
Def ("group", Name_Group);
diff --git a/src/std_names.ads b/src/std_names.ads
index ff273de02..b1e39ca6e 100644
--- a/src/std_names.ads
+++ b/src/std_names.ads
@@ -34,112 +34,113 @@ package Std_Names is
Name_Mod : constant Name_Id := Name_First_Keyword + 000;
Name_Rem : constant Name_Id := Name_First_Keyword + 001;
- Name_And : constant Name_Id := Name_First_Keyword + 002;
- Name_Or : constant Name_Id := Name_First_Keyword + 003;
- Name_Xor : constant Name_Id := Name_First_Keyword + 004;
- Name_Nand : constant Name_Id := Name_First_Keyword + 005;
- Name_Nor : constant Name_Id := Name_First_Keyword + 006;
+ Name_Abs : constant Name_Id := Name_First_Keyword + 002;
+ Name_Not : constant Name_Id := Name_First_Keyword + 003;
- Name_Abs : constant Name_Id := Name_First_Keyword + 007;
- Name_Not : constant Name_Id := Name_First_Keyword + 008;
+ subtype Name_Word_Operators is Name_Id range Name_Mod .. Name_Not;
+
+ Name_Access : constant Name_Id := Name_First_Keyword + 004;
+ Name_After : constant Name_Id := Name_First_Keyword + 005;
+ Name_Alias : constant Name_Id := Name_First_Keyword + 006;
+ Name_All : constant Name_Id := Name_First_Keyword + 007;
+ Name_Architecture : constant Name_Id := Name_First_Keyword + 008;
+ Name_Array : constant Name_Id := Name_First_Keyword + 009;
+ Name_Assert : constant Name_Id := Name_First_Keyword + 010;
+ Name_Attribute : constant Name_Id := Name_First_Keyword + 011;
+
+ Name_Begin : constant Name_Id := Name_First_Keyword + 012;
+ Name_Block : constant Name_Id := Name_First_Keyword + 013;
+ Name_Body : constant Name_Id := Name_First_Keyword + 014;
+ Name_Buffer : constant Name_Id := Name_First_Keyword + 015;
+ Name_Bus : constant Name_Id := Name_First_Keyword + 016;
+
+ Name_Case : constant Name_Id := Name_First_Keyword + 017;
+ Name_Component : constant Name_Id := Name_First_Keyword + 018;
+ Name_Configuration : constant Name_Id := Name_First_Keyword + 019;
+ Name_Constant : constant Name_Id := Name_First_Keyword + 020;
+
+ Name_Disconnect : constant Name_Id := Name_First_Keyword + 021;
+ Name_Downto : constant Name_Id := Name_First_Keyword + 022;
+
+ Name_Else : constant Name_Id := Name_First_Keyword + 023;
+ Name_Elsif : constant Name_Id := Name_First_Keyword + 024;
+ Name_End : constant Name_Id := Name_First_Keyword + 025;
+ Name_Entity : constant Name_Id := Name_First_Keyword + 026;
+ Name_Exit : constant Name_Id := Name_First_Keyword + 027;
+
+ Name_File : constant Name_Id := Name_First_Keyword + 028;
+ Name_For : constant Name_Id := Name_First_Keyword + 029;
+ Name_Function : constant Name_Id := Name_First_Keyword + 030;
+
+ Name_Generate : constant Name_Id := Name_First_Keyword + 031;
+ Name_Generic : constant Name_Id := Name_First_Keyword + 032;
+ Name_Guarded : constant Name_Id := Name_First_Keyword + 033;
+
+ Name_If : constant Name_Id := Name_First_Keyword + 034;
+ Name_In : constant Name_Id := Name_First_Keyword + 035;
+ Name_Inout : constant Name_Id := Name_First_Keyword + 036;
+ Name_Is : constant Name_Id := Name_First_Keyword + 037;
+
+ Name_Label : constant Name_Id := Name_First_Keyword + 038;
+ Name_Library : constant Name_Id := Name_First_Keyword + 039;
+ Name_Linkage : constant Name_Id := Name_First_Keyword + 040;
+ Name_Loop : constant Name_Id := Name_First_Keyword + 041;
+
+ Name_Map : constant Name_Id := Name_First_Keyword + 042;
+
+ Name_New : constant Name_Id := Name_First_Keyword + 043;
+ Name_Next : constant Name_Id := Name_First_Keyword + 044;
+ Name_Null : constant Name_Id := Name_First_Keyword + 045;
+
+ Name_Of : constant Name_Id := Name_First_Keyword + 046;
+ Name_On : constant Name_Id := Name_First_Keyword + 047;
+ Name_Open : constant Name_Id := Name_First_Keyword + 048;
+ Name_Others : constant Name_Id := Name_First_Keyword + 049;
+ Name_Out : constant Name_Id := Name_First_Keyword + 050;
+
+ Name_Package : constant Name_Id := Name_First_Keyword + 051;
+ Name_Port : constant Name_Id := Name_First_Keyword + 052;
+ Name_Procedure : constant Name_Id := Name_First_Keyword + 053;
+ Name_Process : constant Name_Id := Name_First_Keyword + 054;
+
+ Name_Range : constant Name_Id := Name_First_Keyword + 055;
+ Name_Record : constant Name_Id := Name_First_Keyword + 056;
+ Name_Register : constant Name_Id := Name_First_Keyword + 057;
+ Name_Report : constant Name_Id := Name_First_Keyword + 058;
+ Name_Return : constant Name_Id := Name_First_Keyword + 059;
+
+ Name_Select : constant Name_Id := Name_First_Keyword + 060;
+ Name_Severity : constant Name_Id := Name_First_Keyword + 061;
+ Name_Signal : constant Name_Id := Name_First_Keyword + 062;
+ Name_Subtype : constant Name_Id := Name_First_Keyword + 063;
+
+ Name_Then : constant Name_Id := Name_First_Keyword + 064;
+ Name_To : constant Name_Id := Name_First_Keyword + 065;
+ Name_Transport : constant Name_Id := Name_First_Keyword + 066;
+ Name_Type : constant Name_Id := Name_First_Keyword + 067;
+
+ Name_Units : constant Name_Id := Name_First_Keyword + 068;
+ Name_Until : constant Name_Id := Name_First_Keyword + 069;
+ Name_Use : constant Name_Id := Name_First_Keyword + 070;
+
+ Name_Variable : constant Name_Id := Name_First_Keyword + 071;
+
+ Name_Wait : constant Name_Id := Name_First_Keyword + 072;
+ Name_When : constant Name_Id := Name_First_Keyword + 073;
+ Name_While : constant Name_Id := Name_First_Keyword + 074;
+ Name_With : constant Name_Id := Name_First_Keyword + 075;
+
+ Name_And : constant Name_Id := Name_First_Keyword + 076;
+ Name_Or : constant Name_Id := Name_First_Keyword + 077;
+ Name_Xor : constant Name_Id := Name_First_Keyword + 078;
+ Name_Nand : constant Name_Id := Name_First_Keyword + 079;
+ Name_Nor : constant Name_Id := Name_First_Keyword + 080;
subtype Name_Logical_Operators is Name_Id range Name_And .. Name_Nor;
- subtype Name_Word_Operators is Name_Id range Name_Mod .. Name_Not;
- Name_Access : constant Name_Id := Name_First_Keyword + 009;
- Name_After : constant Name_Id := Name_First_Keyword + 010;
- Name_Alias : constant Name_Id := Name_First_Keyword + 011;
- Name_All : constant Name_Id := Name_First_Keyword + 012;
- Name_Architecture : constant Name_Id := Name_First_Keyword + 013;
- Name_Array : constant Name_Id := Name_First_Keyword + 014;
- Name_Assert : constant Name_Id := Name_First_Keyword + 015;
- Name_Attribute : constant Name_Id := Name_First_Keyword + 016;
-
- Name_Begin : constant Name_Id := Name_First_Keyword + 017;
- Name_Block : constant Name_Id := Name_First_Keyword + 018;
- Name_Body : constant Name_Id := Name_First_Keyword + 019;
- Name_Buffer : constant Name_Id := Name_First_Keyword + 020;
- Name_Bus : constant Name_Id := Name_First_Keyword + 021;
-
- Name_Case : constant Name_Id := Name_First_Keyword + 022;
- Name_Component : constant Name_Id := Name_First_Keyword + 023;
- Name_Configuration : constant Name_Id := Name_First_Keyword + 024;
- Name_Constant : constant Name_Id := Name_First_Keyword + 025;
-
- Name_Disconnect : constant Name_Id := Name_First_Keyword + 026;
- Name_Downto : constant Name_Id := Name_First_Keyword + 027;
-
- Name_Else : constant Name_Id := Name_First_Keyword + 028;
- Name_Elsif : constant Name_Id := Name_First_Keyword + 029;
- Name_End : constant Name_Id := Name_First_Keyword + 030;
- Name_Entity : constant Name_Id := Name_First_Keyword + 031;
- Name_Exit : constant Name_Id := Name_First_Keyword + 032;
-
- Name_File : constant Name_Id := Name_First_Keyword + 033;
- Name_For : constant Name_Id := Name_First_Keyword + 034;
- Name_Function : constant Name_Id := Name_First_Keyword + 035;
-
- Name_Generate : constant Name_Id := Name_First_Keyword + 036;
- Name_Generic : constant Name_Id := Name_First_Keyword + 037;
- Name_Guarded : constant Name_Id := Name_First_Keyword + 038;
-
- Name_If : constant Name_Id := Name_First_Keyword + 039;
- Name_In : constant Name_Id := Name_First_Keyword + 040;
- Name_Inout : constant Name_Id := Name_First_Keyword + 041;
- Name_Is : constant Name_Id := Name_First_Keyword + 042;
-
- Name_Label : constant Name_Id := Name_First_Keyword + 043;
- Name_Library : constant Name_Id := Name_First_Keyword + 044;
- Name_Linkage : constant Name_Id := Name_First_Keyword + 045;
- Name_Loop : constant Name_Id := Name_First_Keyword + 046;
-
- Name_Map : constant Name_Id := Name_First_Keyword + 047;
-
- Name_New : constant Name_Id := Name_First_Keyword + 048;
- Name_Next : constant Name_Id := Name_First_Keyword + 049;
- Name_Null : constant Name_Id := Name_First_Keyword + 050;
-
- Name_Of : constant Name_Id := Name_First_Keyword + 051;
- Name_On : constant Name_Id := Name_First_Keyword + 052;
- Name_Open : constant Name_Id := Name_First_Keyword + 053;
- Name_Others : constant Name_Id := Name_First_Keyword + 054;
- Name_Out : constant Name_Id := Name_First_Keyword + 055;
-
- Name_Package : constant Name_Id := Name_First_Keyword + 056;
- Name_Port : constant Name_Id := Name_First_Keyword + 057;
- Name_Procedure : constant Name_Id := Name_First_Keyword + 058;
- Name_Process : constant Name_Id := Name_First_Keyword + 059;
-
- Name_Range : constant Name_Id := Name_First_Keyword + 060;
- Name_Record : constant Name_Id := Name_First_Keyword + 061;
- Name_Register : constant Name_Id := Name_First_Keyword + 062;
- Name_Report : constant Name_Id := Name_First_Keyword + 063;
- Name_Return : constant Name_Id := Name_First_Keyword + 064;
-
- Name_Select : constant Name_Id := Name_First_Keyword + 065;
- Name_Severity : constant Name_Id := Name_First_Keyword + 066;
- Name_Signal : constant Name_Id := Name_First_Keyword + 067;
- Name_Subtype : constant Name_Id := Name_First_Keyword + 068;
-
- Name_Then : constant Name_Id := Name_First_Keyword + 069;
- Name_To : constant Name_Id := Name_First_Keyword + 070;
- Name_Transport : constant Name_Id := Name_First_Keyword + 071;
- Name_Type : constant Name_Id := Name_First_Keyword + 072;
-
- Name_Units : constant Name_Id := Name_First_Keyword + 073;
- Name_Until : constant Name_Id := Name_First_Keyword + 074;
- Name_Use : constant Name_Id := Name_First_Keyword + 075;
-
- Name_Variable : constant Name_Id := Name_First_Keyword + 076;
-
- Name_Wait : constant Name_Id := Name_First_Keyword + 077;
- Name_When : constant Name_Id := Name_First_Keyword + 078;
- Name_While : constant Name_Id := Name_First_Keyword + 079;
- Name_With : constant Name_Id := Name_First_Keyword + 080;
-
- Name_Last_Vhdl87 : constant Name_Id := Name_With;
+ Name_Last_Vhdl87 : constant Name_Id := Name_Nor;
subtype Name_Id_Vhdl87_Reserved_Words is
- Name_Id range Name_First_Keyword .. Name_With;
+ Name_Id range Name_First_Keyword .. Name_Nor;
-- VHDL93 reserved words.
Name_Xnor : constant Name_Id := Name_First_Keyword + 081;
diff --git a/src/vhdl/disp_vhdl.adb b/src/vhdl/disp_vhdl.adb
index b82abe602..e675e718c 100644
--- a/src/vhdl/disp_vhdl.adb
+++ b/src/vhdl/disp_vhdl.adb
@@ -159,6 +159,7 @@ package body Disp_Vhdl is
case Id is
when Name_Id_Operators
| Name_Word_Operators
+ | Name_Logical_Operators
| Name_Xnor
| Name_Shift_Operators =>
Put ("""");
diff --git a/src/vhdl/parse.adb b/src/vhdl/parse.adb
index 37257914a..7c840de4f 100644
--- a/src/vhdl/parse.adb
+++ b/src/vhdl/parse.adb
@@ -49,8 +49,6 @@ package body Parse is
-- current_token must be valid.
-- Leaves a token.
- function Parse_Simple_Expression (Primary : Iir := Null_Iir)
- return Iir_Expression;
function Parse_Primary return Iir_Expression;
function Parse_Use_Clause return Iir_Use_Clause;
@@ -299,7 +297,7 @@ package body Parse is
-- Skip 'to' or 'downto'.
Scan;
- Set_Right_Limit_Expr (Res, Parse_Simple_Expression);
+ Set_Right_Limit_Expr (Res, Parse_Expression (Prio_Simple));
return Res;
end Parse_Range_Expression;
@@ -309,7 +307,7 @@ package body Parse is
is
Left: Iir;
begin
- Left := Parse_Simple_Expression;
+ Left := Parse_Expression (Prio_Simple);
case Current_Token is
when Tok_To
@@ -367,7 +365,7 @@ package body Parse is
is
Left: Iir;
begin
- Left := Parse_Simple_Expression;
+ Left := Parse_Expression (Prio_Simple);
case Current_Token is
when Tok_To
@@ -2014,7 +2012,7 @@ package body Parse is
-- Parse a simple expression (for the range), which can also parse a
-- name.
- Type_Mark := Parse_Simple_Expression;
+ Type_Mark := Parse_Expression (Prio_Simple);
case Current_Token is
when Tok_Range =>
@@ -5255,7 +5253,7 @@ package body Parse is
| Tok_Plus =>
Error_Msg_Parse
("'-' and '+' are not allowed in primary, use parenthesis");
- return Parse_Simple_Expression;
+ return Parse_Expression (Prio_Simple);
when Tok_Comma
| Tok_Semi_Colon
@@ -5272,80 +5270,118 @@ package body Parse is
end case;
end Parse_Primary;
- -- precond : next token
- -- postcond: next token
+ -- [ LRM08 9 Expressions ]
--
- -- [ LRM93 7.1 ]
- -- factor ::= primary [ ** primary ]
- -- | ABS primary
- -- | NOT primary
- -- | logical_operator primary [ VHDL08 9.1 ]
- function Build_Unary_Factor (Primary : Iir; Op : Iir_Kind) return Iir is
+ -- expression ::=
+ -- condition_operator primary
+ -- | logical_expression
+ --
+ -- logical_expression ::=
+ -- relation { and relation }
+ -- | relation { or relation }
+ -- | relation { xor relation }
+ -- | relation [ nand relation ]
+ -- | relation [ nor relation ]
+ -- | relation { xnor relation }
+ --
+ -- relation ::=
+ -- shift_expression [ relational_operator shift_expression ]
+ --
+ -- shift_expression ::=
+ -- simple_expression [ shift_operator simple_expression ]
+ --
+ -- simple_expression ::=
+ -- [ sign ] term { adding_operator term }
+ --
+ -- term ::=
+ -- factor { multiplying_operator factor }
+ --
+ -- factor ::=
+ -- primary [ ** primary ]
+ -- | abs primary
+ -- | not primary
+ -- | logical_operator primary
+ function Build_Unary_Factor (Op : Iir_Kind) return Iir
+ is
Res : Iir;
begin
- if Primary /= Null_Iir then
- return Primary;
- end if;
Res := Create_Iir (Op);
Set_Location (Res);
+
+ -- Skip operator.
Scan;
+
Set_Operand (Res, Parse_Primary);
+
return Res;
end Build_Unary_Factor;
- function Build_Unary_Factor_08 (Primary : Iir; Op : Iir_Kind) return Iir is
+ function Build_Unary_Simple (Op : Iir_Kind) return Iir
+ is
+ Res : Iir;
+ begin
+ Res := Create_Iir (Op);
+ Set_Location (Res);
+
+ -- Skip operator.
+ Scan;
+
+ Set_Operand (Res, Parse_Expression (Prio_Term));
+
+ return Res;
+ end Build_Unary_Simple;
+
+ function Build_Unary_Factor_08 (Op : Iir_Kind) return Iir is
begin
- if Primary /= Null_Iir then
- return Primary;
- end if;
if Flags.Vhdl_Std < Vhdl_08 then
Error_Msg_Parse ("missing left operand of logical expression");
+
-- Skip operator
Scan;
+
return Parse_Primary;
else
- return Build_Unary_Factor (Primary, Op);
+ return Build_Unary_Factor (Op);
end if;
end Build_Unary_Factor_08;
- function Parse_Factor (Primary : Iir := Null_Iir) return Iir_Expression is
- Res, Left: Iir_Expression;
+ function Parse_Unary_Expression return Iir
+ is
+ Res, Left : Iir_Expression;
begin
case Current_Token is
+ when Tok_Plus =>
+ return Build_Unary_Simple (Iir_Kind_Identity_Operator);
+ when Tok_Minus =>
+ return Build_Unary_Simple (Iir_Kind_Negation_Operator);
+
when Tok_Abs =>
- return Build_Unary_Factor (Primary, Iir_Kind_Absolute_Operator);
+ return Build_Unary_Factor (Iir_Kind_Absolute_Operator);
when Tok_Not =>
- return Build_Unary_Factor (Primary, Iir_Kind_Not_Operator);
+ return Build_Unary_Factor (Iir_Kind_Not_Operator);
when Tok_And =>
- return Build_Unary_Factor_08
- (Primary, Iir_Kind_Reduction_And_Operator);
+ return Build_Unary_Factor_08 (Iir_Kind_Reduction_And_Operator);
when Tok_Or =>
- return Build_Unary_Factor_08
- (Primary, Iir_Kind_Reduction_Or_Operator);
+ return Build_Unary_Factor_08 (Iir_Kind_Reduction_Or_Operator);
when Tok_Nand =>
- return Build_Unary_Factor_08
- (Primary, Iir_Kind_Reduction_Nand_Operator);
+ return Build_Unary_Factor_08 (Iir_Kind_Reduction_Nand_Operator);
when Tok_Nor =>
- return Build_Unary_Factor_08
- (Primary, Iir_Kind_Reduction_Nor_Operator);
+ return Build_Unary_Factor_08 (Iir_Kind_Reduction_Nor_Operator);
when Tok_Xor =>
- return Build_Unary_Factor_08
- (Primary, Iir_Kind_Reduction_Xor_Operator);
+ return Build_Unary_Factor_08 (Iir_Kind_Reduction_Xor_Operator);
when Tok_Xnor =>
- return Build_Unary_Factor_08
- (Primary, Iir_Kind_Reduction_Xnor_Operator);
+ return Build_Unary_Factor_08 (Iir_Kind_Reduction_Xnor_Operator);
when others =>
- if Primary /= Null_Iir then
- Left := Primary;
- else
- Left := Parse_Primary;
- end if;
+ Left := Parse_Primary;
if Current_Token = Tok_Double_Star then
Res := Create_Iir (Iir_Kind_Exponentiation_Operator);
Set_Location (Res);
+
+ -- Skip '**'.
Scan;
+
Set_Left (Res, Left);
Set_Right (Res, Parse_Primary);
return Res;
@@ -5353,272 +5389,135 @@ package body Parse is
return Left;
end if;
end case;
- end Parse_Factor;
+ end Parse_Unary_Expression;
- -- precond : next token
- -- postcond: next token
- --
- -- [ LRM93 7.1 ]
- -- term ::= factor { multiplying_operator factor }
- --
- -- [ LRM93 7.2 ]
- -- multiplying_operator ::= * | / | MOD | REM
- function Parse_Term (Primary : Iir) return Iir_Expression is
- Res, Tmp: Iir_Expression;
+ -- Example: When PRIO is Prio_Simple, a simple expression will be returned.
+ function Parse_Binary_Expression (Left : Iir; Prio : Prio_Type) return Iir
+ is
+ Res : Iir;
+ Expr : Iir;
+ Op : Iir_Kind;
+ Op_Prio : Prio_Type;
+ Op_Tok : Token_Type;
begin
- Res := Parse_Factor (Primary);
- while Current_Token in Token_Multiplying_Operator_Type loop
- case Current_Token is
+ Res := Left;
+ loop
+ Op_Tok := Current_Token;
+ case Op_Tok is
when Tok_Star =>
- Tmp := Create_Iir (Iir_Kind_Multiplication_Operator);
+ Op := Iir_Kind_Multiplication_Operator;
+ Op_Prio := Prio_Term;
when Tok_Slash =>
- Tmp := Create_Iir (Iir_Kind_Division_Operator);
+ Op := Iir_Kind_Division_Operator;
+ Op_Prio := Prio_Term;
when Tok_Mod =>
- Tmp := Create_Iir (Iir_Kind_Modulus_Operator);
+ Op := Iir_Kind_Modulus_Operator;
+ Op_Prio := Prio_Term;
when Tok_Rem =>
- Tmp := Create_Iir (Iir_Kind_Remainder_Operator);
- when others =>
- raise Program_Error;
- end case;
- Set_Location (Tmp);
- Set_Left (Tmp, Res);
- Scan;
- Set_Right (Tmp, Parse_Factor);
- Res := Tmp;
- end loop;
- return Res;
- end Parse_Term;
+ Op := Iir_Kind_Remainder_Operator;
+ Op_Prio := Prio_Term;
- -- precond : next token
- -- postcond: next token
- --
- -- [ LRM93 7.1 ]
- -- simple_expression ::= [ sign ] term { adding_operator term }
- --
- -- [ LRM93 7.2 ]
- -- sign ::= + | -
- --
- -- [ LRM93 7.2 ]
- -- adding_operator ::= + | - | &
- function Parse_Simple_Expression (Primary : Iir := Null_Iir)
- return Iir_Expression
- is
- Res, Tmp: Iir_Expression;
- begin
- if Current_Token in Token_Sign_Type
- and then Primary = Null_Iir
- then
- case Current_Token is
- when Tok_Plus =>
- Res := Create_Iir (Iir_Kind_Identity_Operator);
- when Tok_Minus =>
- Res := Create_Iir (Iir_Kind_Negation_Operator);
- when others =>
- raise Program_Error;
- end case;
- Set_Location (Res);
- Scan;
- Set_Operand (Res, Parse_Term (Null_Iir));
- else
- Res := Parse_Term (Primary);
- end if;
- while Current_Token in Token_Adding_Operator_Type loop
- case Current_Token is
when Tok_Plus =>
- Tmp := Create_Iir (Iir_Kind_Addition_Operator);
+ Op := Iir_Kind_Addition_Operator;
+ Op_Prio := Prio_Simple;
when Tok_Minus =>
- Tmp := Create_Iir (Iir_Kind_Substraction_Operator);
+ Op := Iir_Kind_Substraction_Operator;
+ Op_Prio := Prio_Simple;
when Tok_Ampersand =>
- Tmp := Create_Iir (Iir_Kind_Concatenation_Operator);
- when others =>
- raise Program_Error;
- end case;
- Set_Location (Tmp);
- Scan;
- Set_Left (Tmp, Res);
- Set_Right (Tmp, Parse_Term (Null_Iir));
- Res := Tmp;
- end loop;
- return Res;
- end Parse_Simple_Expression;
-
- -- precond : next token
- -- postcond: next token
- --
- -- [ LRM93 7.1 ]
- -- shift_expression ::=
- -- simple_expression [ shift_operator simple_expression ]
- --
- -- [ LRM93 7.2 ]
- -- shift_operator ::= SLL | SRL | SLA | SRA | ROL | ROR
- function Parse_Shift_Expression return Iir_Expression is
- Res, Tmp: Iir_Expression;
- begin
- Tmp := Parse_Simple_Expression;
- if Current_Token not in Token_Shift_Operator_Type then
- return Tmp;
- elsif Flags.Vhdl_Std = Vhdl_87 then
- Error_Msg_Parse ("shift operators not allowed in vhdl 87");
- end if;
- case Current_Token is
- when Tok_Sll =>
- Res := Create_Iir (Iir_Kind_Sll_Operator);
- when Tok_Sla =>
- Res := Create_Iir (Iir_Kind_Sla_Operator);
- when Tok_Srl =>
- Res := Create_Iir (Iir_Kind_Srl_Operator);
- when Tok_Sra =>
- Res := Create_Iir (Iir_Kind_Sra_Operator);
- when Tok_Rol =>
- Res := Create_Iir (Iir_Kind_Rol_Operator);
- when Tok_Ror =>
- Res := Create_Iir (Iir_Kind_Ror_Operator);
- when others =>
- raise Program_Error;
- end case;
- Set_Location (Res);
- Scan;
- Set_Left (Res, Tmp);
- Set_Right (Res, Parse_Simple_Expression);
- return Res;
- end Parse_Shift_Expression;
+ Op := Iir_Kind_Concatenation_Operator;
+ Op_Prio := Prio_Simple;
+
+ when Tok_Sll =>
+ Op := Iir_Kind_Sll_Operator;
+ Op_Prio := Prio_Shift;
+ when Tok_Sla =>
+ Op := Iir_Kind_Sla_Operator;
+ Op_Prio := Prio_Shift;
+ when Tok_Srl =>
+ Op := Iir_Kind_Srl_Operator;
+ Op_Prio := Prio_Shift;
+ when Tok_Sra =>
+ Op := Iir_Kind_Sra_Operator;
+ Op_Prio := Prio_Shift;
+ when Tok_Rol =>
+ Op := Iir_Kind_Rol_Operator;
+ Op_Prio := Prio_Shift;
+ when Tok_Ror =>
+ Op := Iir_Kind_Ror_Operator;
+ Op_Prio := Prio_Shift;
- -- precond : next token (relational_operator)
- -- postcond: next token
- --
- -- [ LRM93 7.1 ]
- -- relational_operator shift_expression
- function Parse_Relation_Rhs (Left : Iir) return Iir
- is
- Res, Tmp: Iir_Expression;
- begin
- Tmp := Left;
-
- -- This loop is just to handle errors such as a = b = c.
- loop
- case Current_Token is
when Tok_Equal =>
- Res := Create_Iir (Iir_Kind_Equality_Operator);
+ Op := Iir_Kind_Equality_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Not_Equal =>
- Res := Create_Iir (Iir_Kind_Inequality_Operator);
+ Op := Iir_Kind_Inequality_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Less =>
- Res := Create_Iir (Iir_Kind_Less_Than_Operator);
+ Op := Iir_Kind_Less_Than_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Less_Equal =>
- Res := Create_Iir (Iir_Kind_Less_Than_Or_Equal_Operator);
+ Op := Iir_Kind_Less_Than_Or_Equal_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Greater =>
- Res := Create_Iir (Iir_Kind_Greater_Than_Operator);
+ Op := Iir_Kind_Greater_Than_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Greater_Equal =>
- Res := Create_Iir (Iir_Kind_Greater_Than_Or_Equal_Operator);
+ Op := Iir_Kind_Greater_Than_Or_Equal_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Match_Equal =>
- Res := Create_Iir (Iir_Kind_Match_Equality_Operator);
+ Op := Iir_Kind_Match_Equality_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Match_Not_Equal =>
- Res := Create_Iir (Iir_Kind_Match_Inequality_Operator);
+ Op := Iir_Kind_Match_Inequality_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Match_Less =>
- Res := Create_Iir (Iir_Kind_Match_Less_Than_Operator);
+ Op := Iir_Kind_Match_Less_Than_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Match_Less_Equal =>
- Res := Create_Iir (Iir_Kind_Match_Less_Than_Or_Equal_Operator);
+ Op := Iir_Kind_Match_Less_Than_Or_Equal_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Match_Greater =>
- Res := Create_Iir (Iir_Kind_Match_Greater_Than_Operator);
+ Op := Iir_Kind_Match_Greater_Than_Operator;
+ Op_Prio := Prio_Relation;
when Tok_Match_Greater_Equal =>
- Res := Create_Iir
- (Iir_Kind_Match_Greater_Than_Or_Equal_Operator);
- when others =>
- raise Program_Error;
- end case;
- Set_Location (Res);
- Scan;
- Set_Left (Res, Tmp);
- Set_Right (Res, Parse_Shift_Expression);
- exit when Current_Token not in Token_Relational_Operator_Type;
- Error_Msg_Parse
- ("use parenthesis for consecutive relational expressions");
- Tmp := Res;
- end loop;
- return Res;
- end Parse_Relation_Rhs;
-
- -- precond : next token
- -- postcond: next token
- --
- -- [ LRM93 7.1 ]
- -- relation ::= shift_expression [ relational_operator shift_expression ]
- --
- -- [ LRM93 7.2 ]
- -- relational_operator ::= = | /= | < | <= | > | >=
- -- | ?= | ?/= | ?< | ?<= | ?> | ?>=
- function Parse_Relation return Iir
- is
- Tmp: Iir;
- begin
- Tmp := Parse_Shift_Expression;
- if Current_Token not in Token_Relational_Operator_Type then
- return Tmp;
- end if;
-
- return Parse_Relation_Rhs (Tmp);
- end Parse_Relation;
-
- -- precond : next token
- -- postcond: next token
- --
- -- [ LRM93 7.1 ]
- -- expression ::= relation { AND relation }
- -- | relation { OR relation }
- -- | relation { XOR relation }
- -- | relation [ NAND relation }
- -- | relation [ NOR relation }
- -- | relation { XNOR relation }
- function Parse_Expression_Rhs (Left : Iir) return Iir
- is
- Res, Tmp: Iir;
+ Op := Iir_Kind_Match_Greater_Than_Or_Equal_Operator;
+ Op_Prio := Prio_Relation;
- -- OP_TOKEN contains the operator combinaison.
- Op_Token: Token_Type;
- begin
- Tmp := Left;
- Op_Token := Tok_Invalid;
- loop
- case Current_Token is
when Tok_And =>
- Res := Create_Iir (Iir_Kind_And_Operator);
+ Op := Iir_Kind_And_Operator;
+ Op_Prio := Prio_Logical;
when Tok_Or =>
- Res := Create_Iir (Iir_Kind_Or_Operator);
+ Op := Iir_Kind_Or_Operator;
+ Op_Prio := Prio_Logical;
when Tok_Xor =>
- Res := Create_Iir (Iir_Kind_Xor_Operator);
+ Op := Iir_Kind_Xor_Operator;
+ Op_Prio := Prio_Logical;
when Tok_Nand =>
- Res := Create_Iir (Iir_Kind_Nand_Operator);
+ Op := Iir_Kind_Nand_Operator;
+ Op_Prio := Prio_Logical;
when Tok_Nor =>
- Res := Create_Iir (Iir_Kind_Nor_Operator);
+ Op := Iir_Kind_Nor_Operator;
+ Op_Prio := Prio_Logical;
when Tok_Xnor =>
- if Flags.Vhdl_Std = Vhdl_87 then
- Error_Msg_Parse ("'xnor' keyword not allowed in vhdl 87");
- end if;
- Res := Create_Iir (Iir_Kind_Xnor_Operator);
+ Op := Iir_Kind_Xnor_Operator;
+ Op_Prio := Prio_Logical;
+
when others =>
- return Tmp;
+ return Res;
end case;
- if Op_Token = Tok_Invalid then
- Op_Token := Current_Token;
- else
- -- Check after the case, since current_token may not be an
- -- operator...
- -- TODO: avoid repetition of this message ?
- if Op_Token = Tok_Nand or Op_Token = Tok_Nor then
- Error_Msg_Parse
- ("sequence of 'nor' or 'nand' not allowed", Cont => True);
- Error_Msg_Parse
- ("('nor' and 'nand' are not associative)");
- end if;
- if Op_Token /= Current_Token then
- -- Expression is a sequence of relations, with the same
- -- operator.
- Error_Msg_Parse ("only one type of logical operators may be "
- & "used to combine relation");
- end if;
+ -- If the OP_PRIO is less than PRIO, the binary operator will apply
+ -- to the whole expression.
+ -- eg: A * B + C
+ if Op_Prio < Prio then
+ return Res;
end if;
- Set_Location (Res);
+ Expr := Create_Iir (Op);
+ Set_Location (Expr);
+ Set_Left (Expr, Res);
+
+ -- Skip operator.
Scan;
-- Catch errors for Ada programmers.
@@ -5630,23 +5529,55 @@ package body Parse is
Scan;
end if;
- Set_Left (Res, Tmp);
- Set_Right (Res, Parse_Relation);
- Tmp := Res;
+ if Op_Prio >= Prio_Simple and then Current_Token in Token_Sign_Type
+ then
+ Error_Msg_Parse ("'-'/'+' can only appear before the first term");
+ end if;
+
+ -- Left association: A + B + C is (A + B) + C
+ Set_Right (Expr, Parse_Expression (Prio_Type'Succ (Op_Prio)));
+ Res := Expr;
+
+ -- Only one relational_operator or shift_operator.
+ if Op_Prio = Prio_Relation then
+ if Current_Token in Token_Relational_Operator_Type then
+ Error_Msg_Parse
+ ("use parenthesis for consecutive relational expressions");
+ end if;
+ elsif Op_Prio = Prio_Shift then
+ -- Only one shift_operator.
+ if Current_Token in Token_Shift_Operator_Type then
+ Error_Msg_Parse
+ ("use parenthesis for consecutive shift expressions");
+ end if;
+ elsif Op_Prio = Prio_Logical then
+ if Current_Token = Op_Tok then
+ if Op_Tok = Tok_Nand or Op_Tok = Tok_Nor then
+ Error_Msg_Parse
+ ("sequence of 'nor' or 'nand' not allowed", Cont => True);
+ Error_Msg_Parse
+ ("('nor' and 'nand' are not associative)");
+ end if;
+ elsif Current_Token in Token_Logical_Type then
+ -- Expression is a sequence of relations, with the same
+ -- operator.
+ Error_Msg_Parse ("only one type of logical operators may be "
+ & "used to combine relation");
+ end if;
+ end if;
end loop;
- end Parse_Expression_Rhs;
+ end Parse_Binary_Expression;
- -- precond : next token
- -- postcond: next token
- --
- -- LRM08 9.1 General
- -- expression ::= condition_operator primary
- -- | logical_expression
- function Parse_Expression return Iir_Expression
+ function Parse_Expression (Prio : Prio_Type := Prio_Expression) return Iir
is
+ Left : Iir;
Res : Iir;
begin
if Current_Token = Tok_Condition then
+ if Prio /= Prio_Expression then
+ Error_Msg_Parse
+ ("'??' must be the first operator of an expression");
+ end if;
Res := Create_Iir (Iir_Kind_Condition_Operator);
Set_Location (Res);
@@ -5655,7 +5586,8 @@ package body Parse is
Set_Operand (Res, Parse_Primary);
else
- Res := Parse_Expression_Rhs (Parse_Relation);
+ Left := Parse_Unary_Expression;
+ Res := Parse_Binary_Expression (Left, Prio);
end if;
return Res;
@@ -8084,20 +8016,21 @@ package body Parse is
-- or a simple simultaneous statement
if AMS_Vhdl then
Res := Create_Iir (Iir_Kind_Simple_Simultaneous_Statement);
- Set_Simultaneous_Left (Res, Parse_Simple_Expression (Target));
+ Set_Simultaneous_Left
+ (Res, Parse_Binary_Expression (Target, Prio_Simple));
if Current_Token /= Tok_Equal_Equal then
Error_Msg_Parse ("'==' expected after expression");
else
Set_Location (Res);
Scan;
end if;
- Set_Simultaneous_Right (Res, Parse_Simple_Expression);
+ Set_Simultaneous_Right (Res, Parse_Expression (Prio_Simple));
Set_Tolerance (Res, Parse_Tolerance_Aspect_Opt);
Expect (Tok_Semi_Colon);
return Res;
else
return Parse_Concurrent_Conditional_Signal_Assignment
- (Parse_Simple_Expression (Target));
+ (Parse_Binary_Expression (Target, Prio_Simple));
end if;
end case;
end Parse_Concurrent_Assignment;
diff --git a/src/vhdl/parse.ads b/src/vhdl/parse.ads
index 9a80d1e33..8204a2d0e 100644
--- a/src/vhdl/parse.ads
+++ b/src/vhdl/parse.ads
@@ -22,13 +22,21 @@ package Parse is
-- If True, create nodes for parenthesis expressions.
Flag_Parse_Parenthesis : Boolean := False;
+ type Prio_Type is
+ (
+ Prio_Expression,
+ Prio_Logical,
+ Prio_Relation,
+ Prio_Shift,
+ Prio_Simple,
+ Prio_Term,
+ Prio_Factor
+ );
+
-- Parse an expression.
-- (Used by PSL).
- function Parse_Expression return Iir;
- function Parse_Expression_Rhs (Left : Iir) return Iir;
-
- -- Parse an relationnal operator and its rhs.
- function Parse_Relation_Rhs (Left : Iir) return Iir;
+ function Parse_Expression (Prio : Prio_Type := Prio_Expression) return Iir;
+ function Parse_Binary_Expression (Left : Iir; Prio : Prio_Type) return Iir;
-- Convert the STR (0 .. LEN - 1) into a operator symbol identifier.
-- Emit an error message if the name is not an operator name.
diff --git a/src/vhdl/parse_psl.adb b/src/vhdl/parse_psl.adb
index 4c682ae3f..6a0e906e4 100644
--- a/src/vhdl/parse_psl.adb
+++ b/src/vhdl/parse_psl.adb
@@ -359,13 +359,26 @@ package body Parse_Psl is
Error_Msg_Parse ("'(' expected around property");
return Parse_FL_Property (Prio_Lowest);
else
+ -- Skip '('.
Scan;
+
Res := Parse_FL_Property (Prio_Lowest);
- if Current_Token /= Tok_Right_Paren then
+ if Current_Token = Tok_Right_Paren then
+ -- Skip ')'.
+ Scan;
+ else
Error_Msg_Parse ("missing matching ')' for '(' at line "
& Image (Loc, False));
- else
- Scan;
+ end if;
+
+ if Get_Kind (Res) = N_HDL_Expr then
+ declare
+ N : Iirs.Iir;
+ begin
+ N := Psl_To_Vhdl (Res);
+ N := Parse.Parse_Binary_Expression (N, Parse.Prio_Expression);
+ Res := Vhdl_To_Psl (N);
+ end;
end if;
return Res;
end if;
@@ -558,7 +571,8 @@ package body Parse_Psl is
Res := Parse_Binary_FL_Property (N_And_Prop, Res, Prio_Seq_And);
when Token_Relational_Operator_Type =>
return Vhdl_To_Psl
- (Parse.Parse_Relation_Rhs (Psl_To_Vhdl (Res)));
+ (Parse.Parse_Binary_Expression
+ (Psl_To_Vhdl (Res), Parse.Prio_Relation));
when Tok_Colon
| Tok_Bar
| Tok_Ampersand
diff --git a/src/vhdl/tokens.ads b/src/vhdl/tokens.ads
index 42def9f3d..fc555ce71 100644
--- a/src/vhdl/tokens.ads
+++ b/src/vhdl/tokens.ads
@@ -106,13 +106,6 @@ package Tokens is
Tok_Mod, -- mod
Tok_Rem, -- rem
- -- relation token:
- Tok_And,
- Tok_Or,
- Tok_Xor,
- Tok_Nand,
- Tok_Nor,
-
-- miscellaneous operator
Tok_Abs,
Tok_Not,
@@ -209,8 +202,17 @@ package Tokens is
Tok_While,
Tok_With,
- -- Tokens below this line are key words in vhdl93 but not in vhdl87
+ -- logical token:
+ Tok_And,
+ Tok_Or,
+ Tok_Xor,
+ Tok_Nand,
+ Tok_Nor,
+
+ -- Tokens below this line are key words in vhdl93 but not in vhdl87
+ -- Note: xnor is the first one, as it is a logical token.
Tok_Xnor,
+
Tok_Group,
Tok_Impure,
Tok_Inertial,
@@ -279,6 +281,9 @@ package Tokens is
-- To ease interfacing
pragma Convention (C, Token_Type);
+ subtype Token_Logical_Type is Token_Type range
+ Tok_And .. Tok_Xnor;
+
subtype Token_Relational_Operator_Type is Token_Type range
Tok_Equal .. Tok_Match_Greater_Equal;
subtype Token_Shift_Operator_Type is Token_Type range