diff options
author | Tristan Gingold <tgingold@free.fr> | 2018-12-05 20:03:14 +0100 |
---|---|---|
committer | Tristan Gingold <tgingold@free.fr> | 2018-12-05 20:03:14 +0100 |
commit | 962db30624215804452afa70ce2d1d32e497cc02 (patch) | |
tree | aca3a71626ef149937e3438f3c1dbd7e55a2fd4b | |
parent | 457d8d9a1364e6d3d1506a9a25d6aa5c621b210d (diff) | |
download | ghdl-962db30624215804452afa70ce2d1d32e497cc02.tar.gz ghdl-962db30624215804452afa70ce2d1d32e497cc02.tar.bz2 ghdl-962db30624215804452afa70ce2d1d32e497cc02.zip |
parse: refactoring to improve error messages.
-rw-r--r-- | src/vhdl/parse.adb | 497 | ||||
-rw-r--r-- | src/vhdl/scanner.adb | 47 | ||||
-rw-r--r-- | src/vhdl/scanner.ads | 5 |
3 files changed, 347 insertions, 202 deletions
diff --git a/src/vhdl/parse.adb b/src/vhdl/parse.adb index ea3181b83..fbed818ea 100644 --- a/src/vhdl/parse.adb +++ b/src/vhdl/parse.adb @@ -97,10 +97,12 @@ package body Parse is Report_Msg (Msgid_Error, Errorout.Parse, No_Location, Msg, Args, Cont); end Error_Msg_Parse; - procedure Error_Msg_Parse - (Loc : Location_Type; Msg: String; Args : Earg_Arr := No_Eargs) is + procedure Error_Msg_Parse (Loc : Location_Type; + Msg: String; + Args : Earg_Arr := No_Eargs; + Cont : Boolean := False) is begin - Report_Msg (Msgid_Error, Errorout.Parse, Loc, Msg, Args); + Report_Msg (Msgid_Error, Errorout.Parse, Loc, Msg, Args, Cont); end Error_Msg_Parse; procedure Unexpected (Where: String) is @@ -108,17 +110,29 @@ package body Parse is Error_Msg_Parse ("unexpected token %t in a " & Where, +Current_Token); end Unexpected; - procedure Expect_Error (Token: Token_Type; Msg: String) is + procedure Expect_Error (Token: Token_Type; Msg: String) + is + Loc : Location_Type; begin + case Token is + when Tok_Semi_Colon + | Tok_Right_Paren + | Tok_Comma => + Loc := Get_Prev_Location; + when others => + Loc := Get_Token_Location; + end case; + if Msg'Length > 0 then - Error_Msg_Parse (Msg, Args => No_Eargs, Cont => True); - Error_Msg_Parse ("(found: %t)", +Current_Token); + Error_Msg_Parse (Loc, Msg, Args => No_Eargs, Cont => True); + Error_Msg_Parse (Loc, "(found: %t)", (1 => +Current_Token)); elsif Current_Token = Tok_Identifier then Error_Msg_Parse - ("%t is expected instead of %i", (+Token, +Current_Identifier)); + (Loc, "%t is expected instead of %i", + (+Token, +Current_Identifier)); else Error_Msg_Parse - ("%t is expected instead of %t", (+Token, + Current_Token)); + (Loc, "%t is expected instead of %t", (+Token, + Current_Token)); end if; end Expect_Error; @@ -193,7 +207,6 @@ package body Parse is Scan; end if; Check_End_Name (Decl); - Expect (Tok_Semi_Colon); end if; end Check_End_Name; @@ -228,8 +241,10 @@ package body Parse is begin loop case Current_Token is - when Tok_Eof - | Tok_Semi_Colon => + when Tok_Eof => + exit; + when Tok_Semi_Colon => + Scan; exit; when Tok_End | Tok_Begin => @@ -241,25 +256,87 @@ package body Parse is | Tok_File | Tok_Alias | Tok_Type - | Tok_Subtype => + | Tok_Subtype + | Tok_Use + | Tok_Component + | Tok_Attribute + | Tok_Group + | Tok_For + | Tok_Disconnect + | Tok_Shared + | Tok_Impure + | Tok_Pure + | Tok_Function + | Tok_Procedure + | Tok_Package => -- Start of a new declaration exit; when others => + -- Eat. Scan; end case; end loop; end Resync_To_End_Of_Declaration; + procedure Error_Missing_Semi_Colon (Msg : String) is + begin + Error_Msg_Parse (Get_Prev_Location, "missing "";"" at end of " & Msg); + end Error_Missing_Semi_Colon; + -- Expect and scan ';' emit an error message using MSG if not present. procedure Scan_Semi_Colon (Msg : String) is begin if Current_Token /= Tok_Semi_Colon then - Error_Msg_Parse ("missing "";"" at end of " & Msg); + Error_Missing_Semi_Colon (Msg); else Scan; end if; end Scan_Semi_Colon; + procedure Scan_Semi_Colon_Declaration (Msg : String) is + begin + if Current_Token = Tok_Semi_Colon then + -- Skip ';'. + Scan; + else + Error_Missing_Semi_Colon (Msg); + + Resync_To_End_Of_Declaration; + end if; + end Scan_Semi_Colon_Declaration; + + procedure Scan_Semi_Colon_Unit (Msg : String) is + begin + if Current_Token = Tok_Semi_Colon then + -- ';' is not skipped. + null; + else + Error_Missing_Semi_Colon (Msg); + + -- Resync. + loop + case Current_Token is + when Tok_Eof => + exit; + when Tok_Semi_Colon => + -- ';' is not skipped. + exit; + when Tok_Library + | Tok_Use + | Tok_Architecture + | Tok_Entity + | Tok_Package + | Tok_Configuration + | Tok_Context => + -- Possible start of a new unit. + exit; + when others => + Scan; + end case; + end loop; + end if; + end Scan_Semi_Colon_Unit; + -- precond : next token -- postcond: next token. -- @@ -2082,10 +2159,12 @@ package body Parse is begin Loc := Get_Token_Location; - -- Skip 'array', scan '(' - Scan_Expect (Tok_Left_Paren); + -- Skip 'array'. Scan; + -- Skip '('. + Expect_Scan (Tok_Left_Paren); + First := True; Index_List := Create_Iir_List; @@ -2148,9 +2227,8 @@ package body Parse is end loop; -- Skip ')' and 'of' - Expect (Tok_Right_Paren); - Scan_Expect (Tok_Of); - Scan; + Expect_Scan (Tok_Right_Paren); + Expect_Scan (Tok_Of); Element_Subtype := Parse_Subtype_Indication; @@ -2199,20 +2277,22 @@ package body Parse is Set_Location (Res); -- Skip 'units' - Expect (Tok_Units); - Scan; + Expect_Scan (Tok_Units); -- Parse primary unit. - Expect (Tok_Identifier); Unit := Create_Iir (Iir_Kind_Unit_Declaration); Set_Location (Unit); Set_Parent (Unit, Parent); - Set_Identifier (Unit, Current_Identifier); + if Current_Token = Tok_Identifier then + Set_Identifier (Unit, Current_Identifier); - -- Skip identifier - Scan; + -- Skip identifier + Scan; + else + Expect (Tok_Identifier); + end if; - Scan_Semi_Colon ("primary unit"); + Scan_Semi_Colon ("primary physical unit"); Build_Init (Last); Append (Last, Res, Unit); @@ -2246,7 +2326,7 @@ package body Parse is end case; end if; Append (Last, Res, Unit); - Scan_Semi_Colon ("secondary unit"); + Scan_Semi_Colon ("secondary physical unit"); end loop; -- Skip 'end'. @@ -2301,15 +2381,18 @@ package body Parse is if First = Null_Iir then First := El; end if; - Expect (Tok_Identifier); - Set_Identifier (El, Current_Identifier); + if Current_Token = Tok_Identifier then + Set_Identifier (El, Current_Identifier); + -- Skip identifier + Scan; + else + Expect (Tok_Identifier); + end if; + Append_Element (El_List, El); Set_Element_Position (El, Pos); Pos := Pos + 1; - -- Skip identifier - Scan; - exit when Current_Token /= Tok_Comma; Set_Has_Identifier_List (El, True); @@ -2319,15 +2402,14 @@ package body Parse is end loop; -- Scan ':'. - Expect (Tok_Colon); - Scan; + Expect_Scan (Tok_Colon); -- Parse element subtype indication. Subtype_Indication := Parse_Subtype_Indication; Set_Subtype_Indication (First, Subtype_Indication); First := Null_Iir; - Scan_Semi_Colon ("element declaration"); + Scan_Semi_Colon_Declaration ("element declaration"); exit when Current_Token /= Tok_Identifier; end loop; @@ -2380,8 +2462,9 @@ package body Parse is Res := Create_Iir (Iir_Kind_File_Type_Definition); Set_Location (Res); -- Accept token 'file'. - Scan_Expect (Tok_Of); Scan; + Expect_Scan (Tok_Of); + Type_Mark := Parse_Type_Mark (Check_Paren => True); if Type_Mark = Null_Iir or else Get_Kind (Type_Mark) not in Iir_Kinds_Denoting_Name @@ -2426,10 +2509,15 @@ package body Parse is Res : Iir; Decl : Iir; begin + -- Skip 'protected'. Scan; + if Current_Token = Tok_Body then Res := Create_Iir (Iir_Kind_Protected_Type_Body); + + -- Skip 'body'. Scan; + Decl := Res; else Decl := Create_Iir (Iir_Kind_Type_Declaration); @@ -2442,20 +2530,19 @@ package body Parse is Parse_Declarative_Part (Res); - Expect (Tok_End); -- Eat 'end'. - Scan; + Expect_Scan (Tok_End); + if Flags.Vhdl_Std >= Vhdl_00 then - Expect (Tok_Protected); + Expect_Scan (Tok_Protected); else -- Avoid weird message: 'protected' expected instead of 'protected'. - Expect (Tok_Identifier); + Expect_Scan (Tok_Identifier); end if; Set_End_Has_Reserved_Id (Res, True); if Get_Kind (Res) = Iir_Kind_Protected_Type_Body then - Scan_Expect (Tok_Body); + Expect_Scan (Tok_Body); end if; - Scan; Check_End_Name (Ident, Res); return Decl; end Parse_Protected_Type_Definition; @@ -2497,14 +2584,21 @@ package body Parse is pragma Assert (Current_Token = Tok_Type); Start_Loc := Get_Token_Location; + -- Skip 'type'. + Scan; + -- Get the identifier - Scan_Expect (Tok_Identifier, - "an identifier is expected after 'type' keyword"); Loc := Get_Token_Location; - Ident := Current_Identifier; + if Current_Token = Tok_Identifier then + Ident := Current_Identifier; + + -- Skip identifier. + Scan; + else + Expect (Tok_Identifier, "identifier is expected after 'type'"); + Ident := Null_Identifier; + end if; - -- Skip identifier. - Scan; if Current_Token = Tok_Semi_Colon then -- If there is a ';', this is an incomplete type declaration. @@ -2594,7 +2688,6 @@ package body Parse is (1 => +Ident), Cont => True); Error_Msg_Parse ("(you should declare a subtype)"); Decl := Create_Iir (Iir_Kind_Type_Declaration); - Eat_Tokens_Until_Semi_Colon; end if; when Tok_Protected => @@ -2604,11 +2697,7 @@ package body Parse is Decl := Parse_Protected_Type_Definition (Ident, Loc); when others => - Error_Msg_Parse - ("type definition starts with a keyword such as RANGE, ARRAY"); - Error_Msg_Parse - (" FILE, RECORD or '(' is expected here"); - Eat_Tokens_Until_Semi_Colon; + Error_Msg_Parse ("missing type definition after 'is'"); Decl := Create_Iir (Iir_Kind_Type_Declaration); end case; @@ -2630,7 +2719,7 @@ package body Parse is Set_Location (Decl, Loc); -- ';' is expected after end of type declaration - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("type declaration"); if Flag_Elocations then Create_Elocations (Decl); @@ -2934,8 +3023,8 @@ package body Parse is Def := Parse_Subtype_Indication; Set_Subtype_Indication (Decl, Def); - -- Skip 'end'. - Expect_Scan (Tok_Semi_Colon); + -- Skip ';'. + Scan_Semi_Colon_Declaration ("subtype decalaration"); if Flag_Elocations then Create_Elocations (Decl); @@ -3035,7 +3124,7 @@ package body Parse is Set_Location (Decl, Loc); -- ';' is expected after end of type declaration - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("nature declaration"); return Decl; end Parse_Nature_Declaration; @@ -3124,7 +3213,10 @@ package body Parse is end if; Terminal := Get_Chain (Terminal); end loop; - Expect_Scan (Tok_Semi_Colon); + + -- Skip ';'. + Scan_Semi_Colon_Declaration ("terminal declaration"); + return First; end Parse_Terminal_Declaration; @@ -3329,7 +3421,10 @@ package body Parse is Eat_Tokens_Until_Semi_Colon; return Null_Iir; end case; - Expect_Scan (Tok_Semi_Colon); + + -- Skip ';'. + Scan_Semi_Colon_Declaration ("quantity declaration"); + return First; end Parse_Quantity_Declaration; @@ -3402,17 +3497,37 @@ package body Parse is case Current_Token is when Tok_Signal => Kind := Iir_Kind_Signal_Declaration; + + -- Skip 'signal'. + Scan; + when Tok_Constant => Kind := Iir_Kind_Constant_Declaration; + + -- Skip 'constant'. + Scan; + when Tok_File => Kind := Iir_Kind_File_Declaration; + + -- Skip 'file'. + Scan; + when Tok_Variable => Kind := Iir_Kind_Variable_Declaration; Shared := False; + + -- Skip 'variable'. + Scan; + when Tok_Shared => Kind := Iir_Kind_Variable_Declaration; Shared := True; - Scan_Expect (Tok_Variable); + + -- Skip 'shared'. + Scan; + + Expect_Scan (Tok_Variable); when others => raise Internal_Error; end case; @@ -3424,9 +3539,6 @@ package body Parse is Set_Shared_Flag (Object, Shared); end if; - -- Eat class or ','. - Scan; - Set_Location (Object); if Current_Token = Tok_Identifier then @@ -3460,6 +3572,8 @@ package body Parse is Resync_To_End_Of_Declaration; return Object; end case; + else + Scan; end if; Set_Has_Identifier_List (Object, True); end loop; @@ -3558,7 +3672,7 @@ package body Parse is end loop; -- Skip ';'. - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("object declaration"); return First; end Parse_Object_Declaration; @@ -3610,7 +3724,7 @@ package body Parse is Check_End_Name (Tok_Component, Component); -- Skip ';'. - Scan; + Expect_Scan (Tok_Semi_Colon); return Component; end Parse_Component_Declaration; @@ -3720,7 +3834,7 @@ package body Parse is end if; -- Skip ';'. - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("alias declaration"); return Res; end Parse_Alias_Declaration; @@ -3746,7 +3860,7 @@ package body Parse is Set_Binding_Indication (Res, Parse_Binding_Indication); -- Skip ';'. - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("configuration specification"); return Res; end Parse_Configuration_Specification; @@ -3922,7 +4036,7 @@ package body Parse is Scan; Set_Type_Mark (Res, Parse_Type_Mark (Check_Paren => True)); - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("attribute declaration"); when Tok_Of => Res := Create_Iir (Iir_Kind_Attribute_Specification); @@ -3941,7 +4055,7 @@ package body Parse is Expect_Scan (Tok_Is); Set_Expression (Res, Parse_Expression); - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("attribute specification"); when others => Error_Msg_Parse ("':' or 'of' expected after identifier"); @@ -4023,7 +4137,8 @@ package body Parse is -- Skip ')' ';' Expect_Scan (Tok_Right_Paren); - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("group template"); + return Res; end; when Tok_Colon => @@ -4055,7 +4170,7 @@ package body Parse is -- Skip ')' ';'. Expect_Scan (Tok_Right_Paren); - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("group declaration"); Set_Group_Constituent_List (Res, List_To_Flist (List)); return Res; @@ -4136,7 +4251,7 @@ package body Parse is Set_Expression (Res, Parse_Expression); -- Skip ';'. - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("disconnection specification"); return Res; end Parse_Disconnection_Specification; @@ -4160,11 +4275,12 @@ package body Parse is Expect_Scan (Tok_Is); Set_Psl_Boolean (Res, Parse_Psl.Parse_Psl_Boolean); - Expect (Tok_Semi_Colon); Scanner.Flag_Scan_In_Comment := False; Scanner.Flag_Psl := False; + Expect_Scan (Tok_Semi_Colon); + return Res; end Parse_Psl_Default_Clock_Cont; @@ -4206,10 +4322,11 @@ package body Parse is -- Parse PSL declaration. Scanner.Flag_Psl := True; Decl := Parse_Psl.Parse_Psl_Declaration (Tok); - Expect (Tok_Semi_Colon); Scanner.Flag_Scan_In_Comment := False; Scanner.Flag_Psl := False; + Expect_Scan (Tok_Semi_Colon); + if Tok = Tok_Psl_Endpoint and then Parse_Psl.Is_Instantiated_Declaration (Decl) then @@ -4734,11 +4851,6 @@ package body Parse is Error_Kind ("parse_declarative_part", Parent); end case; Decl := Parse_Psl_Default_Clock; - - if Current_Token = Tok_Semi_Colon then - -- Skip ';' (scan without PSL keywords). - Scan; - end if; else Error_Msg_Parse ("object class keyword such as 'variable' is expected"); @@ -4825,7 +4937,7 @@ package body Parse is Scan; end if; Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("entity"); Set_Library_Unit (Unit, Res); @@ -5460,7 +5572,6 @@ package body Parse is when others => Unexpected ("primary"); - Scan; return Null_Iir; end case; end Parse_Primary; @@ -5938,7 +6049,7 @@ package body Parse is end Parse_Conditional_Waveforms; -- precond : '<=' (or ':=') - -- postcond: ';' + -- postcond: next token (after ';') -- -- [ LRM93 9.5.1 ] -- concurrent_conditional_signal_assignment ::= @@ -5992,12 +6103,13 @@ package body Parse is end if; Set_Location (Res, Loc); Set_Target (Res, Target); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon, "';' expected at end of signal assignment"); + return Res; end Parse_Concurrent_Conditional_Signal_Assignment; -- precond : WITH - -- postcond: ';' + -- postcond: next token -- -- [ LRM93 9.5.2 ] -- selected_signal_assignment ::= @@ -6019,21 +6131,22 @@ package body Parse is When_Loc : Location_Type; Pos : Int32; begin - Scan; -- accept 'with' token. + -- Skip 'with'. + Scan; + Res := Create_Iir (Iir_Kind_Concurrent_Selected_Signal_Assignment); Set_Location (Res); Set_Expression (Res, Parse_Expression); - Expect (Tok_Select, "'select' expected after expression"); - Scan; + Expect_Scan (Tok_Select, "'select' expected after expression"); + if Current_Token = Tok_Left_Paren then Target := Parse_Aggregate; else Target := Parse_Name (Allow_Indexes => True); end if; Set_Target (Res, Target); - Expect (Tok_Less_Equal); - Scan; + Expect_Scan (Tok_Less_Equal); Parse_Options (Res); @@ -6055,7 +6168,7 @@ package body Parse is Scan; end loop; - Expect (Tok_Semi_Colon, "';' expected at end of statement"); + Expect_Scan (Tok_Semi_Colon, "';' expected at end of signal assignment"); return Res; end Parse_Selected_Signal_Assignment; @@ -6099,20 +6212,33 @@ package body Parse is -- postcond: next token -- Note: this fill an sequential or a concurrent statement. -- + -- [ LRM93 9.4 ] + -- concurrent_assertion_statement ::= + -- [ label : ] [ POSTPONED ] assertion ; + -- -- [ LRM93 8.2 ] -- assertion ::= ASSERT condition -- [ REPORT expression ] [ SEVERITY expression ] procedure Parse_Assertion (Stmt: Iir) is begin Set_Location (Stmt); + + -- Skip 'assert'. Scan; + Set_Assertion_Condition (Stmt, Parse_Expression); + if Current_Token = Tok_Report then + -- Skip 'report'. Scan; + Set_Report_Expression (Stmt, Parse_Expression); end if; + if Current_Token = Tok_Severity then + -- Skip 'severity'. Scan; + Set_Severity_Expression (Stmt, Parse_Expression); if Current_Token = Tok_Report then -- Nice message in case of inversion. @@ -6138,10 +6264,16 @@ package body Parse is if Flags.Vhdl_Std = Vhdl_87 then Error_Msg_Parse ("report statement not allowed in vhdl87"); end if; + + -- Skip 'report'. Scan; + Set_Report_Expression (Res, Parse_Expression); + if Current_Token = Tok_Severity then + -- Skip 'severity'. Scan; + Set_Severity_Expression (Res, Parse_Expression); end if; return Res; @@ -6606,9 +6738,7 @@ package body Parse is Build_Init (Last_Assoc); Pos := 0; - while Current_Token /= Tok_End loop - exit when Current_Token = Tok_Eof; - Expect (Tok_When); + while Current_Token = Tok_When loop When_Loc := Get_Token_Location; -- Skip 'when'. @@ -6637,8 +6767,8 @@ package body Parse is end if; -- Skip 'end', 'case'. - Scan_Expect (Tok_Case); - Scan; + Expect_Scan (Tok_End); + Expect_Scan (Tok_Case); if Flags.Vhdl_Std >= Vhdl_93c then Check_End_Name (Stmt); @@ -6882,7 +7012,10 @@ package body Parse is when Tok_Return => Stmt := Create_Iir (Iir_Kind_Return_Statement); + + -- Skip return. Scan; + if Current_Token /= Tok_Semi_Colon then Set_Expression (Stmt, Parse_Expression); end if; @@ -6942,7 +7075,7 @@ package body Parse is Set_Location (Stmt, Loc); if Label /= Null_Identifier then if Flags.Vhdl_Std = Vhdl_87 then - Error_Msg_Sem + Error_Msg_Parse (+Stmt, "this statement can't have a label in vhdl 87"); else Set_Label (Stmt, Label); @@ -7050,13 +7183,17 @@ package body Parse is Set_Start_Location (Subprg, Start_Loc); end if; - if Current_Token = Tok_Semi_Colon then + if Current_Token /= Tok_Is then -- Skip ';'. - Scan; + Expect_Scan (Tok_Semi_Colon); return Subprg; end if; + -- Skip 'is'. + Is_Loc := Get_Token_Location; + Scan; + -- The body. Set_Has_Body (Subprg, True); if Kind = Iir_Kind_Function_Declaration then @@ -7070,25 +7207,18 @@ package body Parse is Set_Subprogram_Specification (Subprg_Body, Subprg); Set_Chain (Subprg, Subprg_Body); - -- Skip 'is'. - Is_Loc := Get_Token_Location; - Expect (Tok_Is); - Scan; - Parse_Declarative_Part (Subprg_Body); -- Skip 'begin'. Begin_Loc := Get_Token_Location; - Expect (Tok_Begin); - Scan; + Expect_Scan (Tok_Begin); Set_Sequential_Statement_Chain (Subprg_Body, Parse_Sequential_Statements (Subprg_Body)); -- Skip 'end'. End_Loc := Get_Token_Location; - Expect (Tok_End); - Scan; + Expect_Scan (Tok_End); if Flag_Elocations then Create_Elocations (Subprg_Body); @@ -7142,13 +7272,13 @@ package body Parse is when others => null; end case; - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon_Declaration ("subprogram body"); return Subprg; end Parse_Subprogram_Declaration; -- precond: PROCESS - -- postcond: null + -- postcond: next token -- -- [ LRM87 9.2 / LRM08 11.3 ] -- process_statement ::= @@ -7219,16 +7349,14 @@ package body Parse is Parse_Declarative_Part (Res); -- Skip 'begin'. - Expect (Tok_Begin); Begin_Loc := Get_Token_Location; - Scan; + Expect_Scan (Tok_Begin); Set_Sequential_Statement_Chain (Res, Parse_Sequential_Statements (Res)); -- Skip 'end'. - Expect (Tok_End); End_Loc := Get_Token_Location; - Scan; + Expect_Scan (Tok_End); if Current_Token = Tok_Postponed then if not Is_Postponed then @@ -7246,12 +7374,14 @@ package body Parse is if Current_Token = Tok_Semi_Colon then Error_Msg_Parse ("""end"" must be followed by ""process"""); - else - Expect (Tok_Process); + + -- Skip ';'. Scan; + else + Expect_Scan (Tok_Process); Set_End_Has_Reserved_Id (Res, True); Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon, "';' expected at end of process"); end if; if Flag_Elocations then @@ -7539,7 +7669,7 @@ package body Parse is end Parse_Instantiated_Unit; -- precond : next token - -- postcond: ';' + -- postcond: next token -- -- component_instantiation_statement ::= -- INSTANTIATION_label : @@ -7560,7 +7690,7 @@ package body Parse is if Current_Token = Tok_Port then Set_Port_Map_Aspect_Chain (Res, Parse_Port_Map_Aspect); end if; - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon); return Res; end Parse_Component_Instantiation; @@ -7636,11 +7766,11 @@ package body Parse is -- Eat '('. Scan; + Set_Guard_Expression (Guard, Parse_Expression); - Expect (Tok_Right_Paren, "a ')' is expected after guard expression"); -- Eat ')'. - Scan; + Expect_Scan (Tok_Right_Paren, "')' expected after guard expression"); end if; if Current_Token = Tok_Is then @@ -7672,6 +7802,8 @@ package body Parse is end if; Check_End_Name (Tok_Block, Res); + Expect_Scan (Tok_Semi_Colon); + return Res; end Parse_Block_Statement; @@ -7868,17 +8000,15 @@ package body Parse is Parse_Generate_Statement_Body (Res, Null_Identifier, Bod, End_Loc); Set_Generate_Statement_Body (Res, Bod); - Expect (Tok_Generate); - Set_End_Has_Reserved_Id (Res, True); - -- Skip 'generate' - Scan; + Expect_Scan (Tok_Generate); + Set_End_Has_Reserved_Id (Res, True); -- LRM93 9.7 -- If a label appears at the end of a generate statement, it must repeat -- the generate label. Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon); if Flag_Elocations then Create_Elocations (Res); @@ -8061,7 +8191,7 @@ package body Parse is -- If a label appears at the end of a generate statement, it must repeat -- the generate label. Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon); return Res; end Parse_If_Generate_Statement; @@ -8124,8 +8254,7 @@ package body Parse is Set_Location (Assoc, Loc); -- Eat '=>' - Expect (Tok_Double_Arrow); - Scan; + Expect_Scan (Tok_Double_Arrow); Parse_Generate_Statement_Body (Parent, Alt_Label, Bod, End_Loc); Set_Associated_Block (Assoc, Bod); @@ -8165,10 +8294,8 @@ package body Parse is Set_Expression (Res, Parse_Expression); - Expect (Tok_Generate); - -- Skip 'generate' - Scan; + Expect_Scan (Tok_Generate); if Current_Token = Tok_End then Error_Msg_Parse ("no generate alternative"); @@ -8192,35 +8319,21 @@ package body Parse is end loop; end loop; - Expect (Tok_Generate); - Set_End_Has_Reserved_Id (Res, True); - -- Skip 'generate' - Scan; + Expect_Scan (Tok_Generate); + Set_End_Has_Reserved_Id (Res, True); -- LRM93 9.7 -- If a label appears at the end of a generate statement, it must repeat -- the generate label. Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon); + return Res; end Parse_Case_Generate_Statement; -- precond : first token - -- postcond: END - -- - -- [ LRM93 9 ] - -- concurrent_statement ::= block_statement - -- | process_statement - -- | concurrent_procedure_call_statement - -- | concurrent_assertion_statement - -- | concurrent_signal_assignment_statement - -- | component_instantiation_statement - -- | generate_statement - -- - -- [ LRM93 9.4 ] - -- concurrent_assertion_statement ::= - -- [ label : ] [ POSTPONED ] assertion ; + -- postcond: next token -- -- [ LRM93 9.3 ] -- concurrent_procedure_call_statement ::= @@ -8244,9 +8357,13 @@ package body Parse is -- a procedure call or a component instantiation. -- Parse it as a procedure call, may be revert to a -- component instantiation during sem. - Expect (Tok_Semi_Colon); - return Parenthesis_Name_To_Procedure_Call + Res := Parenthesis_Name_To_Procedure_Call (Target, Iir_Kind_Concurrent_Procedure_Call_Statement); + + -- Skip ';'. + Scan; + + return Res; when Tok_Generic | Tok_Port => -- or a component instantiation. return Parse_Component_Instantiation (Target); @@ -8263,6 +8380,7 @@ package body Parse is Current_Token := Tok_Psl_Clock; Res := Parse_Psl_Default_Clock_Cont (Get_Location (Target)); + return Res; end if; @@ -8279,7 +8397,7 @@ package body Parse is end if; Set_Simultaneous_Right (Res, Parse_Expression (Prio_Simple)); Set_Tolerance (Res, Parse_Tolerance_Aspect_Opt); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon); return Res; else return Parse_Concurrent_Conditional_Signal_Assignment @@ -8291,6 +8409,9 @@ package body Parse is -- Parse end of PSL assert/cover statement. procedure Parse_Psl_Assert_Report_Severity (Stmt : Iir) is begin + -- No more PSL tokens after the property. + Scanner.Flag_Psl := False; + if Current_Token = Tok_Report then -- Skip 'report' Scan; @@ -8305,7 +8426,9 @@ package body Parse is Set_Severity_Expression (Stmt, Parse_Expression); end if; - Expect (Tok_Semi_Colon); + Scanner.Flag_Scan_In_Comment := False; + + Expect_Scan (Tok_Semi_Colon); end Parse_Psl_Assert_Report_Severity; function Parse_Psl_Assert_Statement return Iir @@ -8324,12 +8447,8 @@ package body Parse is Set_Psl_Property (Res, Parse_Psl.Parse_Psl_Property); - -- No more PSL tokens after the property. - Scanner.Flag_Psl := False; - Parse_Psl_Assert_Report_Severity (Res); - Scanner.Flag_Scan_In_Comment := False; return Res; end Parse_Psl_Assert_Statement; @@ -8344,15 +8463,23 @@ package body Parse is Set_Psl_Sequence (Res, Parse_Psl.Parse_Psl_Sequence (True)); - -- No more PSL tokens after the property. - Scanner.Flag_Psl := False; - Parse_Psl_Assert_Report_Severity (Res); - Scanner.Flag_Scan_In_Comment := False; return Res; end Parse_Psl_Cover_Statement; + -- precond : first token + -- postcond: next token (end/else/when...) + -- + -- [ LRM93 9 ] + -- concurrent_statement ::= block_statement + -- | process_statement + -- | concurrent_procedure_call_statement + -- | concurrent_assertion_statement + -- | concurrent_signal_assignment_statement + -- | component_instantiation_statement + -- | generate_statement + -- procedure Parse_Concurrent_Statements (Parent : Iir) is Last_Stmt : Iir; @@ -8461,7 +8588,7 @@ package body Parse is else Stmt := Create_Iir (Iir_Kind_Concurrent_Assertion_Statement); Parse_Assertion (Stmt); - Expect (Tok_Semi_Colon); + Expect_Scan (Tok_Semi_Colon); end if; when Tok_With => Stmt := Parse_Selected_Signal_Assignment; @@ -8512,6 +8639,9 @@ package body Parse is -- report: 'signal declarations are not allowed in conc stmt' Unexpected ("concurrent statement list"); Eat_Tokens_Until_Semi_Colon; + if Current_Token = Tok_Semi_Colon then + Scan; + end if; end case; << Has_Stmt >> null; @@ -8534,11 +8664,6 @@ package body Parse is end if; Last_Stmt := Stmt; end if; - - if Current_Token = Tok_Semi_Colon then - -- Skip ';'. - Scan; - end if; end loop; end Parse_Concurrent_Statements; @@ -8586,7 +8711,7 @@ package body Parse is end loop; -- Skip ';'. - Expect_Scan (Tok_Semi_Colon); + Scan_Semi_Colon ("library clause"); return First; end Parse_Library_Clause; @@ -8633,7 +8758,8 @@ package body Parse is Scan; end loop; - Expect_Scan (Tok_Semi_Colon, "';' expected at end of use clause"); + -- Skip ';'. + Scan_Semi_Colon ("use clause"); return First; end Parse_Use_Clause; @@ -8703,7 +8829,8 @@ package body Parse is Scan; end if; Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("architecture"); + Set_Library_Unit (Unit, Res); if Flag_Elocations then @@ -8922,9 +9049,9 @@ package body Parse is -- Eat ';'. Scan; end if; - Expect (Tok_End); - Scan_Expect (Tok_For); - Scan_Expect (Tok_Semi_Colon); + Expect_Scan (Tok_End); + Expect_Scan (Tok_For); + Expect (Tok_Semi_Colon); return Res; end Parse_Component_Configuration; @@ -8980,9 +9107,9 @@ package body Parse is Scan; end loop; end; - Expect (Tok_End); - Scan_Expect (Tok_For); - Scan_Expect (Tok_Semi_Colon); + Expect_Scan (Tok_End); + Expect_Scan (Tok_For); + Expect (Tok_Semi_Colon); return Res; end Parse_Block_Configuration_Suffix; @@ -9012,8 +9139,7 @@ package body Parse is El : Iir; begin Loc := Get_Token_Location; - Expect (Tok_For); - Scan; + Expect_Scan (Tok_For); -- ALL and OTHERS are tokens from an instantiation list. -- Thus, the rule is a component_configuration. @@ -9183,7 +9309,8 @@ package body Parse is -- If a simple name appears at the end of a configuration declaration, -- it must repeat the identifier of the configuration declaration. Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("configuration"); + Set_Library_Unit (Unit, Res); if Flag_Elocations then @@ -9260,7 +9387,7 @@ package body Parse is end if; Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("package declaration"); if Flag_Elocations then Create_Elocations (Res); @@ -9319,7 +9446,7 @@ package body Parse is end if; Check_End_Name (Res); - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("package body"); if Flag_Elocations then Create_Elocations (Res); @@ -9364,7 +9491,7 @@ package body Parse is Set_End_Location (Res, Get_Token_Location); end if; - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("package instantiation"); return Res; end Parse_Package_Instantiation_Declaration; @@ -9450,7 +9577,7 @@ package body Parse is -- It is an error if the context clause preceding a library -- unit that is a context declaration is not empty. if Get_Context_Items (Unit) /= Null_Iir then - Error_Msg_Sem + Error_Msg_Parse (+Get_Context_Items (Unit), "context declaration does not allow context " & "clauses before it"); @@ -9505,7 +9632,7 @@ package body Parse is end if; Check_End_Name (Decl); - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("context declaration"); if Flag_Elocations then Create_Elocations (Decl); @@ -9544,7 +9671,7 @@ package body Parse is Last := Ref; end loop; - Expect (Tok_Semi_Colon); + Scan_Semi_Colon_Unit ("context reference"); return First; end Parse_Context_Reference; diff --git a/src/vhdl/scanner.adb b/src/vhdl/scanner.adb index 868aa9182..c24706ec1 100644 --- a/src/vhdl/scanner.adb +++ b/src/vhdl/scanner.adb @@ -141,22 +141,25 @@ package body Scanner is -- it can be used to push/pop a lexical analysis, to restart the -- scanner from a context marking a previous point. type Scan_Context is record - Source: File_Buffer_Acc; - Source_File: Source_File_Entry; - Line_Number: Natural; - Line_Pos: Source_Ptr; - Pos: Source_Ptr; - Token_Pos: Source_Ptr; - File_Len: Source_Ptr; - Token: Token_Type; - Prev_Token: Token_Type; + Source : File_Buffer_Acc; + Source_File : Source_File_Entry; + Line_Number : Natural; + Line_Pos : Source_Ptr; + Prev_Pos : Source_Ptr; + Token_Pos : Source_Ptr; + Pos : Source_Ptr; + File_Len : Source_Ptr; + Token : Token_Type; + Prev_Token : Token_Type; + + -- Additional values for the current token. Bit_Str_Base : Character; Bit_Str_Sign : Character; Str_Id : String8_Id; Str_Len : Nat32; Identifier: Name_Id; - Int64: Iir_Int64; - Fp64: Iir_Fp64; + Int64 : Iir_Int64; + Fp64 : Iir_Fp64; end record; pragma Suppress_Initialization (Scan_Context); @@ -199,6 +202,7 @@ package body Scanner is Line_Number => 0, Line_Pos => 0, Pos => 0, + Prev_Pos => 0, Token_Pos => 0, File_Len => 0, Token => Tok_Invalid, @@ -295,6 +299,18 @@ package body Scanner is return Current_Context.Pos; end Get_Position; + function Get_Token_Location return Location_Type is + begin + return File_Pos_To_Location + (Current_Context.Source_File, Current_Context.Token_Pos); + end Get_Token_Location; + + function Get_Prev_Location return Location_Type is + begin + return File_Pos_To_Location + (Current_Context.Source_File, Current_Context.Prev_Pos); + end Get_Prev_Location; + procedure Set_File (Source_File : Source_File_Entry) is N_Source: File_Buffer_Acc; @@ -306,6 +322,7 @@ package body Scanner is Source_File => Source_File, Line_Number => 1, Line_Pos => 0, + Prev_Pos => N_Source'First, Pos => N_Source'First, Token_Pos => 0, -- should be invalid, File_Len => Get_File_Length (Source_File), @@ -1703,6 +1720,8 @@ package body Scanner is Current_Context.Prev_Token := Current_Token; end if; + Current_Context.Prev_Pos := Pos; + << Again >> null; -- Skip commonly used separators. @@ -2296,12 +2315,6 @@ package body Scanner is -- Not reachable: all case should use goto Again or return. end Scan; - function Get_Token_Location return Location_Type is - begin - return File_Pos_To_Location - (Current_Context.Source_File, Current_Context.Token_Pos); - end Get_Token_Location; - function Is_Whitespace (C : Character) return Boolean is begin if C = ' ' then diff --git a/src/vhdl/scanner.ads b/src/vhdl/scanner.ads index 3b50a9712..2fc3db7be 100644 --- a/src/vhdl/scanner.ads +++ b/src/vhdl/scanner.ads @@ -123,6 +123,11 @@ package Scanner is function Get_Token_Offset return Natural; function Get_Token_Position return Source_Ptr; + -- Return the initial location before the current token (ie before all + -- the blanks, comments and newlines have been skipped). Useful for the + -- location of a missing token. + function Get_Prev_Location return Location_Type; + -- Convert (canonicalize) an identifier stored in name_buffer/name_length. -- Upper case letters are converted into lower case. -- Lexical checks are performed. |