aboutsummaryrefslogtreecommitdiffstats
path: root/src/vhdl/parse.adb
diff options
context:
space:
mode:
Diffstat (limited to 'src/vhdl/parse.adb')
-rw-r--r--src/vhdl/parse.adb247
1 files changed, 196 insertions, 51 deletions
diff --git a/src/vhdl/parse.adb b/src/vhdl/parse.adb
index edcdb7a19..2991e07e3 100644
--- a/src/vhdl/parse.adb
+++ b/src/vhdl/parse.adb
@@ -4935,7 +4935,7 @@ package body Parse is
-- precond : next token
-- postcond: next token
--
- -- [ §9.5 ]
+ -- [ LRM93 9.5 ]
-- options ::= [ GUARDED ] [ delay_mechanism ]
procedure Parse_Options (Stmt : Iir) is
begin
@@ -4947,26 +4947,75 @@ package body Parse is
end Parse_Options;
-- precond : next tkoen
- -- postcond: ';'
- --
- -- [ §9.5.1 ]
- -- conditional_signal_assignment ::=
- -- target <= options conditional_waveforms ;
+ -- postcond: next token (';')
--
- -- [ §9.5.1 ]
+ -- [ LRM93 9.5.1 ]
-- conditional_waveforms ::=
-- { waveform WHEN condition ELSE }
-- waveform [ WHEN condition ]
- function Parse_Conditional_Signal_Assignment (Target: Iir) return Iir
+ function Parse_Conditional_Waveforms return Iir
is
- use Iir_Chains.Conditional_Waveform_Chain_Handling;
- Res: Iir;
- Cond_Wf, Last_Cond_Wf : Iir_Conditional_Waveform;
+ Wf : Iir;
+ Res : Iir;
+ Cond_Wf, N_Cond_Wf : Iir_Conditional_Waveform;
begin
- Res := Create_Iir (Iir_Kind_Concurrent_Conditional_Signal_Assignment);
- Set_Target (Res, Target);
- Location_Copy (Res, Get_Target (Res));
+ Wf := Parse_Waveform;
+ if Current_Token /= Tok_When then
+ return Wf;
+ else
+ Res := Create_Iir (Iir_Kind_Conditional_Waveform);
+ Set_Location (Res);
+ Set_Waveform_Chain (Res, Wf);
+
+ Cond_Wf := Res;
+ loop
+ -- Eat 'when'
+ Scan;
+
+ Set_Condition (Cond_Wf, Parse_Expression);
+
+ if Current_Token /= Tok_Else then
+ if Flags.Vhdl_Std = Vhdl_87 then
+ Error_Msg_Parse ("else missing in vhdl 87");
+ end if;
+ exit;
+ end if;
+
+ N_Cond_Wf := Create_Iir (Iir_Kind_Conditional_Waveform);
+ Set_Location (N_Cond_Wf);
+ Set_Chain (Cond_Wf, N_Cond_Wf);
+ Cond_Wf := N_Cond_Wf;
+
+ -- Eat 'else'
+ Scan;
+
+ Set_Waveform_Chain (Cond_Wf, Parse_Waveform);
+
+ exit when Current_Token /= Tok_When;
+ end loop;
+ return Res;
+ end if;
+ end Parse_Conditional_Waveforms;
+ -- precond : '<=' (or ':=')
+ -- postcond: ';'
+ --
+ -- [ LRM93 9.5.1 ]
+ -- concurrent_conditional_signal_assignment ::=
+ -- target <= [ GUARDED ] [ delay_mechanism ] conditional_waveforms ;
+ --
+ -- [ LRM08 10.5.2.1 ]
+ -- concurrent_simple_waveform_assignment ::=
+ -- target <= [ GUARDED ] [ delay_mechanism ] waveform ;
+ function Parse_Concurrent_Conditional_Signal_Assignment (Target: Iir)
+ return Iir
+ is
+ Res: Iir;
+ Loc : Location_Type;
+ N_Res : Iir;
+ Wf : Iir;
+ begin
+ Loc := Get_Token_Location;
case Current_Token is
when Tok_Less_Equal =>
null;
@@ -4976,30 +5025,34 @@ package body Parse is
when others =>
Expect (Tok_Less_Equal);
end case;
+
+ -- Eat '<='.
Scan;
+ -- Assume simple signal assignment.
+ Res := Create_Iir (Iir_Kind_Concurrent_Simple_Signal_Assignment);
Parse_Options (Res);
- Build_Init (Last_Cond_Wf);
- loop
- Cond_Wf := Create_Iir (Iir_Kind_Conditional_Waveform);
- Append (Last_Cond_Wf, Res, Cond_Wf);
- Set_Location (Cond_Wf);
- Set_Waveform_Chain (Cond_Wf, Parse_Waveform);
- exit when Current_Token /= Tok_When;
- Scan;
- Set_Condition (Cond_Wf, Parse_Expression);
- if Current_Token /= Tok_Else then
- if Flags.Vhdl_Std = Vhdl_87 then
- Error_Msg_Parse ("else missing in vhdl 87");
- end if;
- exit;
+ Wf := Parse_Conditional_Waveforms;
+ if Get_Kind (Wf) = Iir_Kind_Conditional_Waveform then
+ N_Res :=
+ Create_Iir (Iir_Kind_Concurrent_Conditional_Signal_Assignment);
+ if Get_Guard (Res) /= Null_Iir then
+ Set_Guard (N_Res, N_Res);
end if;
- Scan;
- end loop;
+ Set_Delay_Mechanism (N_Res, Get_Delay_Mechanism (Res));
+ Set_Reject_Time_Expression (N_Res, Get_Reject_Time_Expression (Res));
+ Free_Iir (Res);
+ Res := N_Res;
+ Set_Conditional_Waveform_Chain (Res, Wf);
+ else
+ Set_Waveform_Chain (Res, Wf);
+ end if;
+ Set_Location (Res, Loc);
+ Set_Target (Res, Target);
Expect (Tok_Semi_Colon);
return Res;
- end Parse_Conditional_Signal_Assignment;
+ end Parse_Concurrent_Conditional_Signal_Assignment;
-- precond : WITH
-- postcond: ';'
@@ -5336,53 +5389,145 @@ package body Parse is
-- precond: '<='
-- postcond: next token
--
- -- [ §8.4 ]
+ -- [ LRM93 8.4 ]
-- signal_assignment_statement ::=
-- [ label : ] target <= [ delay_mechanism ] waveform ;
+ --
+ -- [ LRM08 10.5 Signal assignment statement ]
+ -- signal_assignement_statement ::=
+ -- [ label : ] simple_signal_assignement
+ -- | [ label : ] conditional_signal_assignement
+ -- | [ label : ] selected_signal_assignement (TODO)
function Parse_Signal_Assignment_Statement (Target : Iir) return Iir
is
Stmt : Iir;
- Wave_Chain : Iir_Waveform_Element;
+ N_Stmt : Iir;
+ Wave_Chain : Iir;
begin
- Stmt := Create_Iir (Iir_Kind_Signal_Assignment_Statement);
- Location_Copy (Stmt, Target);
+ Stmt := Create_Iir (Iir_Kind_Simple_Signal_Assignment_Statement);
+ Set_Location (Stmt);
Set_Target (Stmt, Target);
+
+ -- Eat '<='.
Scan;
+
Parse_Delay_Mechanism (Stmt);
- Wave_Chain := Parse_Waveform;
+
+ Wave_Chain := Parse_Conditional_Waveforms;
+
-- LRM 8.4 Signal assignment statement
-- It is an error is the reserved word UNAFFECTED appears as a
- -- waveform in a (sequential) signa assignment statement.
+ -- waveform in a (sequential) signal assignment statement.
if Wave_Chain = Null_Iir then
Error_Msg_Parse
("'unaffected' is not allowed in a sequential statement");
+ elsif Get_Kind (Wave_Chain) = Iir_Kind_Conditional_Waveform then
+ if Flags.Vhdl_Std < Vhdl_08 then
+ Error_Msg_Parse
+ ("conditional signal assignment not allowed in before vhdl08");
+ end if;
+ N_Stmt :=
+ Create_Iir (Iir_Kind_Conditional_Signal_Assignment_Statement);
+ Location_Copy (N_Stmt, Stmt);
+ Set_Target (N_Stmt, Target);
+ Set_Delay_Mechanism (N_Stmt, Get_Delay_Mechanism (Stmt));
+ Set_Reject_Time_Expression
+ (N_Stmt, Get_Reject_Time_Expression (Stmt));
+ Set_Conditional_Waveform_Chain (N_Stmt, Wave_Chain);
+ Free_Iir (Stmt);
+ Stmt := N_Stmt;
+ else
+ Set_Waveform_Chain (Stmt, Wave_Chain);
end if;
- Set_Waveform_Chain (Stmt, Wave_Chain);
+
return Stmt;
end Parse_Signal_Assignment_Statement;
+ -- precond: WHEN
+ -- postcond: next token
+ --
+ -- [ LRM08 10.5.3 Conditional signal assignments ]
+ -- conditional_expressions ::=
+ -- expression WHEN condition
+ -- { ELSE expression WHEN condition }
+ -- [ ELSE expression ]
+ function Parse_Conditional_Expression (Expr : Iir) return Iir
+ is
+ Res : Iir;
+ El, N_El : Iir;
+ begin
+ Res := Create_Iir (Iir_Kind_Conditional_Expression);
+ Set_Location (Res);
+ Set_Expression (Res, Expr);
+ El := Res;
+
+ loop
+ -- Eat 'when'
+ Scan;
+
+ Set_Condition (El, Parse_Expression);
+
+ exit when Current_Token /= Tok_Else;
+
+ N_El := Create_Iir (Iir_Kind_Conditional_Expression);
+ Set_Location (N_El);
+ Set_Chain (El, N_El);
+ El := N_El;
+
+ -- Eat 'else'
+ Scan;
+
+ Set_Expression (N_El, Parse_Expression);
+
+ exit when Current_Token /= Tok_When;
+ end loop;
+
+ return Res;
+ end Parse_Conditional_Expression;
+
-- precond: ':='
-- postcond: next token
--
- -- [ §8.5 ]
+ -- [ LRM93 8.5 ]
-- variable_assignment_statement ::=
-- [ label : ] target := expression ;
function Parse_Variable_Assignment_Statement (Target : Iir) return Iir
is
Stmt : Iir;
+ Loc : Location_Type;
+ Expr : Iir;
begin
- Stmt := Create_Iir (Iir_Kind_Variable_Assignment_Statement);
- Location_Copy (Stmt, Target);
- Set_Target (Stmt, Target);
+ Loc := Get_Token_Location;
+
+ -- Eat ':='
Scan;
- Set_Expression (Stmt, Parse_Expression);
+
+ Expr := Parse_Expression;
+
+ if Current_Token = Tok_When then
+ if Flags.Vhdl_Std < Vhdl_08 then
+ Error_Msg_Parse
+ ("conditional variable assignment not allowed before vhdl08");
+ end if;
+ Stmt :=
+ Create_Iir (Iir_Kind_Conditional_Variable_Assignment_Statement);
+ Set_Location (Stmt, Loc);
+ Set_Target (Stmt, Target);
+ Set_Conditional_Expression
+ (Stmt, Parse_Conditional_Expression (Expr));
+ else
+ Stmt := Create_Iir (Iir_Kind_Variable_Assignment_Statement);
+ Set_Location (Stmt, Loc);
+ Set_Target (Stmt, Target);
+ Set_Expression (Stmt, Expr);
+ end if;
return Stmt;
end Parse_Variable_Assignment_Statement;
-- precond: next token
-- postcond: next token
--
- -- [ 8 ]
+ -- [ LRM93 8 ]
-- sequence_of_statement ::= { sequential_statement }
--
-- [ 8 ]
@@ -6641,7 +6786,7 @@ package body Parse is
-- precond : first token
-- postcond: END
--
- -- [ §9 ]
+ -- [ LRM93 9 ]
-- concurrent_statement ::= block_statement
-- | process_statement
-- | concurrent_procedure_call_statement
@@ -6650,15 +6795,15 @@ package body Parse is
-- | component_instantiation_statement
-- | generate_statement
--
- -- [ §9.4 ]
+ -- [ LRM93 9.4 ]
-- concurrent_assertion_statement ::=
-- [ label : ] [ POSTPONED ] assertion ;
--
- -- [ §9.3 ]
+ -- [ LRM93 9.3 ]
-- concurrent_procedure_call_statement ::=
-- [ label : ] [ POSTPONED ] procedure_call ;
--
- -- [ §9.5 ]
+ -- [ LRM93 9.5 ]
-- concurrent_signal_assignment_statement ::=
-- [ label : ] [ POSTPONED ] conditional_signal_assignment
-- | [ label : ] [ POSTPONED ] selected_signal_assignment
@@ -6671,7 +6816,7 @@ package body Parse is
| Tok_Assign =>
-- This is a conditional signal assignment.
-- Error for ':=' is handled by the subprogram.
- return Parse_Conditional_Signal_Assignment (Target);
+ return Parse_Concurrent_Conditional_Signal_Assignment (Target);
when Tok_Semi_Colon =>
-- a procedure call or a component instantiation.
-- Parse it as a procedure call, may be revert to a
@@ -6698,7 +6843,7 @@ package body Parse is
Expect (Tok_Semi_Colon);
return Res;
else
- return Parse_Conditional_Signal_Assignment
+ return Parse_Concurrent_Conditional_Signal_Assignment
(Parse_Simple_Expression (Target));
end if;
end case;
@@ -6878,7 +7023,7 @@ package body Parse is
Id := Parse_Aggregate;
if Current_Token = Tok_Less_Equal then
-- This is a conditional signal assignment.
- Stmt := Parse_Conditional_Signal_Assignment (Id);
+ Stmt := Parse_Concurrent_Conditional_Signal_Assignment (Id);
else
Error_Msg_Parse ("'<=' expected after aggregate");
Eat_Tokens_Until_Semi_Colon;