aboutsummaryrefslogtreecommitdiffstats
path: root/parse.adb
diff options
context:
space:
mode:
Diffstat (limited to 'parse.adb')
-rw-r--r--parse.adb509
1 files changed, 492 insertions, 17 deletions
diff --git a/parse.adb b/parse.adb
index dc1fad6f5..6410edd3b 100644
--- a/parse.adb
+++ b/parse.adb
@@ -51,7 +51,8 @@ package body Parse is
-- current_token must be valid.
-- Leaves a token.
- function Parse_Simple_Expression return Iir_Expression;
+ 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;
@@ -1939,6 +1940,24 @@ package body Parse is
return Def;
end Parse_Element_Constraint;
+ -- precond : tolerance
+ -- postcond: next token
+ --
+ -- [ LRM93 4.2 ]
+ -- tolerance_aspect ::= TOLERANCE string_expression
+ function Parse_Tolerance_Aspect_Opt return Iir
+ is
+ begin
+ if AMS_Vhdl
+ and then Current_Token = Tok_Tolerance
+ then
+ Scan.Scan;
+ return Parse_Expression;
+ else
+ return Null_Iir;
+ end if;
+ end Parse_Tolerance_Aspect_Opt;
+
-- precond : identifier or '('
-- postcond: next token
--
@@ -1960,6 +1979,7 @@ package body Parse is
Type_Mark : Iir;
Def: Iir;
Resolution_Function: Iir;
+ Tolerance : Iir;
begin
-- FIXME: location.
Resolution_Function := Null_Iir;
@@ -1996,6 +2016,7 @@ package body Parse is
Def := Parse_Element_Constraint;
Set_Type_Mark (Def, Type_Mark);
Set_Resolution_Function (Def, Resolution_Function);
+ Set_Tolerance (Def, Parse_Tolerance_Aspect_Opt);
when Tok_Range =>
-- range_constraint.
@@ -2004,13 +2025,18 @@ package body Parse is
Set_Type_Mark (Def, Type_Mark);
Set_Range_Constraint (Def, Parse_Range_Constraint);
Set_Resolution_Function (Def, Resolution_Function);
+ Set_Tolerance (Def, Parse_Tolerance_Aspect_Opt);
when others =>
- if Resolution_Function /= Null_Iir then
+ Tolerance := Parse_Tolerance_Aspect_Opt;
+ if Resolution_Function /= Null_Iir
+ or else Tolerance /= Null_Iir
+ then
Def := Create_Iir (Iir_Kind_Subtype_Definition);
Location_Copy (Def, Type_Mark);
Set_Type_Mark (Def, Type_Mark);
Set_Resolution_Function (Def, Resolution_Function);
+ Set_Tolerance (Def, Tolerance);
else
Def := Type_Mark;
end if;
@@ -2042,6 +2068,417 @@ package body Parse is
return Decl;
end Parse_Subtype_Declaration;
+ -- precond : NATURE
+ -- postcond: a token
+ --
+ -- [ §4.8 ]
+ -- nature_definition ::= scalar_nature_definition
+ -- | composite_nature_definition
+ --
+ -- [ §3.5.1 ]
+ -- scalar_nature_definition ::= type_mark ACROSS
+ -- type_mark THROUGH
+ -- identifier REFERENCE
+ --
+ -- [ §3.5.2 ]
+ -- composite_nature_definition ::= array_nature_definition
+ -- | record_nature_definition
+ function Parse_Nature_Declaration return Iir
+ is
+ Def : Iir;
+ Ref : Iir;
+ Loc : Location_Type;
+ Ident : Name_Id;
+ Decl : Iir;
+ begin
+ -- The current token must be type.
+ if Current_Token /= Tok_Nature then
+ raise Program_Error;
+ end if;
+
+ -- Get the identifier
+ Scan_Expect (Tok_Identifier,
+ "an identifier is expected after 'nature'");
+ Loc := Get_Token_Location;
+ Ident := Current_Identifier;
+
+ Scan.Scan;
+
+ if Current_Token /= Tok_Is then
+ Error_Msg_Parse ("'is' expected here");
+ -- Act as if IS token was forgotten.
+ else
+ -- Eat IS token.
+ Scan.Scan;
+ end if;
+
+ case Current_Token is
+ when Tok_Array =>
+ -- TODO
+ Error_Msg_Parse ("array nature definition not supported");
+ Def := Null_Iir;
+ Eat_Tokens_Until_Semi_Colon;
+ when Tok_Record =>
+ -- TODO
+ Error_Msg_Parse ("record nature definition not supported");
+ Def := Null_Iir;
+ Eat_Tokens_Until_Semi_Colon;
+ when Tok_Identifier =>
+ Def := Create_Iir (Iir_Kind_Scalar_Nature_Definition);
+ Set_Location (Def, Loc);
+ Set_Across_Type (Def, Parse_Type_Mark);
+ if Current_Token = Tok_Across then
+ Scan.Scan;
+ else
+ Expect (Tok_Across, "'across' expected after type mark");
+ end if;
+ Set_Through_Type (Def, Parse_Type_Mark);
+ if Current_Token = Tok_Through then
+ Scan.Scan;
+ else
+ Expect (Tok_Across, "'through' expected after type mark");
+ end if;
+ if Current_Token = Tok_Identifier then
+ Ref := Create_Iir (Iir_Kind_Terminal_Declaration);
+ Set_Identifier (Ref, Current_Identifier);
+ Set_Location (Ref);
+ Set_Reference (Def, Ref);
+ Scan.Scan;
+ if Current_Token = Tok_Reference then
+ Scan.Scan;
+ else
+ Expect (Tok_Reference, "'reference' expected");
+ Eat_Tokens_Until_Semi_Colon;
+ end if;
+ else
+ Error_Msg_Parse ("reference identifier expected");
+ Eat_Tokens_Until_Semi_Colon;
+ end if;
+ when others =>
+ Error_Msg_Parse ("nature definition expected here");
+ Eat_Tokens_Until_Semi_Colon;
+ end case;
+
+ Decl := Create_Iir (Iir_Kind_Nature_Declaration);
+ Set_Nature (Decl, Def);
+ Set_Identifier (Decl, Ident);
+ Set_Location (Decl, Loc);
+
+ -- ';' is expected after end of type declaration
+ Expect (Tok_Semi_Colon);
+ Invalidate_Current_Token;
+ return Decl;
+ end Parse_Nature_Declaration;
+
+ -- precond : identifier
+ -- postcond: next token
+ --
+ -- LRM 4.8 Nature declaration
+ --
+ -- subnature_indication ::=
+ -- nature_mark [ index_constraint ]
+ -- [ TOLERANCE string_expression ACROSS string_expression THROUGH ]
+ --
+ -- nature_mark ::=
+ -- nature_name | subnature_name
+ function Parse_Subnature_Indication return Iir is
+ Nature_Mark : Iir;
+ begin
+ if Current_Token /= Tok_Identifier then
+ Error_Msg_Parse ("nature mark expected in a subnature indication");
+ raise Parse_Error;
+ end if;
+ Nature_Mark := Parse_Name (Allow_Indexes => False);
+
+ if Current_Token = Tok_Left_Paren then
+ -- TODO
+ Error_Msg_Parse
+ ("index constraint not supported for subnature indication");
+ raise Parse_Error;
+ end if;
+
+ if Current_Token = Tok_Tolerance then
+ Error_Msg_Parse
+ ("tolerance not supported for subnature indication");
+ raise Parse_Error;
+ end if;
+ return Nature_Mark;
+ end Parse_Subnature_Indication;
+
+ -- precond : TERMINAL
+ -- postcond: ;
+ --
+ -- [ 4.3.1.5 Terminal declarations ]
+ -- terminal_declaration ::=
+ -- TERMINAL identifier_list : subnature_indication
+ function Parse_Terminal_Declaration (Parent : Iir) return Iir
+ is
+ -- First and last element of the chain to be returned.
+ First, Last : Iir;
+ Terminal : Iir;
+ Subnature : Iir;
+ Proxy : Iir_Proxy;
+ begin
+ Sub_Chain_Init (First, Last);
+
+ loop
+ -- 'terminal' or "," was just scanned.
+ Terminal := Create_Iir (Iir_Kind_Terminal_Declaration);
+ Scan_Expect (Tok_Identifier);
+ Set_Identifier (Terminal, Current_Identifier);
+ Set_Location (Terminal);
+ Set_Parent (Terminal, Parent);
+
+ Sub_Chain_Append (First, Last, Terminal);
+
+ Scan.Scan;
+ exit when Current_Token = Tok_Colon;
+ if Current_Token /= Tok_Comma then
+ Error_Msg_Parse
+ ("',' or ':' is expected after "
+ & "identifier in terminal declaration");
+ raise Expect_Error;
+ end if;
+ end loop;
+
+ -- The colon was parsed.
+ Scan.Scan;
+ Subnature := Parse_Subnature_Indication;
+
+ Proxy := Null_Iir;
+ Terminal := First;
+ while Terminal /= Null_Iir loop
+ -- Type definitions are factorized. This is OK, but not done by
+ -- sem.
+ if Terminal = First then
+ Set_Nature (Terminal, Subnature);
+ else
+ -- FIXME: could avoid to create many proxies, by adding
+ -- a reference counter.
+ Proxy := Create_Iir (Iir_Kind_Proxy);
+ Set_Proxy (Proxy, First);
+ Set_Nature (Terminal, Proxy);
+ end if;
+ Terminal := Get_Chain (Terminal);
+ end loop;
+ Expect (Tok_Semi_Colon);
+ return First;
+ end Parse_Terminal_Declaration;
+
+ -- precond : QUANTITY
+ -- postcond: ;
+ --
+ -- [ 4.3.1.6 Quantity declarations ]
+ -- quantity_declaration ::=
+ -- free_quantity_declaration
+ -- | branch_quantity_declaration
+ -- | source_quantity_declaration
+ --
+ -- free_quantity_declaration ::=
+ -- QUANTITY identifier_list : subtype_indication [ := expression ] ;
+ --
+ -- branch_quantity_declaration ::=
+ -- QUANTITY [ across_aspect ] [ through_aspect ] terminal_aspect ;
+ --
+ -- source_quantity_declaration ::=
+ -- QUANTITY identifier_list : subtype_indication source_aspect ;
+ --
+ -- across_aspect ::=
+ -- identifier_list [ tolerance_aspect ] [ := expression ] ACROSS
+ --
+ -- through_aspect ::=
+ -- identifier_list [ tolerance_aspect ] [ := expression ] THROUGH
+ --
+ -- terminal_aspect ::=
+ -- plus_terminal_name [ TO minus_terminal_name ]
+ function Parse_Quantity_Declaration (Parent : Iir) return Iir
+ is
+ -- First and last element of the chain to be returned.
+ First, Last : Iir;
+ Object : Iir;
+ New_Object : Iir;
+ Tolerance : Iir;
+ Default_Value : Iir;
+ Kind : Iir_Kind;
+ Plus_Terminal : Iir;
+ Proxy : Iir;
+ First_Through : Iir;
+ begin
+ Sub_Chain_Init (First, Last);
+
+ -- Eat 'quantity'
+ Scan.Scan;
+
+ loop
+ -- Quantity or "," was just scanned. We assume a free quantity
+ -- declaration and will change to branch or source quantity if
+ -- necessary.
+ Object := Create_Iir (Iir_Kind_Free_Quantity_Declaration);
+ Expect (Tok_Identifier);
+ Set_Identifier (Object, Current_Identifier);
+ Set_Location (Object);
+ Set_Parent (Object, Parent);
+
+ Sub_Chain_Append (First, Last, Object);
+
+ -- Eat identifier
+ Scan.Scan;
+ exit when Current_Token /= Tok_Comma;
+
+ -- Eat ','
+ Scan.Scan;
+ end loop;
+
+ case Current_Token is
+ when Tok_Colon =>
+ -- Either a free quantity (or a source quantity)
+ -- TODO
+ raise Program_Error;
+ when Tok_Tolerance
+ | Tok_Assign
+ | Tok_Across
+ | Tok_Through =>
+ -- A branch quantity
+
+ -- Parse tolerance aspect
+ Tolerance := Parse_Tolerance_Aspect_Opt;
+
+ -- Parse default value
+ if Current_Token = Tok_Assign then
+ Scan.Scan;
+ Default_Value := Parse_Expression;
+ else
+ Default_Value := Null_Iir;
+ end if;
+
+ case Current_Token is
+ when Tok_Across =>
+ Kind := Iir_Kind_Across_Quantity_Declaration;
+ when Tok_Through =>
+ Kind := Iir_Kind_Through_Quantity_Declaration;
+ when others =>
+ Error_Msg_Parse ("'across' or 'through' expected here");
+ Eat_Tokens_Until_Semi_Colon;
+ raise Expect_Error;
+ end case;
+
+ -- Eat across/through
+ Scan.Scan;
+
+ -- Change declarations
+ Object := First;
+ Sub_Chain_Init (First, Last);
+ while Object /= Null_Iir loop
+ New_Object := Create_Iir (Kind);
+ Location_Copy (New_Object, Object);
+ Set_Identifier (New_Object, Get_Identifier (Object));
+ Set_Parent (New_Object, Parent);
+ Set_Tolerance (New_Object, Tolerance);
+ Set_Default_Value (New_Object, Default_Value);
+
+ Sub_Chain_Append (First, Last, New_Object);
+
+ if Object /= First then
+ Proxy := Create_Iir (Iir_Kind_Proxy);
+ Set_Proxy (Proxy, First);
+ Set_Plus_Terminal (New_Object, Proxy);
+ end if;
+ New_Object := Get_Chain (Object);
+ Free_Iir (Object);
+ Object := New_Object;
+ end loop;
+
+ -- Parse terminal (or first identifier of through declarations)
+ Plus_Terminal := Parse_Name;
+
+ case Current_Token is
+ when Tok_Comma
+ | Tok_Tolerance
+ | Tok_Assign
+ | Tok_Through
+ | Tok_Across =>
+ -- Through quantity declaration. Convert the Plus_Terminal
+ -- to a declaration.
+ Object := Create_Iir (Iir_Kind_Through_Quantity_Declaration);
+ New_Object := Object;
+ Location_Copy (Object, Plus_Terminal);
+ if Get_Kind (Plus_Terminal) /= Iir_Kind_Simple_Name then
+ Error_Msg_Parse
+ ("identifier for quantity declaration expected");
+ else
+ Set_Identifier (Object, Get_Identifier (Plus_Terminal));
+ end if;
+ Proxy := Create_Iir (Iir_Kind_Proxy);
+ Set_Proxy (Proxy, First);
+ Set_Plus_Terminal (Object, Proxy);
+ First_Through := Object;
+ Free_Iir (Plus_Terminal);
+
+ loop
+ Set_Parent (Object, Parent);
+ Sub_Chain_Append (First, Last, Object);
+ exit when Current_Token /= Tok_Comma;
+ Scan.Scan;
+
+ Object := Create_Iir
+ (Iir_Kind_Through_Quantity_Declaration);
+ Set_Location (Object);
+ if Current_Token /= Tok_Identifier then
+ Error_Msg_Parse
+ ("identifier for quantity declaration expected");
+ else
+ Set_Identifier (Object, Current_Identifier);
+ Scan.Scan;
+ end if;
+ Proxy := Create_Iir (Iir_Kind_Proxy);
+ Set_Proxy (Proxy, First_Through);
+ Set_Plus_Terminal (Object, Proxy);
+
+ end loop;
+
+ -- Parse tolerance aspect
+ Set_Tolerance (Object, Parse_Tolerance_Aspect_Opt);
+
+ -- Parse default value
+ if Current_Token = Tok_Assign then
+ Scan.Scan;
+ Set_Default_Value (Object, Parse_Expression);
+ end if;
+
+ -- Scan 'through'
+ if Current_Token = Tok_Through then
+ Scan.Scan;
+ elsif Current_Token = Tok_Across then
+ Error_Msg_Parse ("across quantity declaration must appear"
+ & " before though declaration");
+ Scan.Scan;
+ else
+ Error_Msg_Parse ("'through' expected");
+ end if;
+
+ -- Parse plus terminal
+ Plus_Terminal := Parse_Name;
+ when others =>
+ null;
+ end case;
+
+ Set_Plus_Terminal (First, Plus_Terminal);
+
+ -- Parse minus terminal (if present)
+ if Current_Token = Tok_To then
+ Scan.Scan;
+ Set_Minus_Terminal (First, Parse_Name);
+ end if;
+ when others =>
+ Error_Msg_Parse ("missign type or across/throught aspect "
+ & "in quantity declaration");
+ Eat_Tokens_Until_Semi_Colon;
+ raise Expect_Error;
+ end case;
+ Expect (Tok_Semi_Colon);
+ return First;
+ end Parse_Quantity_Declaration;
+
-- precond : token (CONSTANT, SIGNAL, VARIABLE, FILE)
-- postcond: ;
--
@@ -2762,6 +3199,12 @@ package body Parse is
end if;
when Tok_Subtype =>
Decl := Parse_Subtype_Declaration;
+ when Tok_Nature =>
+ Decl := Parse_Nature_Declaration;
+ when Tok_Terminal =>
+ Decl := Parse_Terminal_Declaration (Parent);
+ when Tok_Quantity =>
+ Decl := Parse_Quantity_Declaration (Parent);
when Tok_Signal =>
case Get_Kind (Parent) is
when Iir_Kind_Function_Body
@@ -3254,24 +3697,34 @@ package body Parse is
-- factor ::= primary [ ** primary ]
-- | ABS primary
-- | NOT primary
- function Parse_Factor return Iir_Expression is
+ function Parse_Factor (Primary : Iir := Null_Iir) return Iir_Expression is
Res, Tmp: Iir_Expression;
begin
case Current_Token is
when Tok_Abs =>
+ if Primary /= Null_Iir then
+ return Primary;
+ end if;
Scan.Scan;
Res := Create_Iir (Iir_Kind_Absolute_Operator);
Set_Location (Res);
Set_Operand (Res, Parse_Primary);
return Res;
when Tok_Not =>
+ if Primary /= Null_Iir then
+ return Primary;
+ end if;
Res := Create_Iir (Iir_Kind_Not_Operator);
Set_Location (Res);
Scan.Scan;
Set_Operand (Res, Parse_Primary);
return Res;
when others =>
- Tmp := Parse_Primary;
+ if Primary /= Null_Iir then
+ Tmp := Primary;
+ else
+ Tmp := Parse_Primary;
+ end if;
if Current_Token = Tok_Double_Star then
Res := Create_Iir (Iir_Kind_Exponentiation_Operator);
Set_Location (Res);
@@ -3293,10 +3746,10 @@ package body Parse is
--
-- [ §7.2 ]
-- multiplying_operator ::= * | / | MOD | REM
- function Parse_Term return Iir_Expression is
+ function Parse_Term (Primary : Iir) return Iir_Expression is
Res, Tmp: Iir_Expression;
begin
- Res := Parse_Factor;
+ Res := Parse_Factor (Primary);
while Current_Token in Token_Multiplying_Operator_Type loop
case Current_Token is
when Tok_Star =>
@@ -3330,10 +3783,14 @@ package body Parse is
--
-- [ §7.2 ]
-- adding_operator ::= + | - | &
- function Parse_Simple_Expression return Iir_Expression is
+ function Parse_Simple_Expression (Primary : Iir := Null_Iir)
+ return Iir_Expression
+ is
Res, Tmp: Iir_Expression;
begin
- if Current_Token in Token_Sign_Type then
+ 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);
@@ -3344,9 +3801,9 @@ package body Parse is
end case;
Set_Location (Res);
Scan.Scan;
- Set_Operand (Res, Parse_Term);
+ Set_Operand (Res, Parse_Term (Null_Iir));
else
- Res := Parse_Term;
+ Res := Parse_Term (Primary);
end if;
while Current_Token in Token_Adding_Operator_Type loop
case Current_Token is
@@ -3362,7 +3819,7 @@ package body Parse is
Set_Location (Tmp);
Scan.Scan;
Set_Left (Tmp, Res);
- Set_Right (Tmp, Parse_Term);
+ Set_Right (Tmp, Parse_Term (Null_Iir));
Res := Tmp;
end loop;
return Res;
@@ -3984,12 +4441,10 @@ package body Parse is
when Iir_Kind_Simple_Name
| Iir_Kind_Selected_Name =>
Set_Implementation (Call, Name);
- when Iir_Kind_Attribute_Name => -- Support issue 3060
- Error_Msg_Parse ("Attribute cannot be applied to procedure call");
+ when Iir_Kind_Attribute_Name =>
+ Error_Msg_Parse ("attribute cannot be used as procedure call");
when others =>
- -- Support issue 2686 : no testcase, but improve the error message
- Error_Kind("parenthesis_name_to_procedure_call", Name);
- -- raise Internal_Error;
+ Error_Kind ("parenthesis_name_to_procedure_call", Name);
end case;
return Res;
end Parenthesis_Name_To_Procedure_Call;
@@ -5024,6 +5479,7 @@ package body Parse is
-- | [ label : ] [ POSTPONED ] selected_signal_assignment
function Parse_Concurrent_Assignment (Target : Iir) return Iir
is
+ Res : Iir;
begin
case Current_Token is
when Tok_Less_Equal
@@ -5038,9 +5494,28 @@ package body Parse is
Expect (Tok_Semi_Colon);
return Parenthesis_Name_To_Procedure_Call
(Target, Iir_Kind_Concurrent_Procedure_Call_Statement);
- when others =>
+ when Tok_Generic | Tok_Port =>
-- or a component instantiation.
return Parse_Component_Instantiation (Target);
+ when others =>
+ -- 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));
+ if Current_Token /= Tok_Equal_Equal then
+ Error_Msg_Parse ("'==' expected after expression");
+ else
+ Set_Location (Res);
+ Scan.Scan;
+ end if;
+ Set_Simultaneous_Right (Res, Parse_Simple_Expression);
+ Set_Tolerance (Res, Parse_Tolerance_Aspect_Opt);
+ Expect (Tok_Semi_Colon);
+ return Res;
+ else
+ return Parse_Conditional_Signal_Assignment
+ (Parse_Simple_Expression (Target));
+ end if;
end case;
end Parse_Concurrent_Assignment;