From edde255f8820aba17b688990a2929dce8c34e3a8 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 24 Jun 2023 12:22:32 +0200 Subject: [PATCH 01/31] Register completion provider --- vhdl_ls/src/vhdl_server.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index 5b05141c..b7bfec6f 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -14,10 +14,12 @@ use vhdl_lang::ast::{Designator, ObjectClass}; use crate::rpc_channel::SharedRpcChannel; use std::io; use std::path::{Path, PathBuf}; +use clap::builder::Str; use vhdl_lang::{ AnyEntKind, Concurrent, Config, Diagnostic, EntHierarchy, EntRef, Message, MessageHandler, Object, Overloaded, Project, Severity, Source, SrcPos, Type, }; +use vhdl_lang::ast::InterfacePackageGenericMapAspect::Default; #[derive(Default, Clone)] pub struct VHDLServerSettings { @@ -112,6 +114,7 @@ impl VHDLServer { let config = self.load_config(); self.project = Project::from_config(&config, &mut self.message_filter()); self.init_params = Some(init_params); + let trigger_chars: Vec = r"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.\".chars().map(|ch| ch.to_string()).collect(); let capabilities = ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Kind( @@ -128,6 +131,13 @@ impl VHDLServer { })), workspace_symbol_provider: Some(OneOf::Left(true)), document_symbol_provider: Some(OneOf::Left(true)), + completion_provider: Some(CompletionOptions { + resolve_provider: Some(false), + trigger_characters: Some(trigger_chars), + all_commit_characters: None, + work_done_progress_options: Default::default(), + completion_item: Default::default() + }), ..Default::default() }; From 9d836decd284bd229482769d8c74f4427d91e24b Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 24 Jun 2023 12:24:18 +0200 Subject: [PATCH 02/31] clippy and fmt --- vhdl_ls/src/vhdl_server.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index b7bfec6f..de39468c 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -14,12 +14,10 @@ use vhdl_lang::ast::{Designator, ObjectClass}; use crate::rpc_channel::SharedRpcChannel; use std::io; use std::path::{Path, PathBuf}; -use clap::builder::Str; use vhdl_lang::{ AnyEntKind, Concurrent, Config, Diagnostic, EntHierarchy, EntRef, Message, MessageHandler, Object, Overloaded, Project, Severity, Source, SrcPos, Type, }; -use vhdl_lang::ast::InterfacePackageGenericMapAspect::Default; #[derive(Default, Clone)] pub struct VHDLServerSettings { @@ -114,7 +112,10 @@ impl VHDLServer { let config = self.load_config(); self.project = Project::from_config(&config, &mut self.message_filter()); self.init_params = Some(init_params); - let trigger_chars: Vec = r"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.\".chars().map(|ch| ch.to_string()).collect(); + let trigger_chars: Vec = r"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.\" + .chars() + .map(|ch| ch.to_string()) + .collect(); let capabilities = ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Kind( @@ -136,7 +137,7 @@ impl VHDLServer { trigger_characters: Some(trigger_chars), all_commit_characters: None, work_done_progress_options: Default::default(), - completion_item: Default::default() + completion_item: Default::default(), }), ..Default::default() }; From 2bbfdaaa5476d13bf70e28c4221c4a5fc332f009 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 24 Jun 2023 12:33:10 +0200 Subject: [PATCH 03/31] Add function to request completion --- vhdl_ls/src/stdio_server.rs | 8 ++++++++ vhdl_ls/src/vhdl_server.rs | 3 +++ 2 files changed, 11 insertions(+) diff --git a/vhdl_ls/src/stdio_server.rs b/vhdl_ls/src/stdio_server.rs index ce74ff1a..6865411a 100644 --- a/vhdl_ls/src/stdio_server.rs +++ b/vhdl_ls/src/stdio_server.rs @@ -203,6 +203,14 @@ impl ConnectionRpcChannel { } Err(request) => request, }; + let request = match extract::(request) { + Ok((id, params)) => { + let res = server.request_completion(¶ms); + self.send_response(lsp_server::Response::new_ok(id, res)); + return; + } + Err(request) => request, + }; debug!("Unhandled request: {:?}", request); self.send_response(lsp_server::Response::new_err( diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index de39468c..6e87bb88 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -263,6 +263,9 @@ impl VHDLServer { } } + pub fn request_completion(&mut self, params: &CompletionParams) { + } + fn client_supports_related_information(&self) -> bool { let try_fun = || { self.init_params From 3177bc83308b8a5632747c6e110776f2ca458952 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 24 Jun 2023 14:51:32 +0200 Subject: [PATCH 04/31] Add dummy implementation of request_completion function --- vhdl_ls/src/vhdl_server.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index 6e87bb88..44b9b762 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -263,7 +263,17 @@ impl VHDLServer { } } - pub fn request_completion(&mut self, params: &CompletionParams) { + pub fn request_completion(&mut self, params: &CompletionParams) -> CompletionList { + let binding = uri_to_file_name(¶ms.text_document_position.text_document.uri); + let file = binding.as_path(); + let Some(source) = self.project.get_source(file) else { + // Do not enable completions for files that are not part of the project + return CompletionList {..Default::default()}; + }; + return CompletionList { + items: vec![], + is_incomplete: true + }; } fn client_supports_related_information(&self) -> bool { From 93ec3f0f2fc26d55b3a9c205584f01cfd943ffbb Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 24 Jun 2023 17:33:12 +0200 Subject: [PATCH 05/31] Naive implementation --- vhdl_lang/src/analysis/root.rs | 6 ++++ vhdl_lang/src/ast/search.rs | 53 ++++++++++++++++++++++++++++++++++ vhdl_lang/src/project.rs | 4 +++ vhdl_ls/src/vhdl_server.rs | 28 +++++++++++++----- 4 files changed, 83 insertions(+), 8 deletions(-) diff --git a/vhdl_lang/src/analysis/root.rs b/vhdl_lang/src/analysis/root.rs index d5f9d29e..0b699c9c 100644 --- a/vhdl_lang/src/analysis/root.rs +++ b/vhdl_lang/src/analysis/root.rs @@ -431,6 +431,12 @@ impl DesignRoot { Vec::default() } + pub fn list_completion_options<'a>(&'a self, source: &Source, cursor: Position) -> Vec { + let mut searcher = SuggestionSearcher::new(self, cursor, source); + let _ = self.search(&mut searcher); + searcher.result + } + #[cfg(test)] pub fn search_reference_pos(&self, source: &Source, cursor: Position) -> Option { self.search_reference(source, cursor) diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index ddc32cf5..4ccc76f5 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -1782,6 +1782,59 @@ impl std::fmt::Display for FoundDeclaration<'_> { } } +pub struct SuggestionSearcher<'a> { + pub root: &'a DesignRoot, + pub cursor: Position, + pub source: &'a Source, + pub result: Vec, +} + +impl<'a> SuggestionSearcher<'a> { + pub fn new( + root: &'a DesignRoot, + cursor: Position, + source: &'a Source, + ) -> SuggestionSearcher<'a> { + SuggestionSearcher { + root, + cursor, + source, + result: vec![], + } + } + + fn cursor_inside_of(&self, pos: &SrcPos) -> bool { + pos.start() <= self.cursor && self.cursor <= pos.end() + } + + fn search_entity(&mut self, entity: EntityId, pos: &SrcPos) -> SearchState { + let ent = self.root.get_ent(entity); + self.result.push(format!("{:?}: {:?}", ent.describe(), pos.range)); + self.result.push(ent.describe()); + NotFinished + } +} + +impl<'a> Searcher for SuggestionSearcher<'a> { + fn search_pos_with_ref(&mut self, pos: &SrcPos, reference: &mut Reference) -> SearchState { + /* if !self.cursor_inside_of(pos) { + return Finished(NotFound); + } */ + match reference { + Some(eid) => self.search_entity(eid.clone(), pos), + None => Finished(NotFound), + } + } + + fn search_source(&mut self, source: &Source) -> SearchState { + if source == self.source { + NotFinished + } else { + Finished(NotFound) + } + } +} + #[derive(Default)] pub struct FindAllUnresolved { pub count: usize, diff --git a/vhdl_lang/src/project.rs b/vhdl_lang/src/project.rs index 0399bf31..437d6cc0 100644 --- a/vhdl_lang/src/project.rs +++ b/vhdl_lang/src/project.rs @@ -292,6 +292,10 @@ impl Project { pub fn files(&self) -> impl Iterator { self.files.values() } + + pub fn list_completion_options(&self, source: &Source, cursor: Position) -> Vec { + self.root.list_completion_options(source, cursor) + } } /// Multiply clonable value by cloning diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index 44b9b762..bc52c90f 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -112,10 +112,7 @@ impl VHDLServer { let config = self.load_config(); self.project = Project::from_config(&config, &mut self.message_filter()); self.init_params = Some(init_params); - let trigger_chars: Vec = r"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.\" - .chars() - .map(|ch| ch.to_string()) - .collect(); + let trigger_chars: Vec = r".".chars().map(|ch| ch.to_string()).collect(); let capabilities = ServerCapabilities { text_document_sync: Some(TextDocumentSyncCapability::Kind( @@ -263,6 +260,8 @@ impl VHDLServer { } } + /// Called when the client requests a completion. + /// This function looks in the source code to find suitable options and then returns them pub fn request_completion(&mut self, params: &CompletionParams) -> CompletionList { let binding = uri_to_file_name(¶ms.text_document_position.text_document.uri); let file = binding.as_path(); @@ -270,10 +269,23 @@ impl VHDLServer { // Do not enable completions for files that are not part of the project return CompletionList {..Default::default()}; }; - return CompletionList { - items: vec![], - is_incomplete: true - }; + let options = self + .project + .list_completion_options( + &source, + from_lsp_pos(params.text_document_position.position), + ) + .into_iter() + .map(|option| CompletionItem { + label: option, + ..Default::default() + }) + .collect(); + self.message(Message::log(format!("{:?}", options))); + CompletionList { + items: options, + is_incomplete: true, + } } fn client_supports_related_information(&self) -> bool { From dc238077479f1bbaecabd9e043abcf7a8a081b70 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 22 Jul 2023 20:59:56 +0200 Subject: [PATCH 06/31] Refactor: TokenStream is now a trait --- vhdl_lang/src/ast/search.rs | 7 +- vhdl_lang/src/syntax/alias_declaration.rs | 2 +- vhdl_lang/src/syntax/attributes.rs | 2 +- vhdl_lang/src/syntax/common.rs | 2 +- vhdl_lang/src/syntax/component_declaration.rs | 2 +- vhdl_lang/src/syntax/concurrent_statement.rs | 2 +- vhdl_lang/src/syntax/configuration.rs | 2 +- vhdl_lang/src/syntax/context.rs | 2 +- vhdl_lang/src/syntax/design_unit.rs | 2 +- vhdl_lang/src/syntax/expression.rs | 2 +- vhdl_lang/src/syntax/names.rs | 2 +- vhdl_lang/src/syntax/object_declaration.rs | 2 +- vhdl_lang/src/syntax/range.rs | 2 +- vhdl_lang/src/syntax/sequential_statement.rs | 2 +- vhdl_lang/src/syntax/subprogram.rs | 2 +- vhdl_lang/src/syntax/subtype_indication.rs | 2 +- vhdl_lang/src/syntax/tokens/tokenstream.rs | 265 +++++++++++------- vhdl_lang/src/syntax/type_declaration.rs | 2 +- vhdl_lang/src/syntax/waveform.rs | 2 +- vhdl_ls/src/vhdl_server.rs | 12 + 20 files changed, 199 insertions(+), 119 deletions(-) diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index a528eb47..8535580e 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -1804,7 +1804,8 @@ impl<'a> SuggestionSearcher<'a> { fn search_entity(&mut self, entity: EntityId, pos: &SrcPos) -> SearchState { let ent = self.root.get_ent(entity); - self.result.push(format!("{:?}: {:?}", ent.describe(), pos.range)); + self.result + .push(format!("{:?}: {:?}", ent.describe(), pos.range)); self.result.push(ent.describe()); NotFinished } @@ -1812,9 +1813,9 @@ impl<'a> SuggestionSearcher<'a> { impl<'a> Searcher for SuggestionSearcher<'a> { fn search_pos_with_ref(&mut self, pos: &SrcPos, reference: &mut Reference) -> SearchState { - /* if !self.cursor_inside_of(pos) { + if !self.cursor_inside_of(pos) { return Finished(NotFound); - } */ + } match reference { Some(eid) => self.search_entity(eid.clone(), pos), None => Finished(NotFound), diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index 156299da..a301007e 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::names::{parse_designator, parse_name}; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::{AliasDeclaration, WithDecl}; pub fn parse_alias_declaration(stream: &TokenStream) -> ParseResult { diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index e44a9542..065b366f 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_type_mark; use super::subprogram::parse_signature; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::{ Attribute, AttributeDeclaration, AttributeSpecification, Designator, EntityClass, EntityName, EntityTag, WithRef, diff --git a/vhdl_lang/src/syntax/common.rs b/vhdl_lang/src/syntax/common.rs index 4fa7a699..951869aa 100644 --- a/vhdl_lang/src/syntax/common.rs +++ b/vhdl_lang/src/syntax/common.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{Kind, TokenStream}; +use super::tokens::{Kind, TokenStream, _TokenStream}; use crate::ast::Ident; use crate::data::Diagnostic; use crate::data::DiagnosticHandler; diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index 8a85c663..f816ef4e 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -7,7 +7,7 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::interface_declaration::{parse_generic_interface_list, parse_port_interface_list}; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::WithDecl; use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; use crate::data::{Diagnostic, DiagnosticHandler}; diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index 6461b226..4d0c4987 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -19,7 +19,7 @@ use super::sequential_statement::{ parse_assert_statement, parse_labeled_sequential_statements, parse_selection, parse_signal_assignment_right_hand, parse_target, }; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index a794c04a..beb61416 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -9,7 +9,7 @@ use super::common::ParseResult; use super::concurrent_statement::parse_generic_and_port_map; use super::context::parse_use_clause; use super::names::{parse_name, parse_selected_name}; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index 69725e83..cdda8d2d 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -7,7 +7,7 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::names::parse_name; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 74b39ab5..6e612dde 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use super::common::check_end_identifier_mismatch; use super::common::ParseResult; diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index 6549873e..276d82de 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_name, parse_type_mark}; use super::subtype_indication::parse_subtype_constraint; -use super::tokens::{Kind, Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind, Kind::*, TokenStream, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index 0556afd1..c7957e75 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -9,7 +9,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index 17ab5d82..414bea55 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_identifier_list; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; /// LRM 6.4.2 Object Declarations use crate::ast::*; use crate::data::WithPos; diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index 376e5e17..fa5dab68 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -8,7 +8,7 @@ use super::common::parse_optional; use super::common::ParseResult; use super::expression::name_to_type_mark; use super::expression::parse_expression; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index f061c3a3..472fcec2 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -10,7 +10,7 @@ use super::expression::parse_aggregate; use super::expression::{parse_choices, parse_expression}; use super::names::parse_name; use super::range::parse_discrete_range; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 719cbf66..635390bb 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -9,7 +9,7 @@ use super::declarative_part::parse_declarative_part; use super::interface_declaration::parse_parameter_interface_list; use super::names::parse_type_mark; use super::sequential_statement::parse_labeled_sequential_statements; -use super::tokens::{kinds_error, Kind::*, TokenStream}; +use super::tokens::{kinds_error, DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index 93f12997..373ee0ad 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_selected_name, parse_type_mark, parse_type_mark_starting_with_name}; use super::range::{parse_discrete_range, parse_range}; -use super::tokens::{kinds_error, Kind::*, TokenStream}; +use super::tokens::{kinds_error, DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; /// LRM 6.3 Subtype declarations use crate::ast::*; use crate::data::{SrcPos, WithPos}; diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index adc41f2d..d1558ce3 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -18,78 +18,102 @@ pub struct TokenStream<'a> { tokens: Vec, } -impl<'a> TokenStream<'a> { - pub fn new( - mut tokenizer: Tokenizer<'a>, - diagnostics: &mut dyn DiagnosticHandler, - ) -> TokenStream<'a> { - let mut tokens = Vec::new(); - loop { - match tokenizer.pop() { - Ok(Some(token)) => tokens.push(token), - Ok(None) => break, - Err(err) => diagnostics.push(err), - } - } - TokenStream { - tokenizer, - idx: Cell::new(0), - tokens, - } - } +/// A TokenStream is an immutable collection of tokens with a mutable state. +/// The state points to a certain tokens. Methods exist to mutate that state and seek +/// to another token, e.g. to skip a token or go to a previous one. +pub trait _TokenStream { + /// Returns the current state. + /// `token_at(self.state())` must always return the current token, or `None` if the + /// state is invalid + fn state(&self) -> usize; + + /// Sets the current state. + /// An invalid state is OK but `token_at(invalid_state)` will return `None` + fn set_state(&self, state: usize); + + /// Returns the token at an given state + fn token_at(&self, state: usize) -> Option<&Token>; + + /// Returns the state of a token + fn state_of(&self, token: &Token) -> Option; + + // Default implementations for common operations - pub fn state(&self) -> usize { - self.get_idx() + /// Skips the current token, i.e. increments the current state + fn skip(&self) { + self.set_state(self.state() + 1) } - pub fn set_state(&self, state: usize) { - self.set_idx(state); + /// Returns the token at the current state + fn peek(&self) -> Option<&Token> { + self.token_at(self.state()) } - pub fn skip(&self) { - self.set_idx(self.get_idx() + 1) + /// Returns the token kind at the current state + fn peek_kind(&self) -> Option { + self.peek().map(|token| token.kind) } - fn get_idx(&self) -> usize { - self.idx.get() + /// returns the token at the previous state + fn last(&self) -> Option<&Token> { + let state = self.state().checked_sub(1)?; + self.token_at(state) } - fn set_idx(&self, idx: usize) { - self.idx.replace(idx); + /// Returns `true`, when the n'th next token is of kind `kind` + fn nth_kind_is(&self, offset: usize, kind: Kind) -> bool { + if let Some(token) = self.token_at(self.state() + offset) { + token.kind == kind + } else { + false + } } - pub fn peek(&self) -> Option<&Token> { - self.tokens.get(self.get_idx()) + /// returns true, when the next token is of a certain kind + fn next_kind_is(&self, kind: Kind) -> bool { + self.nth_kind_is(0, kind) } - pub fn last(&self) -> Option<&Token> { - let last_idx = self.get_idx().checked_sub(1)?; - self.tokens.get(last_idx) + /// returns true when all next tokens are of a certain kind + fn next_kinds_are(&self, kinds: &[Kind]) -> bool { + kinds + .iter() + .enumerate() + .all(|(idx, kind)| self.nth_kind_is(idx, *kind)) } - fn eof_error(&self) -> Diagnostic { - let end = self.tokenizer.source.contents().end(); - Diagnostic::error( - self.tokenizer.source.pos(end, end.next_char()), - "Unexpected EOF", - ) + /// advances (i.e. skips) if the next token is of a particular kind and returns the token + fn pop_if_kind(&self, kind: Kind) -> Option<&Token> { + if let Some(token) = self.peek() { + if token.kind == kind { + self.skip(); + return Some(token); + } + } + None } - fn idx_of(&self, token: &Token) -> Option { - let base = self.tokens.as_ptr() as usize; - let ptr = (token as *const Token) as usize; - let idx = ptr.checked_sub(base)? / std::mem::size_of::(); + /// advances (i.e. skips) if the next token is of a particular kind and returns true if successfully + fn skip_if_kind(&self, kind: Kind) -> bool { + self.pop_if_kind(kind).is_some() + } - if idx < self.tokens.len() { - Some(idx) - } else { - None - } + /// skips if the current token is an identifier and returns that identifier, if found + fn pop_optional_ident(&self) -> Option { + self.pop_if_kind(Identifier) + .map(|token| token.to_identifier_value().unwrap()) } + /// Returns the token right before the given token + /// + /// Example: + /// entity my_entity is + /// ^ ^ + /// | | token 'is' + /// token_before('is') fn token_before(&self, token: &Token) -> Option<&Token> { - let idx = self.idx_of(token)?; - self.tokens.get(idx.wrapping_sub(1)) + let state = self.state_of(token)?; + self.token_at(state.wrapping_sub(1)) } /// A position that aligns with the previous token @@ -99,7 +123,7 @@ impl<'a> TokenStream<'a> { /// ~ <- want semi colon error here /// signal /// ~~~~~~ <- not here - pub fn pos_before(&self, token: &Token) -> SrcPos { + fn pos_before(&self, token: &Token) -> SrcPos { if let Some(prev_token) = self.token_before(token) { let prev_pos = prev_token.pos.end(); @@ -110,84 +134,101 @@ impl<'a> TokenStream<'a> { token.pos.clone() } +} + +enum TokenizationException<'a> { + KindsError { pos: SrcPos, kinds: &'a [Kind] }, + EofError { expectations: Option<&'a [Kind]> }, +} + +pub trait DiagnosticTokenStream: _TokenStream { + fn create_diagnostic(&self, exception: TokenizationException) -> Diagnostic; - pub fn expect_kind(&self, kind: Kind) -> DiagnosticResult<&Token> { + fn expect_kind(&self, kind: Kind) -> DiagnosticResult<&Token> { if let Some(token) = self.peek() { if token.kind == kind { self.skip(); Ok(token) } else { - Err(kinds_error(self.pos_before(token), &[kind])) + self.create_diagnostic(TokenizationException::KindsError { + pos: self.pos_before(token), + kinds: &[kind], + }) } } else { - Err(self - .eof_error() - .when(format!("expecting {}", kinds_str(&[kind])))) + self.create_diagnostic(TokenizationException::EofError { + expectations: Some(&[kind]), + }) } } - pub fn peek_expect(&self) -> DiagnosticResult<&Token> { + fn peek_expect(&self) -> DiagnosticResult<&Token> { if let Some(token) = self.peek() { Ok(token) } else { - Err(self.eof_error()) + self.create_diagnostic(TokenizationException::EofError { expectations: None }) } } - pub fn peek_kind(&self) -> Option { - self.peek().map(|token| token.kind) - } - - pub fn next_kind_is(&self, kind: Kind) -> bool { - self.nth_kind_is(0, kind) + fn expect_ident(&self) -> DiagnosticResult { + expect_token!(self, token, Identifier => token.to_identifier_value()) } - pub fn nth_kind_is(&self, idx: usize, kind: Kind) -> bool { - if let Some(token) = self.tokens.get(self.get_idx() + idx) { - token.kind == kind - } else { - false + fn skip_until(&self, cond: fn(Kind) -> bool) -> DiagnosticResult<()> { + loop { + let token = self.peek_expect()?; + if cond(token.kind) { + return Ok(()); + } + self.skip(); } } +} - pub fn next_kinds_are(&self, kinds: &[Kind]) -> bool { - kinds - .iter() - .enumerate() - .all(|(idx, kind)| self.nth_kind_is(idx, *kind)) - } - - pub fn pop_if_kind(&self, kind: Kind) -> Option<&Token> { - if let Some(token) = self.peek() { - if token.kind == kind { - self.skip(); - return Some(token); +impl<'a> DiagnosticTokenStream for TokenStream<'a> { + + fn create_diagnostic(&self, exception: TokenizationException) -> Diagnostic { + match exception { + TokenizationException::KindsError { pos, kinds } => kinds_error(pos, kinds), + TokenizationException::EofError { expectations } => { + let diagnostic = self.eof_error(); + if let Some(kinds) = expectations { + diagnostic.when(format!("expecting {}", kinds_str(kinds))) + } + diagnostic } } - None - } - - pub fn skip_if_kind(&self, kind: Kind) -> bool { - self.pop_if_kind(kind).is_some() } +} - pub fn skip_until(&self, cond: fn(Kind) -> bool) -> DiagnosticResult<()> { +/// The token stream maintains a collection of tokens and a current state. +/// The state is an index into the vector of tokens and +impl<'a> TokenStream<'a> { + pub fn new( + mut tokenizer: Tokenizer<'a>, + diagnostics: &mut dyn DiagnosticHandler, + ) -> TokenStream<'a> { + let mut tokens = Vec::new(); loop { - let token = self.peek_expect()?; - if cond(token.kind) { - return Ok(()); + match tokenizer.pop() { + Ok(Some(token)) => tokens.push(token), + Ok(None) => break, + Err(err) => diagnostics.push(err), } - self.skip(); + } + TokenStream { + tokenizer, + idx: Cell::new(0), + tokens, } } - pub fn pop_optional_ident(&self) -> Option { - self.pop_if_kind(Identifier) - .map(|token| token.to_identifier_value().unwrap()) - } - - pub fn expect_ident(&self) -> DiagnosticResult { - expect_token!(self, token, Identifier => token.to_identifier_value()) + fn eof_error(&self) -> Diagnostic { + let end = self.tokenizer.source.contents().end(); + Diagnostic::error( + self.tokenizer.source.pos(end, end.next_char()), + "Unexpected EOF", + ) } /// Expect identifier or subtype/range keywords @@ -207,6 +248,32 @@ impl<'a> TokenStream<'a> { } } +impl<'a> _TokenStream for TokenStream<'a> { + fn state(&self) -> usize { + self.idx.get() + } + + fn set_state(&self, state: usize) { + self.idx.replace(state); + } + + fn token_at(&self, state: usize) -> Option<&Token> { + self.tokens.get(state) + } + + fn state_of(&self, token: &Token) -> Option { + let base = self.tokens.as_ptr() as usize; + let ptr = (token as *const Token) as usize; + let idx = ptr.checked_sub(base)? / std::mem::size_of::(); + + if idx < self.tokens.len() { + Some(idx) + } else { + None + } + } +} + pub trait Recover { fn or_recover_until( self, diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index 525146bc..b4027c5f 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -11,7 +11,7 @@ use super::names::parse_identifier_list; use super::range::{parse_array_index_constraint, parse_range}; use super::subprogram::parse_subprogram_declaration; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::ast::{AbstractLiteral, Range}; use crate::data::DiagnosticHandler; diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 4e059ab5..3e900ba9 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -8,7 +8,7 @@ use crate::ast::{DelayMechanism, Waveform, WaveformElement}; use super::common::{parse_optional, ParseResult}; use super::expression::parse_expression; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; /// LRM 10.5 Signal assignment statement pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult> { diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index bc52c90f..4e9839f9 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -265,10 +265,22 @@ impl VHDLServer { pub fn request_completion(&mut self, params: &CompletionParams) -> CompletionList { let binding = uri_to_file_name(¶ms.text_document_position.text_document.uri); let file = binding.as_path(); + // 1) get source position, and source file let Some(source) = self.project.get_source(file) else { // Do not enable completions for files that are not part of the project return CompletionList {..Default::default()}; }; + let source= from_lsp_pos(params.text_document_position.position); + // 2) get "context", e.g. in entity declaration, in function declaration, e.t.c + // (let's assume global context for now) + + // 3) go to last recognizable token before the cursor. For global state: + // - Any primary unit (e.g. entity declaration, package declaration, ...) + // => keyword `entity`, `package`, ... + // - Any secondary unit (e.g. package body, architecture) + // => keyword `architecture`, ... + + // 4) Run the parser until the point of the cursor. Then exit with possible completions let options = self .project .list_completion_options( From 32a01e3a7a24608e62801cb1bc21fc4cb5dad1da Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 22 Jul 2023 21:15:31 +0200 Subject: [PATCH 07/31] Merge DiagnosticTokenStream and TokenStream --- vhdl_lang/src/syntax/alias_declaration.rs | 2 +- vhdl_lang/src/syntax/attributes.rs | 2 +- vhdl_lang/src/syntax/component_declaration.rs | 2 +- vhdl_lang/src/syntax/concurrent_statement.rs | 2 +- vhdl_lang/src/syntax/configuration.rs | 2 +- vhdl_lang/src/syntax/context.rs | 2 +- vhdl_lang/src/syntax/design_unit.rs | 2 +- vhdl_lang/src/syntax/expression.rs | 2 +- vhdl_lang/src/syntax/names.rs | 2 +- vhdl_lang/src/syntax/object_declaration.rs | 2 +- vhdl_lang/src/syntax/range.rs | 2 +- vhdl_lang/src/syntax/sequential_statement.rs | 2 +- vhdl_lang/src/syntax/subprogram.rs | 2 +- vhdl_lang/src/syntax/subtype_indication.rs | 2 +- vhdl_lang/src/syntax/tokens/tokenstream.rs | 86 +++++++++---------- vhdl_lang/src/syntax/type_declaration.rs | 2 +- vhdl_lang/src/syntax/waveform.rs | 2 +- 17 files changed, 59 insertions(+), 59 deletions(-) diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index a301007e..74290440 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::names::{parse_designator, parse_name}; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast::{AliasDeclaration, WithDecl}; pub fn parse_alias_declaration(stream: &TokenStream) -> ParseResult { diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index 065b366f..814cae0c 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_type_mark; use super::subprogram::parse_signature; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast::{ Attribute, AttributeDeclaration, AttributeSpecification, Designator, EntityClass, EntityName, EntityTag, WithRef, diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index f816ef4e..19a0807e 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -7,7 +7,7 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::interface_declaration::{parse_generic_interface_list, parse_port_interface_list}; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast::WithDecl; use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; use crate::data::{Diagnostic, DiagnosticHandler}; diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index 4d0c4987..b626e148 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -19,7 +19,7 @@ use super::sequential_statement::{ parse_assert_statement, parse_labeled_sequential_statements, parse_selection, parse_signal_assignment_right_hand, parse_target, }; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index beb61416..a8331dfe 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -9,7 +9,7 @@ use super::common::ParseResult; use super::concurrent_statement::parse_generic_and_port_map; use super::context::parse_use_clause; use super::names::{parse_name, parse_selected_name}; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index cdda8d2d..9800c87e 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -7,7 +7,7 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::names::parse_name; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 6e612dde..89e63481 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use super::common::check_end_identifier_mismatch; use super::common::ParseResult; diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index 276d82de..9e84eaca 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_name, parse_type_mark}; use super::subtype_indication::parse_subtype_constraint; -use super::tokens::{DiagnosticTokenStream, Kind, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind, Kind::*, TokenStream, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index c7957e75..3edbc1c3 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -9,7 +9,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index 414bea55..0fd17ebb 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_identifier_list; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; /// LRM 6.4.2 Object Declarations use crate::ast::*; use crate::data::WithPos; diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index fa5dab68..f7892262 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -8,7 +8,7 @@ use super::common::parse_optional; use super::common::ParseResult; use super::expression::name_to_type_mark; use super::expression::parse_expression; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index 472fcec2..450aa134 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -10,7 +10,7 @@ use super::expression::parse_aggregate; use super::expression::{parse_choices, parse_expression}; use super::names::parse_name; use super::range::parse_discrete_range; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 635390bb..4752e5d6 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -9,7 +9,7 @@ use super::declarative_part::parse_declarative_part; use super::interface_declaration::parse_parameter_interface_list; use super::names::parse_type_mark; use super::sequential_statement::parse_labeled_sequential_statements; -use super::tokens::{kinds_error, DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{kinds_error, Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index 373ee0ad..8640ba85 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_selected_name, parse_type_mark, parse_type_mark_starting_with_name}; use super::range::{parse_discrete_range, parse_range}; -use super::tokens::{kinds_error, DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{kinds_error, Kind::*, TokenStream, _TokenStream}; /// LRM 6.3 Subtype declarations use crate::ast::*; use crate::data::{SrcPos, WithPos}; diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index d1558ce3..49df7413 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -60,7 +60,7 @@ pub trait _TokenStream { self.token_at(state) } - /// Returns `true`, when the n'th next token is of kind `kind` + /// Returns `true`, when the nth next token is of kind `kind` fn nth_kind_is(&self, offset: usize, kind: Kind) -> bool { if let Some(token) = self.token_at(self.state() + offset) { token.kind == kind @@ -134,15 +134,13 @@ pub trait _TokenStream { token.pos.clone() } -} -enum TokenizationException<'a> { - KindsError { pos: SrcPos, kinds: &'a [Kind] }, - EofError { expectations: Option<&'a [Kind]> }, -} + // Diagnostic stuff -pub trait DiagnosticTokenStream: _TokenStream { - fn create_diagnostic(&self, exception: TokenizationException) -> Diagnostic; + fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic; + + // TODO: this should not be an anonymous function (it's too specific) + fn expect_attribute_designator(&self) -> DiagnosticResult>; fn expect_kind(&self, kind: Kind) -> DiagnosticResult<&Token> { if let Some(token) = self.peek() { @@ -150,15 +148,15 @@ pub trait DiagnosticTokenStream: _TokenStream { self.skip(); Ok(token) } else { - self.create_diagnostic(TokenizationException::KindsError { + Err(self.handle_diagnostic(TokenizationException::KindsError { pos: self.pos_before(token), kinds: &[kind], - }) + })) } } else { - self.create_diagnostic(TokenizationException::EofError { + Err(self.handle_diagnostic(TokenizationException::EofError { expectations: Some(&[kind]), - }) + })) } } @@ -166,7 +164,7 @@ pub trait DiagnosticTokenStream: _TokenStream { if let Some(token) = self.peek() { Ok(token) } else { - self.create_diagnostic(TokenizationException::EofError { expectations: None }) + Err(self.handle_diagnostic(TokenizationException::EofError { expectations: None })) } } @@ -185,20 +183,9 @@ pub trait DiagnosticTokenStream: _TokenStream { } } -impl<'a> DiagnosticTokenStream for TokenStream<'a> { - - fn create_diagnostic(&self, exception: TokenizationException) -> Diagnostic { - match exception { - TokenizationException::KindsError { pos, kinds } => kinds_error(pos, kinds), - TokenizationException::EofError { expectations } => { - let diagnostic = self.eof_error(); - if let Some(kinds) = expectations { - diagnostic.when(format!("expecting {}", kinds_str(kinds))) - } - diagnostic - } - } - } +pub enum TokenizationException<'a> { + KindsError { pos: SrcPos, kinds: &'a [Kind] }, + EofError { expectations: Option<&'a [Kind]> }, } /// The token stream maintains a collection of tokens and a current state. @@ -230,22 +217,6 @@ impl<'a> TokenStream<'a> { "Unexpected EOF", ) } - - /// Expect identifier or subtype/range keywords - /// foo'subtype or foo'range - pub fn expect_attribute_designator(&self) -> DiagnosticResult> { - let des = expect_token!( - self, - token, - Identifier => { - let ident = token.to_identifier_value()?; - ident.map_into(|sym| self.tokenizer.attribute(sym)) - }, - Subtype => WithPos::new(AttributeDesignator::Type(TypeAttribute::Subtype), token.pos.clone()), - Range => WithPos::new(AttributeDesignator::Range(RangeAttribute::Range), token.pos.clone()) - ); - Ok(des) - } } impl<'a> _TokenStream for TokenStream<'a> { @@ -272,6 +243,35 @@ impl<'a> _TokenStream for TokenStream<'a> { None } } + + fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic { + match exception { + TokenizationException::KindsError { pos, kinds } => kinds_error(pos, kinds), + TokenizationException::EofError { expectations } => { + let mut diagnostic = self.eof_error(); + if let Some(kinds) = expectations { + diagnostic = diagnostic.when(format!("expecting {}", kinds_str(kinds))); + } + diagnostic + } + } + } + + /// Expect identifier or subtype/range keywords + /// foo'subtype or foo'range + fn expect_attribute_designator(&self) -> DiagnosticResult> { + let des = expect_token!( + self, + token, + Identifier => { + let ident = token.to_identifier_value()?; + ident.map_into(|sym| self.tokenizer.attribute(sym)) + }, + Subtype => WithPos::new(AttributeDesignator::Type(TypeAttribute::Subtype), token.pos.clone()), + Range => WithPos::new(AttributeDesignator::Range(RangeAttribute::Range), token.pos.clone()) + ); + Ok(des) + } } pub trait Recover { diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index b4027c5f..98aab086 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -11,7 +11,7 @@ use super::names::parse_identifier_list; use super::range::{parse_array_index_constraint, parse_range}; use super::subprogram::parse_subprogram_declaration; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; use crate::ast::*; use crate::ast::{AbstractLiteral, Range}; use crate::data::DiagnosticHandler; diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 3e900ba9..58ebcbfc 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -8,7 +8,7 @@ use crate::ast::{DelayMechanism, Waveform, WaveformElement}; use super::common::{parse_optional, ParseResult}; use super::expression::parse_expression; -use super::tokens::{DiagnosticTokenStream, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{Kind::*, TokenStream, _TokenStream}; /// LRM 10.5 Signal assignment statement pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult> { From c274a6b813153cedf451cfb6ba05cfb995a05f9c Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 22 Jul 2023 21:16:21 +0200 Subject: [PATCH 08/31] Rename TokenStream to BaseTokenStream --- vhdl_lang/src/syntax/alias_declaration.rs | 4 +- vhdl_lang/src/syntax/attributes.rs | 8 +-- vhdl_lang/src/syntax/common.rs | 6 +-- vhdl_lang/src/syntax/component_declaration.rs | 8 +-- vhdl_lang/src/syntax/concurrent_statement.rs | 36 ++++++------- vhdl_lang/src/syntax/configuration.rs | 24 ++++----- vhdl_lang/src/syntax/context.rs | 10 ++-- vhdl_lang/src/syntax/declarative_part.rs | 6 +-- vhdl_lang/src/syntax/design_unit.rs | 12 ++--- vhdl_lang/src/syntax/expression.rs | 22 ++++---- vhdl_lang/src/syntax/interface_declaration.rs | 32 ++++++------ vhdl_lang/src/syntax/names.rs | 32 ++++++------ vhdl_lang/src/syntax/object_declaration.rs | 16 +++--- vhdl_lang/src/syntax/parser.rs | 4 +- vhdl_lang/src/syntax/range.rs | 12 ++--- vhdl_lang/src/syntax/sequential_statement.rs | 50 +++++++++---------- vhdl_lang/src/syntax/subprogram.rs | 14 +++--- vhdl_lang/src/syntax/subtype_indication.rs | 14 +++--- vhdl_lang/src/syntax/test.rs | 43 ++++++++-------- vhdl_lang/src/syntax/tokens/tokenstream.rs | 24 ++++----- vhdl_lang/src/syntax/type_declaration.rs | 18 +++---- vhdl_lang/src/syntax/waveform.rs | 6 +-- 22 files changed, 203 insertions(+), 198 deletions(-) diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index 74290440..9cddac2c 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -8,10 +8,10 @@ use super::common::ParseResult; use super::names::{parse_designator, parse_name}; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::{AliasDeclaration, WithDecl}; -pub fn parse_alias_declaration(stream: &TokenStream) -> ParseResult { +pub fn parse_alias_declaration(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Alias)?; let designator = WithDecl::new(parse_designator(stream)?); let subtype_indication = { diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index 814cae0c..8d7f3394 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -8,13 +8,13 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_type_mark; use super::subprogram::parse_signature; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::{ Attribute, AttributeDeclaration, AttributeSpecification, Designator, EntityClass, EntityName, EntityTag, WithRef, }; -fn parse_entity_class(stream: &TokenStream) -> ParseResult { +fn parse_entity_class(stream: &BaseTokenStream) -> ParseResult { Ok(expect_token!(stream, token, Entity => EntityClass::Entity, Architecture => EntityClass::Architecture, @@ -31,7 +31,7 @@ fn parse_entity_class(stream: &TokenStream) -> ParseResult { )) } -pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult> { +pub fn parse_entity_name_list(stream: &BaseTokenStream) -> ParseResult> { Ok(expect_token!(stream, token, Identifier | StringLiteral => { let mut entity_name_list = Vec::new(); @@ -73,7 +73,7 @@ pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult ParseResult> { +pub fn parse_attribute(stream: &BaseTokenStream) -> ParseResult> { stream.expect_kind(Attribute)?; let ident = stream.expect_ident()?; Ok(expect_token!(stream, token, diff --git a/vhdl_lang/src/syntax/common.rs b/vhdl_lang/src/syntax/common.rs index 951869aa..8b182902 100644 --- a/vhdl_lang/src/syntax/common.rs +++ b/vhdl_lang/src/syntax/common.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{Kind, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind, _TokenStream}; use crate::ast::Ident; use crate::data::Diagnostic; use crate::data::DiagnosticHandler; @@ -13,12 +13,12 @@ use crate::SrcPos; /// Parse optional part followed by optional keyword pub fn parse_optional( - stream: &TokenStream, + stream: &BaseTokenStream, keyword: Kind, parse_fun: F, ) -> ParseResult> where - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&BaseTokenStream) -> ParseResult, { let optional = { if stream.skip_if_kind(keyword) { diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index 19a0807e..c71db640 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -7,13 +7,13 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::interface_declaration::{parse_generic_interface_list, parse_port_interface_list}; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::WithDecl; use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; use crate::data::{Diagnostic, DiagnosticHandler}; pub fn parse_optional_generic_list( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { let mut list = None; @@ -38,7 +38,7 @@ pub fn parse_optional_generic_list( } pub fn parse_optional_port_list( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { let mut list = None; @@ -72,7 +72,7 @@ pub fn parse_optional_port_list( } pub fn parse_component_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Component)?; diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index b626e148..ffe1bbd4 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -19,14 +19,14 @@ use super::sequential_statement::{ parse_assert_statement, parse_labeled_sequential_statements, parse_selection, parse_signal_assignment_right_hand, parse_target, }; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; /// LRM 11.2 Block statement pub fn parse_block_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -62,7 +62,7 @@ pub fn parse_block_statement( } fn parse_block_header( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut generic_clause = None; @@ -156,7 +156,7 @@ fn parse_block_header( /// LRM 11.3 Process statement pub fn parse_process_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, postponed: bool, diagnostics: &mut dyn DiagnosticHandler, @@ -252,7 +252,7 @@ fn to_procedure_call( /// Assume target and <= is parsed already fn parse_assignment_known_target( - stream: &TokenStream, + stream: &BaseTokenStream, target: WithPos, ) -> ParseResult { // @TODO postponed @@ -272,7 +272,7 @@ fn parse_assignment_known_target( } fn parse_assignment_or_procedure_call( - stream: &TokenStream, + stream: &BaseTokenStream, target: WithPos, ) -> ParseResult { expect_token!(stream, token, @@ -285,7 +285,7 @@ fn parse_assignment_or_procedure_call( } fn parse_selected_signal_assignment( - stream: &TokenStream, + stream: &BaseTokenStream, postponed: bool, ) -> ParseResult { stream.expect_kind(With)?; @@ -307,7 +307,7 @@ fn parse_selected_signal_assignment( } pub fn parse_concurrent_assert_statement( - stream: &TokenStream, + stream: &BaseTokenStream, postponed: bool, ) -> ParseResult { Ok(ConcurrentAssertStatement { @@ -318,7 +318,7 @@ pub fn parse_concurrent_assert_statement( #[allow(clippy::type_complexity)] pub fn parse_generic_and_port_map( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult<( Option>, Option>, @@ -344,7 +344,7 @@ pub fn parse_generic_and_port_map( } pub fn parse_instantiation_statement( - stream: &TokenStream, + stream: &BaseTokenStream, unit: InstantiatedUnit, ) -> ParseResult { let (generic_map, port_map) = parse_generic_and_port_map(stream)?; @@ -359,7 +359,7 @@ pub fn parse_instantiation_statement( } fn parse_optional_declarative_part( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { if is_declarative_part(stream, true)? { @@ -372,7 +372,7 @@ fn parse_optional_declarative_part( } fn parse_generate_body( - stream: &TokenStream, + stream: &BaseTokenStream, alternative_label: Option>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -409,7 +409,7 @@ fn parse_generate_body( /// 11.8 Generate statements fn parse_for_generate_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -434,7 +434,7 @@ fn parse_for_generate_statement( /// 11.8 Generate statements fn parse_if_generate_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -504,7 +504,7 @@ fn parse_if_generate_statement( /// 11.8 Generate statements fn parse_case_generate_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -554,7 +554,7 @@ fn parse_case_generate_statement( } pub fn parse_concurrent_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -640,7 +640,7 @@ pub fn parse_concurrent_statement( } pub fn parse_labeled_concurrent_statements( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut statements = Vec::new(); @@ -658,7 +658,7 @@ pub fn parse_labeled_concurrent_statements( } pub fn parse_labeled_concurrent_statement( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let start = stream.peek_expect()?; diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index a8331dfe..e8a8f58f 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -9,12 +9,12 @@ use super::common::ParseResult; use super::concurrent_statement::parse_generic_and_port_map; use super::context::parse_use_clause; use super::names::{parse_name, parse_selected_name}; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::*; use crate::data::*; /// LRM 7.3.2.2 -fn parse_entity_aspect(stream: &TokenStream) -> ParseResult { +fn parse_entity_aspect(stream: &BaseTokenStream) -> ParseResult { let entity_aspect = expect_token!( stream, token, @@ -39,7 +39,7 @@ fn parse_entity_aspect(stream: &TokenStream) -> ParseResult { fn parse_binding_indication_known_entity_aspect( entity_aspect: Option, - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult { let (generic_map, port_map) = parse_generic_and_port_map(stream)?; @@ -52,7 +52,7 @@ fn parse_binding_indication_known_entity_aspect( } /// LRM 7.3.2 -fn parse_binding_indication(stream: &TokenStream) -> ParseResult { +fn parse_binding_indication(stream: &BaseTokenStream) -> ParseResult { let entity_aspect = if stream.skip_if_kind(Use) { Some(parse_entity_aspect(stream)?) } else { @@ -62,7 +62,7 @@ fn parse_binding_indication(stream: &TokenStream) -> ParseResult ParseResult { @@ -116,7 +116,7 @@ enum ComponentSpecificationOrName { } fn parse_component_specification_or_name( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult { peek_token!( stream, token, @@ -177,7 +177,7 @@ fn parse_component_specification_or_name( } fn parse_configuration_item_known_keyword( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { match parse_component_specification_or_name(stream)? { @@ -193,7 +193,7 @@ fn parse_configuration_item_known_keyword( } fn parse_block_configuration_known_name( - stream: &TokenStream, + stream: &BaseTokenStream, name: WithPos, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -224,7 +224,7 @@ fn parse_block_configuration_known_name( } fn parse_block_configuration_known_keyword( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let name = parse_name(stream)?; @@ -232,7 +232,7 @@ fn parse_block_configuration_known_keyword( } fn parse_vunit_binding_indication_list_known_keyword( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult> { let mut indications = Vec::new(); loop { @@ -265,7 +265,7 @@ fn parse_vunit_binding_indication_list_known_keyword( /// LRM 3.4 Configuration declaration pub fn parse_configuration_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Configuration)?; @@ -311,7 +311,7 @@ pub fn parse_configuration_declaration( /// LRM 7.3 Configuration Specification pub fn parse_configuration_specification( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult { stream.expect_kind(For)?; match parse_component_specification_or_name(stream)? { diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index 9800c87e..28160b22 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -7,12 +7,12 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::names::parse_name; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::*; use crate::data::*; /// LRM 13. Design units and their analysis -pub fn parse_library_clause(stream: &TokenStream) -> ParseResult> { +pub fn parse_library_clause(stream: &BaseTokenStream) -> ParseResult> { let library_token = stream.expect_kind(Library)?; let mut name_list = Vec::with_capacity(1); loop { @@ -29,7 +29,7 @@ pub fn parse_library_clause(stream: &TokenStream) -> ParseResult ParseResult> { +pub fn parse_use_clause(stream: &BaseTokenStream) -> ParseResult> { let use_token = stream.expect_kind(Use)?; let mut name_list = Vec::with_capacity(1); @@ -52,7 +52,7 @@ pub enum DeclarationOrReference { Reference(WithPos), } -pub fn parse_context_reference(stream: &TokenStream) -> ParseResult> { +pub fn parse_context_reference(stream: &BaseTokenStream) -> ParseResult> { let context_token = stream.expect_kind(Context)?; let name = parse_name(stream)?; @@ -72,7 +72,7 @@ pub fn parse_context_reference(stream: &TokenStream) -> ParseResult ParseResult { let context_token = stream.expect_kind(Context)?; diff --git a/vhdl_lang/src/syntax/declarative_part.rs b/vhdl_lang/src/syntax/declarative_part.rs index d492e60f..a5601fef 100644 --- a/vhdl_lang/src/syntax/declarative_part.rs +++ b/vhdl_lang/src/syntax/declarative_part.rs @@ -18,7 +18,7 @@ use super::type_declaration::parse_type_declaration; use crate::ast::{ContextClause, Declaration, PackageInstantiation}; use crate::data::DiagnosticHandler; -pub fn parse_package_instantiation(stream: &TokenStream) -> ParseResult { +pub fn parse_package_instantiation(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Package)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -43,7 +43,7 @@ pub fn parse_package_instantiation(stream: &TokenStream) -> ParseResult ParseResult { +pub fn is_declarative_part(stream: &BaseTokenStream, begin_is_end: bool) -> ParseResult { Ok(check_declarative_part(stream.peek_expect()?, !begin_is_end, begin_is_end).is_ok()) } @@ -65,7 +65,7 @@ fn check_declarative_part(token: &Token, may_end: bool, may_begin: bool) -> Pars } pub fn parse_declarative_part( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut declarations: Vec = Vec::new(); diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 89e63481..af954e9b 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use super::common::check_end_identifier_mismatch; use super::common::ParseResult; @@ -22,7 +22,7 @@ use crate::data::*; /// Parse an entity declaration, token is initial entity token /// If a parse error occurs the stream is consumed until and end entity pub fn parse_entity_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Entity)?; @@ -57,7 +57,7 @@ pub fn parse_entity_declaration( /// LRM 3.3.1 pub fn parse_architecture_body( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Architecture)?; @@ -88,7 +88,7 @@ pub fn parse_architecture_body( /// LRM 4.7 Package declarations pub fn parse_package_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Package)?; @@ -120,7 +120,7 @@ pub fn parse_package_declaration( /// LRM 4.8 Package bodies pub fn parse_package_body( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Package)?; @@ -159,7 +159,7 @@ fn context_item_message(context_item: &ContextItem, message: impl AsRef) -> } pub fn parse_design_file( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut context_clause = vec![]; diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index 9e84eaca..71bf2b72 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_name, parse_type_mark}; use super::subtype_indication::parse_subtype_constraint; -use super::tokens::{Kind, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind, Kind::*, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; @@ -142,7 +142,7 @@ fn kind_to_binary_op(kind: Kind) -> Option<(Operator, usize)> { } pub fn parse_aggregate_initial_choices( - stream: &TokenStream, + stream: &BaseTokenStream, choices: Vec>, ) -> ParseResult>> { let mut choices = choices; @@ -191,7 +191,7 @@ pub fn parse_aggregate_initial_choices( } } -pub fn parse_aggregate(stream: &TokenStream) -> ParseResult>> { +pub fn parse_aggregate(stream: &BaseTokenStream) -> ParseResult>> { stream.expect_kind(LeftPar)?; if let Some(token) = stream.pop_if_kind(RightPar) { return Ok(WithPos::from(Vec::new(), token.pos.clone())); @@ -201,7 +201,7 @@ pub fn parse_aggregate(stream: &TokenStream) -> ParseResult, direction: Direction, ) -> ParseResult> { @@ -217,7 +217,7 @@ fn parse_half_range( Ok(WithPos::new(range, pos)) } -fn parse_choice(stream: &TokenStream) -> ParseResult> { +fn parse_choice(stream: &BaseTokenStream) -> ParseResult> { if let Some(token) = stream.pop_if_kind(Others) { return Ok(WithPos::new(Choice::Others, token.pos.clone())); } @@ -234,7 +234,7 @@ fn parse_choice(stream: &TokenStream) -> ParseResult> { } } -pub fn parse_choices(stream: &TokenStream) -> ParseResult>> { +pub fn parse_choices(stream: &BaseTokenStream) -> ParseResult>> { let mut choices = Vec::new(); loop { choices.push(parse_choice(stream)?); @@ -247,7 +247,7 @@ pub fn parse_choices(stream: &TokenStream) -> ParseResult>> } /// LRM 9.3.7 Allocators -fn parse_allocator(stream: &TokenStream) -> ParseResult> { +fn parse_allocator(stream: &BaseTokenStream) -> ParseResult> { stream.expect_kind(New)?; let type_mark = parse_type_mark(stream)?; @@ -318,7 +318,7 @@ fn name_to_selected_name(name: Name) -> Option { } } -fn parse_expression_or_aggregate(stream: &TokenStream) -> ParseResult> { +fn parse_expression_or_aggregate(stream: &BaseTokenStream) -> ParseResult> { let mut choices = parse_choices(stream)?; if choices.len() == 1 @@ -369,7 +369,7 @@ fn parse_expression_or_aggregate(stream: &TokenStream) -> ParseResult ParseResult> { +fn parse_primary(stream: &BaseTokenStream) -> ParseResult> { let token = stream.peek_expect()?; match token.kind { Identifier | LtLt => { @@ -479,7 +479,7 @@ fn parse_primary(stream: &TokenStream) -> ParseResult> { } } -fn parse_expr(stream: &TokenStream, min_precedence: usize) -> ParseResult> { +fn parse_expr(stream: &BaseTokenStream, min_precedence: usize) -> ParseResult> { let mut lhs = parse_primary(stream)?; while let Some(token) = stream.peek() { if token.kind == RightPar { @@ -524,7 +524,7 @@ fn parse_expr(stream: &TokenStream, min_precedence: usize) -> ParseResult ParseResult> { +pub fn parse_expression(stream: &BaseTokenStream) -> ParseResult> { let state = stream.state(); parse_expr(stream, 0).map_err(|err| { stream.set_state(state); diff --git a/vhdl_lang/src/syntax/interface_declaration.rs b/vhdl_lang/src/syntax/interface_declaration.rs index bc44a7c7..f87c5af7 100644 --- a/vhdl_lang/src/syntax/interface_declaration.rs +++ b/vhdl_lang/src/syntax/interface_declaration.rs @@ -14,7 +14,7 @@ use super::tokens::{Kind::*, *}; use crate::ast::*; use crate::data::*; -fn parse_optional_mode(stream: &TokenStream) -> ParseResult>> { +fn parse_optional_mode(stream: &BaseTokenStream) -> ParseResult>> { let token = stream.peek_expect()?; let mode = match token.kind { In => Mode::In, @@ -37,7 +37,7 @@ fn unexpected_object_class_kind(list_type: InterfaceType, token: &Token) -> Diag } fn parse_optional_object_class( - stream: &TokenStream, + stream: &BaseTokenStream, list_type: InterfaceType, ) -> ParseResult>> { let token = stream.peek_expect()?; @@ -54,7 +54,7 @@ fn parse_optional_object_class( } fn parse_interface_file_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult> { let file_objects = parse_file_declaration_no_semi(stream)?; for file_object in file_objects.iter() { @@ -84,7 +84,7 @@ fn parse_interface_file_declaration( } fn parse_interface_object_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, list_type: InterfaceType, ) -> ParseResult> { let explicit_object_class = parse_optional_object_class(stream, list_type)?; @@ -158,7 +158,7 @@ fn parse_interface_object_declaration( .collect()) } -fn parse_subprogram_default(stream: &TokenStream) -> ParseResult> { +fn parse_subprogram_default(stream: &BaseTokenStream) -> ParseResult> { if stream.skip_if_kind(Is) { let default = { peek_token!( @@ -177,7 +177,7 @@ fn parse_subprogram_default(stream: &TokenStream) -> ParseResult ParseResult { +fn parse_interface_package(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Package)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -212,7 +212,7 @@ fn parse_interface_package(stream: &TokenStream) -> ParseResult ParseResult> { @@ -241,7 +241,7 @@ fn parse_interface_declaration( /// Parse ; separator in generic or port lists. /// Expect ; for all but the last item -fn parse_semicolon_separator(stream: &TokenStream) -> ParseResult<()> { +fn parse_semicolon_separator(stream: &BaseTokenStream) -> ParseResult<()> { peek_token!( stream, token, SemiColon => { @@ -269,7 +269,7 @@ fn is_sync_kind(list_type: InterfaceType, kind: Kind) -> bool { } fn parse_interface_list( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, list_type: InterfaceType, ) -> ParseResult> { @@ -335,21 +335,21 @@ fn parse_interface_list( } pub fn parse_generic_interface_list( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Generic) } pub fn parse_port_interface_list( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Port) } pub fn parse_parameter_interface_list( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Parameter) @@ -357,7 +357,7 @@ pub fn parse_parameter_interface_list( #[cfg(test)] fn parse_one_interface_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, list_type: InterfaceType, ) -> ParseResult { let mut diagnostics = Vec::new(); @@ -370,17 +370,17 @@ fn parse_one_interface_declaration( } #[cfg(test)] -pub fn parse_parameter(stream: &TokenStream) -> ParseResult { +pub fn parse_parameter(stream: &BaseTokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Parameter) } #[cfg(test)] -pub fn parse_port(stream: &TokenStream) -> ParseResult { +pub fn parse_port(stream: &BaseTokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Port) } #[cfg(test)] -pub fn parse_generic(stream: &TokenStream) -> ParseResult { +pub fn parse_generic(stream: &BaseTokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Generic) } diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index 3edbc1c3..a25a4506 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -9,12 +9,12 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; -pub fn parse_designator(stream: &TokenStream) -> ParseResult> { +pub fn parse_designator(stream: &BaseTokenStream) -> ParseResult> { Ok(expect_token!( stream, token, @@ -24,7 +24,7 @@ pub fn parse_designator(stream: &TokenStream) -> ParseResult )) } -pub fn parse_selected_name(stream: &TokenStream) -> ParseResult> { +pub fn parse_selected_name(stream: &BaseTokenStream) -> ParseResult> { let mut name = parse_designator(stream)? .into_ref() .map_into(SelectedName::Designator); @@ -39,13 +39,13 @@ pub fn parse_selected_name(stream: &TokenStream) -> ParseResult ParseResult> { +pub fn parse_type_mark(stream: &BaseTokenStream) -> ParseResult> { let name = parse_selected_name(stream)?; parse_type_mark_starting_with_name(stream, name) } pub fn parse_type_mark_starting_with_name( - stream: &TokenStream, + stream: &BaseTokenStream, name: WithPos, ) -> ParseResult> { let state = stream.state(); @@ -96,7 +96,7 @@ pub fn expression_to_ident(name: WithPos) -> ParseResult { to_simple_name(name) } -pub fn parse_identifier_list(stream: &TokenStream) -> ParseResult> { +pub fn parse_identifier_list(stream: &BaseTokenStream) -> ParseResult> { let mut idents = Vec::new(); loop { idents.push(stream.expect_ident()?); @@ -152,7 +152,7 @@ fn assoc_to_expression(assoc: AssociationElement) -> ParseResult ParseResult> { +fn parse_actual_part(stream: &BaseTokenStream) -> ParseResult> { if let Some(token) = stream.pop_if_kind(Open) { Ok(WithPos::from(ActualPart::Open, token.pos.clone())) } else { @@ -160,7 +160,7 @@ fn parse_actual_part(stream: &TokenStream) -> ParseResult> { } } -fn parse_association_element(stream: &TokenStream) -> ParseResult { +fn parse_association_element(stream: &BaseTokenStream) -> ParseResult { let actual = parse_actual_part(stream)?; if stream.skip_if_kind(RightArrow) { Ok(AssociationElement { @@ -175,13 +175,13 @@ fn parse_association_element(stream: &TokenStream) -> ParseResult ParseResult> { +pub fn parse_association_list(stream: &BaseTokenStream) -> ParseResult> { stream.expect_kind(LeftPar)?; parse_association_list_no_leftpar(stream) } pub fn parse_association_list_no_leftpar( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult> { let mut association_elements = Vec::with_capacity(1); loop { @@ -198,7 +198,7 @@ pub fn parse_association_list_no_leftpar( } fn parse_function_call( - stream: &TokenStream, + stream: &BaseTokenStream, prefix: WithPos, first: AssociationElement, ) -> ParseResult> { @@ -225,7 +225,7 @@ fn parse_function_call( } fn parse_attribute_name( - stream: &TokenStream, + stream: &BaseTokenStream, name: WithPos, signature: Option>, ) -> ParseResult> { @@ -257,7 +257,7 @@ enum DesignatorOrAll { All, } -fn parse_suffix(stream: &TokenStream) -> ParseResult> { +fn parse_suffix(stream: &BaseTokenStream) -> ParseResult> { let name = { expect_token!( stream, @@ -274,7 +274,7 @@ fn parse_suffix(stream: &TokenStream) -> ParseResult> { /// LRM 8.7 External names /// Inside of << >> -fn parse_inner_external_name(stream: &TokenStream) -> ParseResult { +fn parse_inner_external_name(stream: &BaseTokenStream) -> ParseResult { let token = stream.peek_expect()?; let class = try_init_token_kind!( token, @@ -327,7 +327,7 @@ fn parse_inner_external_name(stream: &TokenStream) -> ParseResult } /// LRM 8. Names -fn _parse_name(stream: &TokenStream) -> ParseResult> { +fn _parse_name(stream: &BaseTokenStream) -> ParseResult> { let mut name = { if let Some(token) = stream.pop_if_kind(LtLt) { let external_name = Name::External(Box::new(parse_inner_external_name(stream)?)); @@ -472,7 +472,7 @@ pub fn into_range(assoc: AssociationElement) -> Result ParseResult> { +pub fn parse_name(stream: &BaseTokenStream) -> ParseResult> { let state = stream.state(); _parse_name(stream).map_err(|err| { stream.set_state(state); diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index 0fd17ebb..06708cb9 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -8,12 +8,14 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_identifier_list; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; /// LRM 6.4.2 Object Declarations use crate::ast::*; use crate::data::WithPos; -pub fn parse_optional_assignment(stream: &TokenStream) -> ParseResult>> { +pub fn parse_optional_assignment( + stream: &BaseTokenStream, +) -> ParseResult>> { if stream.pop_if_kind(ColonEq).is_some() { let expr = parse_expression(stream)?; Ok(Some(expr)) @@ -23,7 +25,7 @@ pub fn parse_optional_assignment(stream: &TokenStream) -> ParseResult ParseResult> { match class { @@ -58,7 +60,7 @@ fn parse_object_declaration_kind( .collect()) } -pub fn parse_object_declaration(stream: &TokenStream) -> ParseResult> { +pub fn parse_object_declaration(stream: &BaseTokenStream) -> ParseResult> { let token = stream.peek_expect()?; let result = try_init_token_kind!( token, @@ -73,7 +75,9 @@ pub fn parse_object_declaration(stream: &TokenStream) -> ParseResult ParseResult> { +pub fn parse_file_declaration_no_semi( + stream: &BaseTokenStream, +) -> ParseResult> { stream.expect_kind(File)?; let idents = parse_identifier_list(stream)?; stream.expect_kind(Colon)?; @@ -106,7 +110,7 @@ pub fn parse_file_declaration_no_semi(stream: &TokenStream) -> ParseResult ParseResult> { +pub fn parse_file_declaration(stream: &BaseTokenStream) -> ParseResult> { let result = parse_file_declaration_no_semi(stream)?; stream.expect_kind(SemiColon)?; Ok(result) diff --git a/vhdl_lang/src/syntax/parser.rs b/vhdl_lang/src/syntax/parser.rs index f87ff107..cf155807 100644 --- a/vhdl_lang/src/syntax/parser.rs +++ b/vhdl_lang/src/syntax/parser.rs @@ -5,7 +5,7 @@ // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com use super::design_unit::parse_design_file; -use super::tokens::{Symbols, TokenStream, Tokenizer}; +use super::tokens::{BaseTokenStream, Symbols, Tokenizer}; use crate::ast::DesignFile; use crate::data::*; use std::io; @@ -30,7 +30,7 @@ impl VHDLParser { ) -> DesignFile { let contents = source.contents(); let tokenizer = Tokenizer::new(&self.symbols, source, ContentReader::new(&contents)); - let stream = TokenStream::new(tokenizer, diagnostics); + let stream = BaseTokenStream::new(tokenizer, diagnostics); match parse_design_file(&stream, diagnostics) { Ok(design_file) => design_file, diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index f7892262..ef34e330 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -8,12 +8,12 @@ use super::common::parse_optional; use super::common::ParseResult; use super::expression::name_to_type_mark; use super::expression::parse_expression; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; -pub fn parse_direction(stream: &TokenStream) -> ParseResult { +pub fn parse_direction(stream: &BaseTokenStream) -> ParseResult { Ok(expect_token!( stream, token, To => Direction::Ascending, @@ -26,7 +26,7 @@ enum NameOrRange { Range(WithPos), } -fn parse_name_or_range(stream: &TokenStream) -> ParseResult { +fn parse_name_or_range(stream: &BaseTokenStream) -> ParseResult { let expr = parse_expression(stream)?; match stream.peek_kind() { @@ -72,14 +72,14 @@ fn parse_name_or_range(stream: &TokenStream) -> ParseResult { /// {selected_name}'range /// {selected_name}'reverse_range /// 2. {expr} to|downto {expr} -pub fn parse_range(stream: &TokenStream) -> ParseResult> { +pub fn parse_range(stream: &BaseTokenStream) -> ParseResult> { match parse_name_or_range(stream)? { NameOrRange::Range(range) => Ok(range), NameOrRange::Name(name) => Err(Diagnostic::error(&name, "Expected range")), } } -pub fn parse_discrete_range(stream: &TokenStream) -> ParseResult { +pub fn parse_discrete_range(stream: &BaseTokenStream) -> ParseResult { match parse_name_or_range(stream) { Ok(NameOrRange::Range(range)) => Ok(DiscreteRange::Range(range.item)), Ok(NameOrRange::Name(name)) => { @@ -91,7 +91,7 @@ pub fn parse_discrete_range(stream: &TokenStream) -> ParseResult } } -pub fn parse_array_index_constraint(stream: &TokenStream) -> ParseResult { +pub fn parse_array_index_constraint(stream: &BaseTokenStream) -> ParseResult { match parse_name_or_range(stream) { Ok(NameOrRange::Range(range)) => Ok(ArrayIndex::Discrete(DiscreteRange::Range(range.item))), Ok(NameOrRange::Name(name)) => { diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index 450aa134..d2bb434b 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -10,14 +10,14 @@ use super::expression::parse_aggregate; use super::expression::{parse_choices, parse_expression}; use super::names::parse_name; use super::range::parse_discrete_range; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; use crate::syntax::common::check_label_identifier_mismatch; /// LRM 10.2 Wait statement -fn parse_wait_statement(stream: &TokenStream) -> ParseResult { +fn parse_wait_statement(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Wait)?; let mut sensitivity_clause = vec![]; if stream.skip_if_kind(On) { @@ -41,7 +41,7 @@ fn parse_wait_statement(stream: &TokenStream) -> ParseResult { } /// LRM 10.3 Assertion statement -pub fn parse_assert_statement(stream: &TokenStream) -> ParseResult { +pub fn parse_assert_statement(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Assert)?; let condition = parse_expression(stream)?; let report = parse_optional(stream, Report, parse_expression)?; @@ -56,7 +56,7 @@ pub fn parse_assert_statement(stream: &TokenStream) -> ParseResult ParseResult { +fn parse_report_statement(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Report)?; let report = parse_expression(stream)?; let severity = parse_optional(stream, Severity, parse_expression)?; @@ -66,7 +66,7 @@ fn parse_report_statement(stream: &TokenStream) -> ParseResult } pub fn parse_labeled_sequential_statements( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut statements = Vec::new(); @@ -85,7 +85,7 @@ pub fn parse_labeled_sequential_statements( /// LRM 10.8 If statement fn parse_if_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -146,7 +146,7 @@ fn parse_if_statement( /// LRM 10.9 Case statement fn parse_case_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -194,7 +194,7 @@ fn parse_case_statement( /// LRM 10.10 Loop statement fn parse_loop_statement( - stream: &TokenStream, + stream: &BaseTokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -236,7 +236,7 @@ fn parse_loop_statement( } /// LRM 10.11 Next statement -fn parse_next_statement(stream: &TokenStream) -> ParseResult { +fn parse_next_statement(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Next)?; let loop_label = stream.pop_optional_ident(); let condition = parse_optional(stream, When, parse_expression)?; @@ -248,7 +248,7 @@ fn parse_next_statement(stream: &TokenStream) -> ParseResult { } /// LRM 10.12 Exit statement -fn parse_exit_statement(stream: &TokenStream) -> ParseResult { +fn parse_exit_statement(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Exit)?; let loop_label = stream.pop_optional_ident(); let condition = parse_optional(stream, When, parse_expression)?; @@ -260,7 +260,7 @@ fn parse_exit_statement(stream: &TokenStream) -> ParseResult { } /// LRM 10.13 Return statement -fn parse_return_statement(stream: &TokenStream) -> ParseResult { +fn parse_return_statement(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Return)?; let expression = { if stream.peek_kind() == Some(SemiColon) { @@ -275,24 +275,24 @@ fn parse_return_statement(stream: &TokenStream) -> ParseResult /// LRM 10.5 Signal assignment statement pub fn parse_signal_assignment_right_hand( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult> { parse_assignment_right_hand(stream, parse_waveform) } /// LRM 10.6 Variable assignment statement fn parse_variable_assignment_right_hand( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult>> { parse_assignment_right_hand(stream, parse_expression) } fn parse_assignment_right_hand( - stream: &TokenStream, + stream: &BaseTokenStream, parse_item: F, ) -> ParseResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&BaseTokenStream) -> ParseResult, { let item = parse_item(stream)?; @@ -310,12 +310,12 @@ where } fn parse_conditonals( - stream: &TokenStream, + stream: &BaseTokenStream, initial_item: T, parse_item: F, ) -> ParseResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&BaseTokenStream) -> ParseResult, { let condition = parse_expression(stream)?; let cond_expr = Conditional { @@ -362,12 +362,12 @@ where } pub fn parse_selection( - stream: &TokenStream, + stream: &BaseTokenStream, expression: WithPos, parse_item: F, ) -> ParseResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&BaseTokenStream) -> ParseResult, { let mut alternatives = Vec::with_capacity(2); @@ -391,7 +391,7 @@ where }) } -fn parse_optional_force_mode(stream: &TokenStream) -> ParseResult> { +fn parse_optional_force_mode(stream: &BaseTokenStream) -> ParseResult> { let token = stream.peek_expect()?; let optional_force_mode = match token.kind { In => { @@ -409,7 +409,7 @@ fn parse_optional_force_mode(stream: &TokenStream) -> ParseResult, ) -> ParseResult { Ok(expect_token!( @@ -472,7 +472,7 @@ fn parse_assignment_or_procedure_call( )) } -pub fn parse_target(stream: &TokenStream) -> ParseResult> { +pub fn parse_target(stream: &BaseTokenStream) -> ParseResult> { if stream.next_kind_is(LeftPar) { Ok(parse_aggregate(stream)?.map_into(Target::Aggregate)) } else { @@ -480,7 +480,7 @@ pub fn parse_target(stream: &TokenStream) -> ParseResult> { } } -fn parse_selected_assignment(stream: &TokenStream) -> ParseResult { +fn parse_selected_assignment(stream: &BaseTokenStream) -> ParseResult { let expression = parse_expression(stream)?; stream.expect_kind(Select)?; let target = parse_target(stream)?; @@ -513,7 +513,7 @@ fn parse_selected_assignment(stream: &TokenStream) -> ParseResult, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -551,7 +551,7 @@ fn parse_unlabeled_sequential_statement( } pub fn parse_sequential_statement( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let start = stream.peek_expect()?; diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 4752e5d6..69d5a4b7 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -9,11 +9,11 @@ use super::declarative_part::parse_declarative_part; use super::interface_declaration::parse_parameter_interface_list; use super::names::parse_type_mark; use super::sequential_statement::parse_labeled_sequential_statements; -use super::tokens::{kinds_error, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{kinds_error, BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::*; use crate::data::*; -pub fn parse_signature(stream: &TokenStream) -> ParseResult> { +pub fn parse_signature(stream: &BaseTokenStream) -> ParseResult> { let left_square = stream.expect_kind(LeftSquare)?; let start_pos = &left_square.pos; let mut type_marks = Vec::new(); @@ -67,7 +67,7 @@ pub fn parse_signature(stream: &TokenStream) -> ParseResult> Ok(WithPos::new(signature, pos)) } -fn parse_designator(stream: &TokenStream) -> ParseResult> { +fn parse_designator(stream: &BaseTokenStream) -> ParseResult> { Ok(expect_token!( stream, token, @@ -77,7 +77,7 @@ fn parse_designator(stream: &TokenStream) -> ParseResult ParseResult { let (is_function, is_pure) = { @@ -125,7 +125,7 @@ pub fn parse_subprogram_declaration_no_semi( } pub fn parse_subprogram_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let res = parse_subprogram_declaration_no_semi(stream, diagnostics); @@ -135,7 +135,7 @@ pub fn parse_subprogram_declaration( /// LRM 4.3 Subprogram bodies pub fn parse_subprogram_body( - stream: &TokenStream, + stream: &BaseTokenStream, specification: SubprogramDeclaration, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -173,7 +173,7 @@ pub fn parse_subprogram_body( } pub fn parse_subprogram( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let specification = parse_subprogram_declaration_no_semi(stream, diagnostics)?; diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index 8640ba85..60498540 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -7,19 +7,19 @@ use super::common::ParseResult; use super::names::{parse_selected_name, parse_type_mark, parse_type_mark_starting_with_name}; use super::range::{parse_discrete_range, parse_range}; -use super::tokens::{kinds_error, Kind::*, TokenStream, _TokenStream}; +use super::tokens::{kinds_error, BaseTokenStream, Kind::*, _TokenStream}; /// LRM 6.3 Subtype declarations use crate::ast::*; use crate::data::{SrcPos, WithPos}; -fn parse_record_element_constraint(stream: &TokenStream) -> ParseResult { +fn parse_record_element_constraint(stream: &BaseTokenStream) -> ParseResult { let ident = stream.expect_ident()?; let constraint = Box::new(parse_composite_constraint(stream)?); Ok(ElementConstraint { ident, constraint }) } fn parse_array_constraint( - stream: &TokenStream, + stream: &BaseTokenStream, leftpar_pos: SrcPos, // Open is None initial: Option, @@ -52,7 +52,7 @@ fn parse_array_constraint( )) } -fn parse_composite_constraint(stream: &TokenStream) -> ParseResult> { +fn parse_composite_constraint(stream: &BaseTokenStream) -> ParseResult> { // There is no finite lookahead that can differentiate // between array and record element constraint let leftpar_pos = stream.expect_kind(LeftPar)?.pos.clone(); @@ -103,7 +103,7 @@ fn parse_composite_constraint(stream: &TokenStream) -> ParseResult ParseResult>> { if let Some(token) = stream.peek() { let constraint = match token.kind { @@ -125,7 +125,7 @@ pub fn parse_subtype_constraint( } pub fn parse_element_resolution_indication( - stream: &TokenStream, + stream: &BaseTokenStream, ) -> ParseResult { stream.expect_kind(LeftPar)?; @@ -178,7 +178,7 @@ pub fn parse_element_resolution_indication( )) } -pub fn parse_subtype_indication(stream: &TokenStream) -> ParseResult { +pub fn parse_subtype_indication(stream: &BaseTokenStream) -> ParseResult { let (resolution, type_mark) = { if stream.peek_kind() == Some(LeftPar) { let resolution = parse_element_resolution_indication(stream)?; diff --git a/vhdl_lang/src/syntax/test.rs b/vhdl_lang/src/syntax/test.rs index 727451c0..e2a9ef70 100644 --- a/vhdl_lang/src/syntax/test.rs +++ b/vhdl_lang/src/syntax/test.rs @@ -21,7 +21,7 @@ use super::range::{parse_discrete_range, parse_range}; use super::sequential_statement::parse_sequential_statement; use super::subprogram::{parse_signature, parse_subprogram_declaration_no_semi}; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Comment, Kind, Symbols, Token, TokenStream, Tokenizer}; +use super::tokens::{BaseTokenStream, Comment, Kind, Symbols, Token, Tokenizer}; use super::type_declaration::parse_type_declaration; use super::waveform::parse_waveform; use crate::ast; @@ -197,7 +197,7 @@ impl Code { /// Helper method to run lower level parsing function at specific substring pub fn parse(&self, parse_fun: F) -> R where - F: FnOnce(&TokenStream) -> R, + F: FnOnce(&BaseTokenStream) -> R, { let contents = self.pos.source.contents(); let source = Source::from_contents( @@ -207,7 +207,7 @@ impl Code { let contents = source.contents(); let reader = ContentReader::new(&contents); let tokenizer = Tokenizer::new(&self.symbols, &source, reader); - let mut stream = TokenStream::new(tokenizer, &mut NoDiagnostics); + let mut stream = BaseTokenStream::new(tokenizer, &mut NoDiagnostics); forward(&stream, self.pos.start()); parse_fun(&mut stream) } @@ -215,7 +215,7 @@ impl Code { /// Expect Ok() value pub fn parse_ok(&self, parse_fun: F) -> R where - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&BaseTokenStream) -> ParseResult, { match self.parse(parse_fun) { Ok(res) => res, @@ -227,21 +227,21 @@ impl Code { pub fn with_partial_stream(&self, parse_fun: F) -> R where - F: FnOnce(&TokenStream) -> R, + F: FnOnce(&BaseTokenStream) -> R, { let contents = self.pos.source.contents(); let reader = ContentReader::new(&contents); let tokenizer = Tokenizer::new(&self.symbols, &self.pos.source, reader); - let mut stream = TokenStream::new(tokenizer, &mut NoDiagnostics); + let mut stream = BaseTokenStream::new(tokenizer, &mut NoDiagnostics); parse_fun(&mut stream) } pub fn with_stream(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&BaseTokenStream) -> ParseResult, { - let parse_fun_eof = |stream: &TokenStream| { + let parse_fun_eof = |stream: &BaseTokenStream| { let result = parse_fun(stream); match result { Err(err) => { @@ -265,9 +265,9 @@ impl Code { pub fn with_stream_err(&self, parse_fun: F) -> Diagnostic where R: Debug, - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&BaseTokenStream) -> ParseResult, { - let parse_fun_eof = |stream: &TokenStream| { + let parse_fun_eof = |stream: &BaseTokenStream| { let result = parse_fun(stream); match result { Err(err) => { @@ -289,28 +289,29 @@ impl Code { pub fn with_partial_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> R, + F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> R, { let mut diagnostics = Vec::new(); - let result = - self.with_partial_stream(|stream: &TokenStream| parse_fun(stream, &mut diagnostics)); + let result = self + .with_partial_stream(|stream: &BaseTokenStream| parse_fun(stream, &mut diagnostics)); (result, diagnostics) } pub fn with_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let mut diagnostics = Vec::new(); - let result = self.with_stream(|stream: &TokenStream| parse_fun(stream, &mut diagnostics)); + let result = + self.with_stream(|stream: &BaseTokenStream| parse_fun(stream, &mut diagnostics)); (result, diagnostics) } pub fn with_stream_no_diagnostics(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let (result, diagnostics) = self.with_stream_diagnostics(parse_fun); check_no_diagnostics(&diagnostics); @@ -325,11 +326,11 @@ impl Code { } /// Helper to create a identifier at first occurence of name pub fn ident(&self) -> Ident { - self.parse_ok(|stream: &TokenStream| stream.expect_ident()) + self.parse_ok(|stream: &BaseTokenStream| stream.expect_ident()) } pub fn decl_ident(&self) -> WithDecl { - WithDecl::new(self.parse_ok(|stream: &TokenStream| stream.expect_ident())) + WithDecl::new(self.parse_ok(|stream: &BaseTokenStream| stream.expect_ident())) } pub fn designator(&self) -> WithPos { @@ -344,7 +345,7 @@ impl Code { } pub fn character(&self) -> WithPos { - self.parse_ok(|stream: &TokenStream| { + self.parse_ok(|stream: &BaseTokenStream| { stream.expect_kind(Kind::Character)?.to_character_value() }) } @@ -435,7 +436,7 @@ impl Code { pub fn parse_ok_no_diagnostics(&self, parse_fun: F) -> R where - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let mut diagnostics = Vec::new(); let res = self.parse_ok(|stream| parse_fun(stream, &mut diagnostics)); @@ -527,7 +528,7 @@ fn substr_range(source: &Source, range: Range, substr: &str, occurence: usize) - } /// Fast forward tokenstream until position -fn forward(stream: &TokenStream, start: Position) { +fn forward(stream: &BaseTokenStream, start: Position) { loop { let token = stream.peek_expect().unwrap(); if token.pos.start() >= start { diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index 49df7413..901089de 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -12,12 +12,6 @@ use crate::ast::{AttributeDesignator, Ident, RangeAttribute, TypeAttribute}; use crate::data::{DiagnosticHandler, DiagnosticResult, WithPos}; use crate::{Diagnostic, SrcPos}; -pub struct TokenStream<'a> { - tokenizer: Tokenizer<'a>, - idx: Cell, - tokens: Vec, -} - /// A TokenStream is an immutable collection of tokens with a mutable state. /// The state points to a certain tokens. Methods exist to mutate that state and seek /// to another token, e.g. to skip a token or go to a previous one. @@ -188,13 +182,19 @@ pub enum TokenizationException<'a> { EofError { expectations: Option<&'a [Kind]> }, } +pub struct BaseTokenStream<'a> { + tokenizer: Tokenizer<'a>, + idx: Cell, + tokens: Vec, +} + /// The token stream maintains a collection of tokens and a current state. /// The state is an index into the vector of tokens and -impl<'a> TokenStream<'a> { +impl<'a> BaseTokenStream<'a> { pub fn new( mut tokenizer: Tokenizer<'a>, diagnostics: &mut dyn DiagnosticHandler, - ) -> TokenStream<'a> { + ) -> BaseTokenStream<'a> { let mut tokens = Vec::new(); loop { match tokenizer.pop() { @@ -203,7 +203,7 @@ impl<'a> TokenStream<'a> { Err(err) => diagnostics.push(err), } } - TokenStream { + BaseTokenStream { tokenizer, idx: Cell::new(0), tokens, @@ -219,7 +219,7 @@ impl<'a> TokenStream<'a> { } } -impl<'a> _TokenStream for TokenStream<'a> { +impl<'a> _TokenStream for BaseTokenStream<'a> { fn state(&self) -> usize { self.idx.get() } @@ -277,7 +277,7 @@ impl<'a> _TokenStream for TokenStream<'a> { pub trait Recover { fn or_recover_until( self, - stream: &TokenStream, + stream: &BaseTokenStream, msgs: &mut dyn DiagnosticHandler, cond: fn(Kind) -> bool, ) -> DiagnosticResult; @@ -288,7 +288,7 @@ pub trait Recover { impl Recover for DiagnosticResult { fn or_recover_until( self, - stream: &TokenStream, + stream: &BaseTokenStream, msgs: &mut dyn DiagnosticHandler, cond: fn(Kind) -> bool, ) -> DiagnosticResult { diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index 98aab086..2aff7fc0 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -11,14 +11,14 @@ use super::names::parse_identifier_list; use super::range::{parse_array_index_constraint, parse_range}; use super::subprogram::parse_subprogram_declaration; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; use crate::ast::*; use crate::ast::{AbstractLiteral, Range}; use crate::data::DiagnosticHandler; use crate::syntax::names::parse_type_mark; /// LRM 5.2.2 Enumeration types -fn parse_enumeration_type_definition(stream: &TokenStream) -> ParseResult { +fn parse_enumeration_type_definition(stream: &BaseTokenStream) -> ParseResult { let mut enum_literals = Vec::new(); loop { expect_token!(stream, @@ -45,7 +45,7 @@ fn parse_enumeration_type_definition(stream: &TokenStream) -> ParseResult ParseResult> { +fn parse_array_index_constraints(stream: &BaseTokenStream) -> ParseResult> { stream.expect_kind(LeftPar)?; let mut indexes = Vec::new(); loop { @@ -61,7 +61,7 @@ fn parse_array_index_constraints(stream: &TokenStream) -> ParseResult ParseResult { +fn parse_array_type_definition(stream: &BaseTokenStream) -> ParseResult { let index_constraints = parse_array_index_constraints(stream)?; stream.expect_kind(Of)?; let element_subtype = parse_subtype_indication(stream)?; @@ -71,7 +71,7 @@ fn parse_array_type_definition(stream: &TokenStream) -> ParseResult ParseResult<(TypeDefinition, Option)> { let mut elem_decls = Vec::new(); @@ -96,7 +96,7 @@ fn parse_record_type_definition( } } -pub fn parse_subtype_declaration(stream: &TokenStream) -> ParseResult { +pub fn parse_subtype_declaration(stream: &BaseTokenStream) -> ParseResult { stream.expect_kind(Subtype)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -111,7 +111,7 @@ pub fn parse_subtype_declaration(stream: &TokenStream) -> ParseResult ParseResult<(ProtectedTypeDeclaration, Option)> { let mut items = Vec::new(); @@ -137,7 +137,7 @@ pub fn parse_protected_type_declaration( /// LRM 5.2.4 Physical types fn parse_physical_type_definition( - stream: &TokenStream, + stream: &BaseTokenStream, range: Range, ) -> ParseResult<(TypeDefinition, Option)> { let primary_unit = WithDecl::new(stream.expect_ident()?); @@ -193,7 +193,7 @@ fn parse_physical_type_definition( /// LRM 6.2 pub fn parse_type_declaration( - stream: &TokenStream, + stream: &BaseTokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { peek_token!( diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 58ebcbfc..1bc61ce1 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -8,10 +8,10 @@ use crate::ast::{DelayMechanism, Waveform, WaveformElement}; use super::common::{parse_optional, ParseResult}; use super::expression::parse_expression; -use super::tokens::{Kind::*, TokenStream, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; /// LRM 10.5 Signal assignment statement -pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult> { +pub fn parse_delay_mechanism(stream: &BaseTokenStream) -> ParseResult> { let token = stream.peek_expect()?; match token.kind { Transport => { @@ -33,7 +33,7 @@ pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult ParseResult { +pub fn parse_waveform(stream: &BaseTokenStream) -> ParseResult { if stream.skip_if_kind(Unaffected) { return Ok(Waveform::Unaffected); } From a6741de80507ebd60718a0873e7733af76395ecf Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 22 Jul 2023 21:16:49 +0200 Subject: [PATCH 09/31] Rename _TokenStream to TokenStream --- vhdl_lang/src/syntax/alias_declaration.rs | 2 +- vhdl_lang/src/syntax/attributes.rs | 2 +- vhdl_lang/src/syntax/common.rs | 2 +- vhdl_lang/src/syntax/component_declaration.rs | 2 +- vhdl_lang/src/syntax/concurrent_statement.rs | 2 +- vhdl_lang/src/syntax/configuration.rs | 2 +- vhdl_lang/src/syntax/context.rs | 2 +- vhdl_lang/src/syntax/design_unit.rs | 2 +- vhdl_lang/src/syntax/expression.rs | 2 +- vhdl_lang/src/syntax/names.rs | 2 +- vhdl_lang/src/syntax/object_declaration.rs | 2 +- vhdl_lang/src/syntax/range.rs | 2 +- vhdl_lang/src/syntax/sequential_statement.rs | 2 +- vhdl_lang/src/syntax/subprogram.rs | 2 +- vhdl_lang/src/syntax/subtype_indication.rs | 2 +- vhdl_lang/src/syntax/tokens/tokenstream.rs | 4 ++-- vhdl_lang/src/syntax/type_declaration.rs | 2 +- vhdl_lang/src/syntax/waveform.rs | 2 +- 18 files changed, 19 insertions(+), 19 deletions(-) diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index 9cddac2c..28aa6dc0 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::names::{parse_designator, parse_name}; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast::{AliasDeclaration, WithDecl}; pub fn parse_alias_declaration(stream: &BaseTokenStream) -> ParseResult { diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index 8d7f3394..595c4126 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_type_mark; use super::subprogram::parse_signature; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast::{ Attribute, AttributeDeclaration, AttributeSpecification, Designator, EntityClass, EntityName, EntityTag, WithRef, diff --git a/vhdl_lang/src/syntax/common.rs b/vhdl_lang/src/syntax/common.rs index 8b182902..311cb9f2 100644 --- a/vhdl_lang/src/syntax/common.rs +++ b/vhdl_lang/src/syntax/common.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{BaseTokenStream, Kind, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind, TokenStream}; use crate::ast::Ident; use crate::data::Diagnostic; use crate::data::DiagnosticHandler; diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index c71db640..5038ef1e 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -7,7 +7,7 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::interface_declaration::{parse_generic_interface_list, parse_port_interface_list}; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast::WithDecl; use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; use crate::data::{Diagnostic, DiagnosticHandler}; diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index ffe1bbd4..fe9a116a 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -19,7 +19,7 @@ use super::sequential_statement::{ parse_assert_statement, parse_labeled_sequential_statements, parse_selection, parse_signal_assignment_right_hand, parse_target, }; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index e8a8f58f..7e0d1a2f 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -9,7 +9,7 @@ use super::common::ParseResult; use super::concurrent_statement::parse_generic_and_port_map; use super::context::parse_use_clause; use super::names::{parse_name, parse_selected_name}; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index 28160b22..54496929 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -7,7 +7,7 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::names::parse_name; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index af954e9b..beb8807b 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use super::common::check_end_identifier_mismatch; use super::common::ParseResult; diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index 71bf2b72..ef8be7e1 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_name, parse_type_mark}; use super::subtype_indication::parse_subtype_constraint; -use super::tokens::{BaseTokenStream, Kind, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind, Kind::*, TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index a25a4506..c04bacfb 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -9,7 +9,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index 06708cb9..ddfc6b59 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -8,7 +8,7 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_identifier_list; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; /// LRM 6.4.2 Object Declarations use crate::ast::*; use crate::data::WithPos; diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index ef34e330..0921e8d9 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -8,7 +8,7 @@ use super::common::parse_optional; use super::common::ParseResult; use super::expression::name_to_type_mark; use super::expression::parse_expression; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index d2bb434b..4500eb19 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -10,7 +10,7 @@ use super::expression::parse_aggregate; use super::expression::{parse_choices, parse_expression}; use super::names::parse_name; use super::range::parse_discrete_range; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 69d5a4b7..b16881dd 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -9,7 +9,7 @@ use super::declarative_part::parse_declarative_part; use super::interface_declaration::parse_parameter_interface_list; use super::names::parse_type_mark; use super::sequential_statement::parse_labeled_sequential_statements; -use super::tokens::{kinds_error, BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{kinds_error, BaseTokenStream, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index 60498540..dbd4a2bc 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_selected_name, parse_type_mark, parse_type_mark_starting_with_name}; use super::range::{parse_discrete_range, parse_range}; -use super::tokens::{kinds_error, BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{kinds_error, BaseTokenStream, Kind::*, TokenStream}; /// LRM 6.3 Subtype declarations use crate::ast::*; use crate::data::{SrcPos, WithPos}; diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index 901089de..851339c6 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -15,7 +15,7 @@ use crate::{Diagnostic, SrcPos}; /// A TokenStream is an immutable collection of tokens with a mutable state. /// The state points to a certain tokens. Methods exist to mutate that state and seek /// to another token, e.g. to skip a token or go to a previous one. -pub trait _TokenStream { +pub trait TokenStream { /// Returns the current state. /// `token_at(self.state())` must always return the current token, or `None` if the /// state is invalid @@ -219,7 +219,7 @@ impl<'a> BaseTokenStream<'a> { } } -impl<'a> _TokenStream for BaseTokenStream<'a> { +impl<'a> TokenStream for BaseTokenStream<'a> { fn state(&self) -> usize { self.idx.get() } diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index 2aff7fc0..c5bef4e9 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -11,7 +11,7 @@ use super::names::parse_identifier_list; use super::range::{parse_array_index_constraint, parse_range}; use super::subprogram::parse_subprogram_declaration; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; use crate::ast::*; use crate::ast::{AbstractLiteral, Range}; use crate::data::DiagnosticHandler; diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 1bc61ce1..9b1e108b 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -8,7 +8,7 @@ use crate::ast::{DelayMechanism, Waveform, WaveformElement}; use super::common::{parse_optional, ParseResult}; use super::expression::parse_expression; -use super::tokens::{BaseTokenStream, Kind::*, _TokenStream}; +use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; /// LRM 10.5 Signal assignment statement pub fn parse_delay_mechanism(stream: &BaseTokenStream) -> ParseResult> { From f169464e0ae43f1b9721ff961d31c78a4d0fa6af Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 22 Jul 2023 21:35:02 +0200 Subject: [PATCH 10/31] Refactor BaseTokenStream to TokenStream --- vhdl_lang/src/syntax/alias_declaration.rs | 4 +- vhdl_lang/src/syntax/attributes.rs | 8 +- vhdl_lang/src/syntax/common.rs | 6 +- vhdl_lang/src/syntax/component_declaration.rs | 8 +- vhdl_lang/src/syntax/concurrent_statement.rs | 36 +++---- vhdl_lang/src/syntax/configuration.rs | 24 ++--- vhdl_lang/src/syntax/context.rs | 10 +- vhdl_lang/src/syntax/declarative_part.rs | 6 +- vhdl_lang/src/syntax/design_unit.rs | 12 +-- vhdl_lang/src/syntax/expression.rs | 22 ++-- vhdl_lang/src/syntax/interface_declaration.rs | 32 +++--- vhdl_lang/src/syntax/names.rs | 32 +++--- vhdl_lang/src/syntax/object_declaration.rs | 12 +-- vhdl_lang/src/syntax/range.rs | 12 +-- vhdl_lang/src/syntax/sequential_statement.rs | 50 ++++----- vhdl_lang/src/syntax/subprogram.rs | 14 +-- vhdl_lang/src/syntax/subtype_indication.rs | 14 +-- vhdl_lang/src/syntax/test.rs | 36 +++---- vhdl_lang/src/syntax/tokens.rs | 2 + .../src/syntax/tokens/base_tokenstream.rs | 99 +++++++++++++++++ vhdl_lang/src/syntax/tokens/tokenstream.rs | 100 +----------------- vhdl_lang/src/syntax/type_declaration.rs | 18 ++-- vhdl_lang/src/syntax/waveform.rs | 6 +- 23 files changed, 285 insertions(+), 278 deletions(-) create mode 100644 vhdl_lang/src/syntax/tokens/base_tokenstream.rs diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index 28aa6dc0..1b6e278c 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -8,10 +8,10 @@ use super::common::ParseResult; use super::names::{parse_designator, parse_name}; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast::{AliasDeclaration, WithDecl}; -pub fn parse_alias_declaration(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_alias_declaration(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Alias)?; let designator = WithDecl::new(parse_designator(stream)?); let subtype_indication = { diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index 595c4126..a6901cb0 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -8,13 +8,13 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_type_mark; use super::subprogram::parse_signature; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast::{ Attribute, AttributeDeclaration, AttributeSpecification, Designator, EntityClass, EntityName, EntityTag, WithRef, }; -fn parse_entity_class(stream: &BaseTokenStream) -> ParseResult { +fn parse_entity_class(stream: &dyn TokenStream) -> ParseResult { Ok(expect_token!(stream, token, Entity => EntityClass::Entity, Architecture => EntityClass::Architecture, @@ -31,7 +31,7 @@ fn parse_entity_class(stream: &BaseTokenStream) -> ParseResult { )) } -pub fn parse_entity_name_list(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_entity_name_list(stream: &dyn TokenStream) -> ParseResult> { Ok(expect_token!(stream, token, Identifier | StringLiteral => { let mut entity_name_list = Vec::new(); @@ -73,7 +73,7 @@ pub fn parse_entity_name_list(stream: &BaseTokenStream) -> ParseResult ParseResult> { +pub fn parse_attribute(stream: &dyn TokenStream) -> ParseResult> { stream.expect_kind(Attribute)?; let ident = stream.expect_ident()?; Ok(expect_token!(stream, token, diff --git a/vhdl_lang/src/syntax/common.rs b/vhdl_lang/src/syntax/common.rs index 311cb9f2..82af91e8 100644 --- a/vhdl_lang/src/syntax/common.rs +++ b/vhdl_lang/src/syntax/common.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{BaseTokenStream, Kind, TokenStream}; +use super::tokens::{Kind, TokenStream}; use crate::ast::Ident; use crate::data::Diagnostic; use crate::data::DiagnosticHandler; @@ -13,12 +13,12 @@ use crate::SrcPos; /// Parse optional part followed by optional keyword pub fn parse_optional( - stream: &BaseTokenStream, + stream: &dyn TokenStream, keyword: Kind, parse_fun: F, ) -> ParseResult> where - F: FnOnce(&BaseTokenStream) -> ParseResult, + F: FnOnce(&dyn TokenStream) -> ParseResult, { let optional = { if stream.skip_if_kind(keyword) { diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index 5038ef1e..96b05e8b 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -7,13 +7,13 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::interface_declaration::{parse_generic_interface_list, parse_port_interface_list}; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast::WithDecl; use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; use crate::data::{Diagnostic, DiagnosticHandler}; pub fn parse_optional_generic_list( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { let mut list = None; @@ -38,7 +38,7 @@ pub fn parse_optional_generic_list( } pub fn parse_optional_port_list( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { let mut list = None; @@ -72,7 +72,7 @@ pub fn parse_optional_port_list( } pub fn parse_component_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Component)?; diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index fe9a116a..87f808d5 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -19,14 +19,14 @@ use super::sequential_statement::{ parse_assert_statement, parse_labeled_sequential_statements, parse_selection, parse_signal_assignment_right_hand, parse_target, }; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; /// LRM 11.2 Block statement pub fn parse_block_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -62,7 +62,7 @@ pub fn parse_block_statement( } fn parse_block_header( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut generic_clause = None; @@ -156,7 +156,7 @@ fn parse_block_header( /// LRM 11.3 Process statement pub fn parse_process_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, postponed: bool, diagnostics: &mut dyn DiagnosticHandler, @@ -252,7 +252,7 @@ fn to_procedure_call( /// Assume target and <= is parsed already fn parse_assignment_known_target( - stream: &BaseTokenStream, + stream: &dyn TokenStream, target: WithPos, ) -> ParseResult { // @TODO postponed @@ -272,7 +272,7 @@ fn parse_assignment_known_target( } fn parse_assignment_or_procedure_call( - stream: &BaseTokenStream, + stream: &dyn TokenStream, target: WithPos, ) -> ParseResult { expect_token!(stream, token, @@ -285,7 +285,7 @@ fn parse_assignment_or_procedure_call( } fn parse_selected_signal_assignment( - stream: &BaseTokenStream, + stream: &dyn TokenStream, postponed: bool, ) -> ParseResult { stream.expect_kind(With)?; @@ -307,7 +307,7 @@ fn parse_selected_signal_assignment( } pub fn parse_concurrent_assert_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, postponed: bool, ) -> ParseResult { Ok(ConcurrentAssertStatement { @@ -318,7 +318,7 @@ pub fn parse_concurrent_assert_statement( #[allow(clippy::type_complexity)] pub fn parse_generic_and_port_map( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult<( Option>, Option>, @@ -344,7 +344,7 @@ pub fn parse_generic_and_port_map( } pub fn parse_instantiation_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, unit: InstantiatedUnit, ) -> ParseResult { let (generic_map, port_map) = parse_generic_and_port_map(stream)?; @@ -359,7 +359,7 @@ pub fn parse_instantiation_statement( } fn parse_optional_declarative_part( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { if is_declarative_part(stream, true)? { @@ -372,7 +372,7 @@ fn parse_optional_declarative_part( } fn parse_generate_body( - stream: &BaseTokenStream, + stream: &dyn TokenStream, alternative_label: Option>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -409,7 +409,7 @@ fn parse_generate_body( /// 11.8 Generate statements fn parse_for_generate_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -434,7 +434,7 @@ fn parse_for_generate_statement( /// 11.8 Generate statements fn parse_if_generate_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -504,7 +504,7 @@ fn parse_if_generate_statement( /// 11.8 Generate statements fn parse_case_generate_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -554,7 +554,7 @@ fn parse_case_generate_statement( } pub fn parse_concurrent_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -640,7 +640,7 @@ pub fn parse_concurrent_statement( } pub fn parse_labeled_concurrent_statements( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut statements = Vec::new(); @@ -658,7 +658,7 @@ pub fn parse_labeled_concurrent_statements( } pub fn parse_labeled_concurrent_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let start = stream.peek_expect()?; diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index 7e0d1a2f..1859f075 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -9,12 +9,12 @@ use super::common::ParseResult; use super::concurrent_statement::parse_generic_and_port_map; use super::context::parse_use_clause; use super::names::{parse_name, parse_selected_name}; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; /// LRM 7.3.2.2 -fn parse_entity_aspect(stream: &BaseTokenStream) -> ParseResult { +fn parse_entity_aspect(stream: &dyn TokenStream) -> ParseResult { let entity_aspect = expect_token!( stream, token, @@ -39,7 +39,7 @@ fn parse_entity_aspect(stream: &BaseTokenStream) -> ParseResult { fn parse_binding_indication_known_entity_aspect( entity_aspect: Option, - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult { let (generic_map, port_map) = parse_generic_and_port_map(stream)?; @@ -52,7 +52,7 @@ fn parse_binding_indication_known_entity_aspect( } /// LRM 7.3.2 -fn parse_binding_indication(stream: &BaseTokenStream) -> ParseResult { +fn parse_binding_indication(stream: &dyn TokenStream) -> ParseResult { let entity_aspect = if stream.skip_if_kind(Use) { Some(parse_entity_aspect(stream)?) } else { @@ -62,7 +62,7 @@ fn parse_binding_indication(stream: &BaseTokenStream) -> ParseResult ParseResult { @@ -116,7 +116,7 @@ enum ComponentSpecificationOrName { } fn parse_component_specification_or_name( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult { peek_token!( stream, token, @@ -177,7 +177,7 @@ fn parse_component_specification_or_name( } fn parse_configuration_item_known_keyword( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { match parse_component_specification_or_name(stream)? { @@ -193,7 +193,7 @@ fn parse_configuration_item_known_keyword( } fn parse_block_configuration_known_name( - stream: &BaseTokenStream, + stream: &dyn TokenStream, name: WithPos, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -224,7 +224,7 @@ fn parse_block_configuration_known_name( } fn parse_block_configuration_known_keyword( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let name = parse_name(stream)?; @@ -232,7 +232,7 @@ fn parse_block_configuration_known_keyword( } fn parse_vunit_binding_indication_list_known_keyword( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult> { let mut indications = Vec::new(); loop { @@ -265,7 +265,7 @@ fn parse_vunit_binding_indication_list_known_keyword( /// LRM 3.4 Configuration declaration pub fn parse_configuration_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Configuration)?; @@ -311,7 +311,7 @@ pub fn parse_configuration_declaration( /// LRM 7.3 Configuration Specification pub fn parse_configuration_specification( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult { stream.expect_kind(For)?; match parse_component_specification_or_name(stream)? { diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index 54496929..dfe3b284 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -7,12 +7,12 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::names::parse_name; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; /// LRM 13. Design units and their analysis -pub fn parse_library_clause(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_library_clause(stream: &dyn TokenStream) -> ParseResult> { let library_token = stream.expect_kind(Library)?; let mut name_list = Vec::with_capacity(1); loop { @@ -29,7 +29,7 @@ pub fn parse_library_clause(stream: &BaseTokenStream) -> ParseResult ParseResult> { +pub fn parse_use_clause(stream: &dyn TokenStream) -> ParseResult> { let use_token = stream.expect_kind(Use)?; let mut name_list = Vec::with_capacity(1); @@ -52,7 +52,7 @@ pub enum DeclarationOrReference { Reference(WithPos), } -pub fn parse_context_reference(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_context_reference(stream: &dyn TokenStream) -> ParseResult> { let context_token = stream.expect_kind(Context)?; let name = parse_name(stream)?; @@ -72,7 +72,7 @@ pub fn parse_context_reference(stream: &BaseTokenStream) -> ParseResult ParseResult { let context_token = stream.expect_kind(Context)?; diff --git a/vhdl_lang/src/syntax/declarative_part.rs b/vhdl_lang/src/syntax/declarative_part.rs index a5601fef..38576de4 100644 --- a/vhdl_lang/src/syntax/declarative_part.rs +++ b/vhdl_lang/src/syntax/declarative_part.rs @@ -18,7 +18,7 @@ use super::type_declaration::parse_type_declaration; use crate::ast::{ContextClause, Declaration, PackageInstantiation}; use crate::data::DiagnosticHandler; -pub fn parse_package_instantiation(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_package_instantiation(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Package)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -43,7 +43,7 @@ pub fn parse_package_instantiation(stream: &BaseTokenStream) -> ParseResult ParseResult { +pub fn is_declarative_part(stream: &dyn TokenStream, begin_is_end: bool) -> ParseResult { Ok(check_declarative_part(stream.peek_expect()?, !begin_is_end, begin_is_end).is_ok()) } @@ -65,7 +65,7 @@ fn check_declarative_part(token: &Token, may_end: bool, may_begin: bool) -> Pars } pub fn parse_declarative_part( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut declarations: Vec = Vec::new(); diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index beb8807b..740a5f6c 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -4,7 +4,7 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use super::common::check_end_identifier_mismatch; use super::common::ParseResult; @@ -22,7 +22,7 @@ use crate::data::*; /// Parse an entity declaration, token is initial entity token /// If a parse error occurs the stream is consumed until and end entity pub fn parse_entity_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Entity)?; @@ -57,7 +57,7 @@ pub fn parse_entity_declaration( /// LRM 3.3.1 pub fn parse_architecture_body( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Architecture)?; @@ -88,7 +88,7 @@ pub fn parse_architecture_body( /// LRM 4.7 Package declarations pub fn parse_package_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Package)?; @@ -120,7 +120,7 @@ pub fn parse_package_declaration( /// LRM 4.8 Package bodies pub fn parse_package_body( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Package)?; @@ -159,7 +159,7 @@ fn context_item_message(context_item: &ContextItem, message: impl AsRef) -> } pub fn parse_design_file( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut context_clause = vec![]; diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index ef8be7e1..8956c825 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -7,7 +7,7 @@ use super::common::ParseResult; use super::names::{parse_name, parse_type_mark}; use super::subtype_indication::parse_subtype_constraint; -use super::tokens::{BaseTokenStream, Kind, Kind::*, TokenStream}; +use super::tokens::{Kind, Kind::*, TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; @@ -142,7 +142,7 @@ fn kind_to_binary_op(kind: Kind) -> Option<(Operator, usize)> { } pub fn parse_aggregate_initial_choices( - stream: &BaseTokenStream, + stream: &dyn TokenStream, choices: Vec>, ) -> ParseResult>> { let mut choices = choices; @@ -191,7 +191,7 @@ pub fn parse_aggregate_initial_choices( } } -pub fn parse_aggregate(stream: &BaseTokenStream) -> ParseResult>> { +pub fn parse_aggregate(stream: &dyn TokenStream) -> ParseResult>> { stream.expect_kind(LeftPar)?; if let Some(token) = stream.pop_if_kind(RightPar) { return Ok(WithPos::from(Vec::new(), token.pos.clone())); @@ -201,7 +201,7 @@ pub fn parse_aggregate(stream: &BaseTokenStream) -> ParseResult, direction: Direction, ) -> ParseResult> { @@ -217,7 +217,7 @@ fn parse_half_range( Ok(WithPos::new(range, pos)) } -fn parse_choice(stream: &BaseTokenStream) -> ParseResult> { +fn parse_choice(stream: &dyn TokenStream) -> ParseResult> { if let Some(token) = stream.pop_if_kind(Others) { return Ok(WithPos::new(Choice::Others, token.pos.clone())); } @@ -234,7 +234,7 @@ fn parse_choice(stream: &BaseTokenStream) -> ParseResult> { } } -pub fn parse_choices(stream: &BaseTokenStream) -> ParseResult>> { +pub fn parse_choices(stream: &dyn TokenStream) -> ParseResult>> { let mut choices = Vec::new(); loop { choices.push(parse_choice(stream)?); @@ -247,7 +247,7 @@ pub fn parse_choices(stream: &BaseTokenStream) -> ParseResult ParseResult> { +fn parse_allocator(stream: &dyn TokenStream) -> ParseResult> { stream.expect_kind(New)?; let type_mark = parse_type_mark(stream)?; @@ -318,7 +318,7 @@ fn name_to_selected_name(name: Name) -> Option { } } -fn parse_expression_or_aggregate(stream: &BaseTokenStream) -> ParseResult> { +fn parse_expression_or_aggregate(stream: &dyn TokenStream) -> ParseResult> { let mut choices = parse_choices(stream)?; if choices.len() == 1 @@ -369,7 +369,7 @@ fn parse_expression_or_aggregate(stream: &BaseTokenStream) -> ParseResult ParseResult> { +fn parse_primary(stream: &dyn TokenStream) -> ParseResult> { let token = stream.peek_expect()?; match token.kind { Identifier | LtLt => { @@ -479,7 +479,7 @@ fn parse_primary(stream: &BaseTokenStream) -> ParseResult> { } } -fn parse_expr(stream: &BaseTokenStream, min_precedence: usize) -> ParseResult> { +fn parse_expr(stream: &dyn TokenStream, min_precedence: usize) -> ParseResult> { let mut lhs = parse_primary(stream)?; while let Some(token) = stream.peek() { if token.kind == RightPar { @@ -524,7 +524,7 @@ fn parse_expr(stream: &BaseTokenStream, min_precedence: usize) -> ParseResult ParseResult> { +pub fn parse_expression(stream: &dyn TokenStream) -> ParseResult> { let state = stream.state(); parse_expr(stream, 0).map_err(|err| { stream.set_state(state); diff --git a/vhdl_lang/src/syntax/interface_declaration.rs b/vhdl_lang/src/syntax/interface_declaration.rs index f87c5af7..41c63399 100644 --- a/vhdl_lang/src/syntax/interface_declaration.rs +++ b/vhdl_lang/src/syntax/interface_declaration.rs @@ -14,7 +14,7 @@ use super::tokens::{Kind::*, *}; use crate::ast::*; use crate::data::*; -fn parse_optional_mode(stream: &BaseTokenStream) -> ParseResult>> { +fn parse_optional_mode(stream: &dyn TokenStream) -> ParseResult>> { let token = stream.peek_expect()?; let mode = match token.kind { In => Mode::In, @@ -37,7 +37,7 @@ fn unexpected_object_class_kind(list_type: InterfaceType, token: &Token) -> Diag } fn parse_optional_object_class( - stream: &BaseTokenStream, + stream: &dyn TokenStream, list_type: InterfaceType, ) -> ParseResult>> { let token = stream.peek_expect()?; @@ -54,7 +54,7 @@ fn parse_optional_object_class( } fn parse_interface_file_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult> { let file_objects = parse_file_declaration_no_semi(stream)?; for file_object in file_objects.iter() { @@ -84,7 +84,7 @@ fn parse_interface_file_declaration( } fn parse_interface_object_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, list_type: InterfaceType, ) -> ParseResult> { let explicit_object_class = parse_optional_object_class(stream, list_type)?; @@ -158,7 +158,7 @@ fn parse_interface_object_declaration( .collect()) } -fn parse_subprogram_default(stream: &BaseTokenStream) -> ParseResult> { +fn parse_subprogram_default(stream: &dyn TokenStream) -> ParseResult> { if stream.skip_if_kind(Is) { let default = { peek_token!( @@ -177,7 +177,7 @@ fn parse_subprogram_default(stream: &BaseTokenStream) -> ParseResult ParseResult { +fn parse_interface_package(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Package)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -212,7 +212,7 @@ fn parse_interface_package(stream: &BaseTokenStream) -> ParseResult ParseResult> { @@ -241,7 +241,7 @@ fn parse_interface_declaration( /// Parse ; separator in generic or port lists. /// Expect ; for all but the last item -fn parse_semicolon_separator(stream: &BaseTokenStream) -> ParseResult<()> { +fn parse_semicolon_separator(stream: &dyn TokenStream) -> ParseResult<()> { peek_token!( stream, token, SemiColon => { @@ -269,7 +269,7 @@ fn is_sync_kind(list_type: InterfaceType, kind: Kind) -> bool { } fn parse_interface_list( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, list_type: InterfaceType, ) -> ParseResult> { @@ -335,21 +335,21 @@ fn parse_interface_list( } pub fn parse_generic_interface_list( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Generic) } pub fn parse_port_interface_list( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Port) } pub fn parse_parameter_interface_list( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Parameter) @@ -357,7 +357,7 @@ pub fn parse_parameter_interface_list( #[cfg(test)] fn parse_one_interface_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, list_type: InterfaceType, ) -> ParseResult { let mut diagnostics = Vec::new(); @@ -370,17 +370,17 @@ fn parse_one_interface_declaration( } #[cfg(test)] -pub fn parse_parameter(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_parameter(stream: &dyn TokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Parameter) } #[cfg(test)] -pub fn parse_port(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_port(stream: &dyn TokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Port) } #[cfg(test)] -pub fn parse_generic(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_generic(stream: &dyn TokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Generic) } diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index c04bacfb..27d95af1 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -9,12 +9,12 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::subprogram::parse_signature; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; -pub fn parse_designator(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_designator(stream: &dyn TokenStream) -> ParseResult> { Ok(expect_token!( stream, token, @@ -24,7 +24,7 @@ pub fn parse_designator(stream: &BaseTokenStream) -> ParseResult ParseResult> { +pub fn parse_selected_name(stream: &dyn TokenStream) -> ParseResult> { let mut name = parse_designator(stream)? .into_ref() .map_into(SelectedName::Designator); @@ -39,13 +39,13 @@ pub fn parse_selected_name(stream: &BaseTokenStream) -> ParseResult ParseResult> { +pub fn parse_type_mark(stream: &dyn TokenStream) -> ParseResult> { let name = parse_selected_name(stream)?; parse_type_mark_starting_with_name(stream, name) } pub fn parse_type_mark_starting_with_name( - stream: &BaseTokenStream, + stream: &dyn TokenStream, name: WithPos, ) -> ParseResult> { let state = stream.state(); @@ -96,7 +96,7 @@ pub fn expression_to_ident(name: WithPos) -> ParseResult { to_simple_name(name) } -pub fn parse_identifier_list(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_identifier_list(stream: &dyn TokenStream) -> ParseResult> { let mut idents = Vec::new(); loop { idents.push(stream.expect_ident()?); @@ -152,7 +152,7 @@ fn assoc_to_expression(assoc: AssociationElement) -> ParseResult ParseResult> { +fn parse_actual_part(stream: &dyn TokenStream) -> ParseResult> { if let Some(token) = stream.pop_if_kind(Open) { Ok(WithPos::from(ActualPart::Open, token.pos.clone())) } else { @@ -160,7 +160,7 @@ fn parse_actual_part(stream: &BaseTokenStream) -> ParseResult ParseResult { +fn parse_association_element(stream: &dyn TokenStream) -> ParseResult { let actual = parse_actual_part(stream)?; if stream.skip_if_kind(RightArrow) { Ok(AssociationElement { @@ -175,13 +175,13 @@ fn parse_association_element(stream: &BaseTokenStream) -> ParseResult ParseResult> { +pub fn parse_association_list(stream: &dyn TokenStream) -> ParseResult> { stream.expect_kind(LeftPar)?; parse_association_list_no_leftpar(stream) } pub fn parse_association_list_no_leftpar( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult> { let mut association_elements = Vec::with_capacity(1); loop { @@ -198,7 +198,7 @@ pub fn parse_association_list_no_leftpar( } fn parse_function_call( - stream: &BaseTokenStream, + stream: &dyn TokenStream, prefix: WithPos, first: AssociationElement, ) -> ParseResult> { @@ -225,7 +225,7 @@ fn parse_function_call( } fn parse_attribute_name( - stream: &BaseTokenStream, + stream: &dyn TokenStream, name: WithPos, signature: Option>, ) -> ParseResult> { @@ -257,7 +257,7 @@ enum DesignatorOrAll { All, } -fn parse_suffix(stream: &BaseTokenStream) -> ParseResult> { +fn parse_suffix(stream: &dyn TokenStream) -> ParseResult> { let name = { expect_token!( stream, @@ -274,7 +274,7 @@ fn parse_suffix(stream: &BaseTokenStream) -> ParseResult> -fn parse_inner_external_name(stream: &BaseTokenStream) -> ParseResult { +fn parse_inner_external_name(stream: &dyn TokenStream) -> ParseResult { let token = stream.peek_expect()?; let class = try_init_token_kind!( token, @@ -327,7 +327,7 @@ fn parse_inner_external_name(stream: &BaseTokenStream) -> ParseResult ParseResult> { +fn _parse_name(stream: &dyn TokenStream) -> ParseResult> { let mut name = { if let Some(token) = stream.pop_if_kind(LtLt) { let external_name = Name::External(Box::new(parse_inner_external_name(stream)?)); @@ -472,7 +472,7 @@ pub fn into_range(assoc: AssociationElement) -> Result ParseResult> { +pub fn parse_name(stream: &dyn TokenStream) -> ParseResult> { let state = stream.state(); _parse_name(stream).map_err(|err| { stream.set_state(state); diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index ddfc6b59..ffef4342 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -8,13 +8,13 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_identifier_list; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; /// LRM 6.4.2 Object Declarations use crate::ast::*; use crate::data::WithPos; pub fn parse_optional_assignment( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult>> { if stream.pop_if_kind(ColonEq).is_some() { let expr = parse_expression(stream)?; @@ -25,7 +25,7 @@ pub fn parse_optional_assignment( } fn parse_object_declaration_kind( - stream: &BaseTokenStream, + stream: &dyn TokenStream, class: ObjectClass, ) -> ParseResult> { match class { @@ -60,7 +60,7 @@ fn parse_object_declaration_kind( .collect()) } -pub fn parse_object_declaration(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_object_declaration(stream: &dyn TokenStream) -> ParseResult> { let token = stream.peek_expect()?; let result = try_init_token_kind!( token, @@ -76,7 +76,7 @@ pub fn parse_object_declaration(stream: &BaseTokenStream) -> ParseResult ParseResult> { stream.expect_kind(File)?; let idents = parse_identifier_list(stream)?; @@ -110,7 +110,7 @@ pub fn parse_file_declaration_no_semi( .collect()) } -pub fn parse_file_declaration(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_file_declaration(stream: &dyn TokenStream) -> ParseResult> { let result = parse_file_declaration_no_semi(stream)?; stream.expect_kind(SemiColon)?; Ok(result) diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index 0921e8d9..b494247d 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -8,12 +8,12 @@ use super::common::parse_optional; use super::common::ParseResult; use super::expression::name_to_type_mark; use super::expression::parse_expression; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; -pub fn parse_direction(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_direction(stream: &dyn TokenStream) -> ParseResult { Ok(expect_token!( stream, token, To => Direction::Ascending, @@ -26,7 +26,7 @@ enum NameOrRange { Range(WithPos), } -fn parse_name_or_range(stream: &BaseTokenStream) -> ParseResult { +fn parse_name_or_range(stream: &dyn TokenStream) -> ParseResult { let expr = parse_expression(stream)?; match stream.peek_kind() { @@ -72,14 +72,14 @@ fn parse_name_or_range(stream: &BaseTokenStream) -> ParseResult { /// {selected_name}'range /// {selected_name}'reverse_range /// 2. {expr} to|downto {expr} -pub fn parse_range(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_range(stream: &dyn TokenStream) -> ParseResult> { match parse_name_or_range(stream)? { NameOrRange::Range(range) => Ok(range), NameOrRange::Name(name) => Err(Diagnostic::error(&name, "Expected range")), } } -pub fn parse_discrete_range(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_discrete_range(stream: &dyn TokenStream) -> ParseResult { match parse_name_or_range(stream) { Ok(NameOrRange::Range(range)) => Ok(DiscreteRange::Range(range.item)), Ok(NameOrRange::Name(name)) => { @@ -91,7 +91,7 @@ pub fn parse_discrete_range(stream: &BaseTokenStream) -> ParseResult ParseResult { +pub fn parse_array_index_constraint(stream: &dyn TokenStream) -> ParseResult { match parse_name_or_range(stream) { Ok(NameOrRange::Range(range)) => Ok(ArrayIndex::Discrete(DiscreteRange::Range(range.item))), Ok(NameOrRange::Name(name)) => { diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index 4500eb19..25da86cf 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -10,14 +10,14 @@ use super::expression::parse_aggregate; use super::expression::{parse_choices, parse_expression}; use super::names::parse_name; use super::range::parse_discrete_range; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; use crate::syntax::common::check_label_identifier_mismatch; /// LRM 10.2 Wait statement -fn parse_wait_statement(stream: &BaseTokenStream) -> ParseResult { +fn parse_wait_statement(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Wait)?; let mut sensitivity_clause = vec![]; if stream.skip_if_kind(On) { @@ -41,7 +41,7 @@ fn parse_wait_statement(stream: &BaseTokenStream) -> ParseResult } /// LRM 10.3 Assertion statement -pub fn parse_assert_statement(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_assert_statement(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Assert)?; let condition = parse_expression(stream)?; let report = parse_optional(stream, Report, parse_expression)?; @@ -56,7 +56,7 @@ pub fn parse_assert_statement(stream: &BaseTokenStream) -> ParseResult ParseResult { +fn parse_report_statement(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Report)?; let report = parse_expression(stream)?; let severity = parse_optional(stream, Severity, parse_expression)?; @@ -66,7 +66,7 @@ fn parse_report_statement(stream: &BaseTokenStream) -> ParseResult ParseResult> { let mut statements = Vec::new(); @@ -85,7 +85,7 @@ pub fn parse_labeled_sequential_statements( /// LRM 10.8 If statement fn parse_if_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -146,7 +146,7 @@ fn parse_if_statement( /// LRM 10.9 Case statement fn parse_case_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -194,7 +194,7 @@ fn parse_case_statement( /// LRM 10.10 Loop statement fn parse_loop_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -236,7 +236,7 @@ fn parse_loop_statement( } /// LRM 10.11 Next statement -fn parse_next_statement(stream: &BaseTokenStream) -> ParseResult { +fn parse_next_statement(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Next)?; let loop_label = stream.pop_optional_ident(); let condition = parse_optional(stream, When, parse_expression)?; @@ -248,7 +248,7 @@ fn parse_next_statement(stream: &BaseTokenStream) -> ParseResult } /// LRM 10.12 Exit statement -fn parse_exit_statement(stream: &BaseTokenStream) -> ParseResult { +fn parse_exit_statement(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Exit)?; let loop_label = stream.pop_optional_ident(); let condition = parse_optional(stream, When, parse_expression)?; @@ -260,7 +260,7 @@ fn parse_exit_statement(stream: &BaseTokenStream) -> ParseResult } /// LRM 10.13 Return statement -fn parse_return_statement(stream: &BaseTokenStream) -> ParseResult { +fn parse_return_statement(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Return)?; let expression = { if stream.peek_kind() == Some(SemiColon) { @@ -275,24 +275,24 @@ fn parse_return_statement(stream: &BaseTokenStream) -> ParseResult ParseResult> { parse_assignment_right_hand(stream, parse_waveform) } /// LRM 10.6 Variable assignment statement fn parse_variable_assignment_right_hand( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult>> { parse_assignment_right_hand(stream, parse_expression) } fn parse_assignment_right_hand( - stream: &BaseTokenStream, + stream: &dyn TokenStream, parse_item: F, ) -> ParseResult> where - F: Fn(&BaseTokenStream) -> ParseResult, + F: Fn(&dyn TokenStream) -> ParseResult, { let item = parse_item(stream)?; @@ -310,12 +310,12 @@ where } fn parse_conditonals( - stream: &BaseTokenStream, + stream: &dyn TokenStream, initial_item: T, parse_item: F, ) -> ParseResult> where - F: Fn(&BaseTokenStream) -> ParseResult, + F: Fn(&dyn TokenStream) -> ParseResult, { let condition = parse_expression(stream)?; let cond_expr = Conditional { @@ -362,12 +362,12 @@ where } pub fn parse_selection( - stream: &BaseTokenStream, + stream: &dyn TokenStream, expression: WithPos, parse_item: F, ) -> ParseResult> where - F: Fn(&BaseTokenStream) -> ParseResult, + F: Fn(&dyn TokenStream) -> ParseResult, { let mut alternatives = Vec::with_capacity(2); @@ -391,7 +391,7 @@ where }) } -fn parse_optional_force_mode(stream: &BaseTokenStream) -> ParseResult> { +fn parse_optional_force_mode(stream: &dyn TokenStream) -> ParseResult> { let token = stream.peek_expect()?; let optional_force_mode = match token.kind { In => { @@ -409,7 +409,7 @@ fn parse_optional_force_mode(stream: &BaseTokenStream) -> ParseResult, ) -> ParseResult { Ok(expect_token!( @@ -472,7 +472,7 @@ fn parse_assignment_or_procedure_call( )) } -pub fn parse_target(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_target(stream: &dyn TokenStream) -> ParseResult> { if stream.next_kind_is(LeftPar) { Ok(parse_aggregate(stream)?.map_into(Target::Aggregate)) } else { @@ -480,7 +480,7 @@ pub fn parse_target(stream: &BaseTokenStream) -> ParseResult> { } } -fn parse_selected_assignment(stream: &BaseTokenStream) -> ParseResult { +fn parse_selected_assignment(stream: &dyn TokenStream) -> ParseResult { let expression = parse_expression(stream)?; stream.expect_kind(Select)?; let target = parse_target(stream)?; @@ -513,7 +513,7 @@ fn parse_selected_assignment(stream: &BaseTokenStream) -> ParseResult, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -551,7 +551,7 @@ fn parse_unlabeled_sequential_statement( } pub fn parse_sequential_statement( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let start = stream.peek_expect()?; diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index b16881dd..d958e496 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -9,11 +9,11 @@ use super::declarative_part::parse_declarative_part; use super::interface_declaration::parse_parameter_interface_list; use super::names::parse_type_mark; use super::sequential_statement::parse_labeled_sequential_statements; -use super::tokens::{kinds_error, BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{kinds_error, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; -pub fn parse_signature(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_signature(stream: &dyn TokenStream) -> ParseResult> { let left_square = stream.expect_kind(LeftSquare)?; let start_pos = &left_square.pos; let mut type_marks = Vec::new(); @@ -67,7 +67,7 @@ pub fn parse_signature(stream: &BaseTokenStream) -> ParseResult ParseResult> { +fn parse_designator(stream: &dyn TokenStream) -> ParseResult> { Ok(expect_token!( stream, token, @@ -77,7 +77,7 @@ fn parse_designator(stream: &BaseTokenStream) -> ParseResult ParseResult { let (is_function, is_pure) = { @@ -125,7 +125,7 @@ pub fn parse_subprogram_declaration_no_semi( } pub fn parse_subprogram_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let res = parse_subprogram_declaration_no_semi(stream, diagnostics); @@ -135,7 +135,7 @@ pub fn parse_subprogram_declaration( /// LRM 4.3 Subprogram bodies pub fn parse_subprogram_body( - stream: &BaseTokenStream, + stream: &dyn TokenStream, specification: SubprogramDeclaration, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -173,7 +173,7 @@ pub fn parse_subprogram_body( } pub fn parse_subprogram( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let specification = parse_subprogram_declaration_no_semi(stream, diagnostics)?; diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index dbd4a2bc..fb10a491 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -7,19 +7,19 @@ use super::common::ParseResult; use super::names::{parse_selected_name, parse_type_mark, parse_type_mark_starting_with_name}; use super::range::{parse_discrete_range, parse_range}; -use super::tokens::{kinds_error, BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{kinds_error, Kind::*, TokenStream}; /// LRM 6.3 Subtype declarations use crate::ast::*; use crate::data::{SrcPos, WithPos}; -fn parse_record_element_constraint(stream: &BaseTokenStream) -> ParseResult { +fn parse_record_element_constraint(stream: &dyn TokenStream) -> ParseResult { let ident = stream.expect_ident()?; let constraint = Box::new(parse_composite_constraint(stream)?); Ok(ElementConstraint { ident, constraint }) } fn parse_array_constraint( - stream: &BaseTokenStream, + stream: &dyn TokenStream, leftpar_pos: SrcPos, // Open is None initial: Option, @@ -52,7 +52,7 @@ fn parse_array_constraint( )) } -fn parse_composite_constraint(stream: &BaseTokenStream) -> ParseResult> { +fn parse_composite_constraint(stream: &dyn TokenStream) -> ParseResult> { // There is no finite lookahead that can differentiate // between array and record element constraint let leftpar_pos = stream.expect_kind(LeftPar)?.pos.clone(); @@ -103,7 +103,7 @@ fn parse_composite_constraint(stream: &BaseTokenStream) -> ParseResult ParseResult>> { if let Some(token) = stream.peek() { let constraint = match token.kind { @@ -125,7 +125,7 @@ pub fn parse_subtype_constraint( } pub fn parse_element_resolution_indication( - stream: &BaseTokenStream, + stream: &dyn TokenStream, ) -> ParseResult { stream.expect_kind(LeftPar)?; @@ -178,7 +178,7 @@ pub fn parse_element_resolution_indication( )) } -pub fn parse_subtype_indication(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_subtype_indication(stream: &dyn TokenStream) -> ParseResult { let (resolution, type_mark) = { if stream.peek_kind() == Some(LeftPar) { let resolution = parse_element_resolution_indication(stream)?; diff --git a/vhdl_lang/src/syntax/test.rs b/vhdl_lang/src/syntax/test.rs index e2a9ef70..e767426d 100644 --- a/vhdl_lang/src/syntax/test.rs +++ b/vhdl_lang/src/syntax/test.rs @@ -21,7 +21,7 @@ use super::range::{parse_discrete_range, parse_range}; use super::sequential_statement::parse_sequential_statement; use super::subprogram::{parse_signature, parse_subprogram_declaration_no_semi}; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Comment, Kind, Symbols, Token, Tokenizer}; +use super::tokens::{TokenStream, Comment, Kind, Symbols, Token, Tokenizer}; use super::type_declaration::parse_type_declaration; use super::waveform::parse_waveform; use crate::ast; @@ -197,7 +197,7 @@ impl Code { /// Helper method to run lower level parsing function at specific substring pub fn parse(&self, parse_fun: F) -> R where - F: FnOnce(&BaseTokenStream) -> R, + F: FnOnce(&dyn TokenStream) -> R, { let contents = self.pos.source.contents(); let source = Source::from_contents( @@ -215,7 +215,7 @@ impl Code { /// Expect Ok() value pub fn parse_ok(&self, parse_fun: F) -> R where - F: FnOnce(&BaseTokenStream) -> ParseResult, + F: FnOnce(&dyn TokenStream) -> ParseResult, { match self.parse(parse_fun) { Ok(res) => res, @@ -227,7 +227,7 @@ impl Code { pub fn with_partial_stream(&self, parse_fun: F) -> R where - F: FnOnce(&BaseTokenStream) -> R, + F: FnOnce(&dyn TokenStream) -> R, { let contents = self.pos.source.contents(); let reader = ContentReader::new(&contents); @@ -239,9 +239,9 @@ impl Code { pub fn with_stream(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&BaseTokenStream) -> ParseResult, + F: FnOnce(&dyn TokenStream) -> ParseResult, { - let parse_fun_eof = |stream: &BaseTokenStream| { + let parse_fun_eof = |stream: &dyn TokenStream| { let result = parse_fun(stream); match result { Err(err) => { @@ -265,9 +265,9 @@ impl Code { pub fn with_stream_err(&self, parse_fun: F) -> Diagnostic where R: Debug, - F: FnOnce(&BaseTokenStream) -> ParseResult, + F: FnOnce(&dyn TokenStream) -> ParseResult, { - let parse_fun_eof = |stream: &BaseTokenStream| { + let parse_fun_eof = |stream: &dyn TokenStream| { let result = parse_fun(stream); match result { Err(err) => { @@ -289,29 +289,29 @@ impl Code { pub fn with_partial_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> R, + F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> R, { let mut diagnostics = Vec::new(); let result = self - .with_partial_stream(|stream: &BaseTokenStream| parse_fun(stream, &mut diagnostics)); + .with_partial_stream(|stream: &dyn TokenStream| parse_fun(stream, &mut diagnostics)); (result, diagnostics) } pub fn with_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let mut diagnostics = Vec::new(); let result = - self.with_stream(|stream: &BaseTokenStream| parse_fun(stream, &mut diagnostics)); + self.with_stream(|stream: &dyn TokenStream| parse_fun(stream, &mut diagnostics)); (result, diagnostics) } pub fn with_stream_no_diagnostics(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let (result, diagnostics) = self.with_stream_diagnostics(parse_fun); check_no_diagnostics(&diagnostics); @@ -326,11 +326,11 @@ impl Code { } /// Helper to create a identifier at first occurence of name pub fn ident(&self) -> Ident { - self.parse_ok(|stream: &BaseTokenStream| stream.expect_ident()) + self.parse_ok(|stream: &dyn TokenStream| stream.expect_ident()) } pub fn decl_ident(&self) -> WithDecl { - WithDecl::new(self.parse_ok(|stream: &BaseTokenStream| stream.expect_ident())) + WithDecl::new(self.parse_ok(|stream: &dyn TokenStream| stream.expect_ident())) } pub fn designator(&self) -> WithPos { @@ -345,7 +345,7 @@ impl Code { } pub fn character(&self) -> WithPos { - self.parse_ok(|stream: &BaseTokenStream| { + self.parse_ok(|stream: &dyn TokenStream| { stream.expect_kind(Kind::Character)?.to_character_value() }) } @@ -436,7 +436,7 @@ impl Code { pub fn parse_ok_no_diagnostics(&self, parse_fun: F) -> R where - F: FnOnce(&BaseTokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let mut diagnostics = Vec::new(); let res = self.parse_ok(|stream| parse_fun(stream, &mut diagnostics)); @@ -528,7 +528,7 @@ fn substr_range(source: &Source, range: Range, substr: &str, occurence: usize) - } /// Fast forward tokenstream until position -fn forward(stream: &BaseTokenStream, start: Position) { +fn forward(stream: &dyn TokenStream, start: Position) { loop { let token = stream.peek_expect().unwrap(); if token.pos.start() >= start { diff --git a/vhdl_lang/src/syntax/tokens.rs b/vhdl_lang/src/syntax/tokens.rs index 2cc3e2a9..dd52accf 100644 --- a/vhdl_lang/src/syntax/tokens.rs +++ b/vhdl_lang/src/syntax/tokens.rs @@ -6,7 +6,9 @@ #[macro_use] mod tokenizer; +mod base_tokenstream; mod tokenstream; pub use tokenizer::*; pub use tokenstream::*; +pub use base_tokenstream::*; diff --git a/vhdl_lang/src/syntax/tokens/base_tokenstream.rs b/vhdl_lang/src/syntax/tokens/base_tokenstream.rs new file mode 100644 index 00000000..17066e44 --- /dev/null +++ b/vhdl_lang/src/syntax/tokens/base_tokenstream.rs @@ -0,0 +1,99 @@ +use super::tokenizer::Kind::*; +use super::tokenizer::*; +use crate::ast::{AttributeDesignator, RangeAttribute, TypeAttribute}; +use crate::data::{DiagnosticHandler, DiagnosticResult, WithPos}; +use crate::syntax::tokens::{TokenStream, TokenizationException}; +use crate::Diagnostic; +use std::cell::Cell; + +pub struct BaseTokenStream<'a> { + tokenizer: Tokenizer<'a>, + idx: Cell, + tokens: Vec, +} + +/// The token stream maintains a collection of tokens and a current state. +/// The state is an index into the vector of tokens and +impl<'a> BaseTokenStream<'a> { + pub fn new( + mut tokenizer: Tokenizer<'a>, + diagnostics: &mut dyn DiagnosticHandler, + ) -> BaseTokenStream<'a> { + let mut tokens = Vec::new(); + loop { + match tokenizer.pop() { + Ok(Some(token)) => tokens.push(token), + Ok(None) => break, + Err(err) => diagnostics.push(err), + } + } + BaseTokenStream { + tokenizer, + idx: Cell::new(0), + tokens, + } + } + + fn eof_error(&self) -> Diagnostic { + let end = self.tokenizer.source.contents().end(); + Diagnostic::error( + self.tokenizer.source.pos(end, end.next_char()), + "Unexpected EOF", + ) + } +} + +impl<'a> TokenStream for BaseTokenStream<'a> { + fn state(&self) -> usize { + self.idx.get() + } + + fn set_state(&self, state: usize) { + self.idx.replace(state); + } + + fn token_at(&self, state: usize) -> Option<&Token> { + self.tokens.get(state) + } + + fn state_of(&self, token: &Token) -> Option { + let base = self.tokens.as_ptr() as usize; + let ptr = (token as *const Token) as usize; + let idx = ptr.checked_sub(base)? / std::mem::size_of::(); + + if idx < self.tokens.len() { + Some(idx) + } else { + None + } + } + + fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic { + match exception { + TokenizationException::KindsError { pos, kinds } => kinds_error(pos, kinds), + TokenizationException::EofError { expectations } => { + let mut diagnostic = self.eof_error(); + if let Some(kinds) = expectations { + diagnostic = diagnostic.when(format!("expecting {}", kinds_str(kinds))); + } + diagnostic + } + } + } + + /// Expect identifier or subtype/range keywords + /// foo'subtype or foo'range + fn expect_attribute_designator(&self) -> DiagnosticResult> { + let des = expect_token!( + self, + token, + Identifier => { + let ident = token.to_identifier_value()?; + ident.map_into(|sym| self.tokenizer.attribute(sym)) + }, + Subtype => WithPos::new(AttributeDesignator::Type(TypeAttribute::Subtype), token.pos.clone()), + Range => WithPos::new(AttributeDesignator::Range(RangeAttribute::Range), token.pos.clone()) + ); + Ok(des) + } +} diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index 851339c6..cbca8ca2 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -4,11 +4,9 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use std::cell::Cell; - use super::tokenizer::Kind::*; use super::tokenizer::*; -use crate::ast::{AttributeDesignator, Ident, RangeAttribute, TypeAttribute}; +use crate::ast::{AttributeDesignator, Ident}; use crate::data::{DiagnosticHandler, DiagnosticResult, WithPos}; use crate::{Diagnostic, SrcPos}; @@ -182,102 +180,10 @@ pub enum TokenizationException<'a> { EofError { expectations: Option<&'a [Kind]> }, } -pub struct BaseTokenStream<'a> { - tokenizer: Tokenizer<'a>, - idx: Cell, - tokens: Vec, -} - -/// The token stream maintains a collection of tokens and a current state. -/// The state is an index into the vector of tokens and -impl<'a> BaseTokenStream<'a> { - pub fn new( - mut tokenizer: Tokenizer<'a>, - diagnostics: &mut dyn DiagnosticHandler, - ) -> BaseTokenStream<'a> { - let mut tokens = Vec::new(); - loop { - match tokenizer.pop() { - Ok(Some(token)) => tokens.push(token), - Ok(None) => break, - Err(err) => diagnostics.push(err), - } - } - BaseTokenStream { - tokenizer, - idx: Cell::new(0), - tokens, - } - } - - fn eof_error(&self) -> Diagnostic { - let end = self.tokenizer.source.contents().end(); - Diagnostic::error( - self.tokenizer.source.pos(end, end.next_char()), - "Unexpected EOF", - ) - } -} - -impl<'a> TokenStream for BaseTokenStream<'a> { - fn state(&self) -> usize { - self.idx.get() - } - - fn set_state(&self, state: usize) { - self.idx.replace(state); - } - - fn token_at(&self, state: usize) -> Option<&Token> { - self.tokens.get(state) - } - - fn state_of(&self, token: &Token) -> Option { - let base = self.tokens.as_ptr() as usize; - let ptr = (token as *const Token) as usize; - let idx = ptr.checked_sub(base)? / std::mem::size_of::(); - - if idx < self.tokens.len() { - Some(idx) - } else { - None - } - } - - fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic { - match exception { - TokenizationException::KindsError { pos, kinds } => kinds_error(pos, kinds), - TokenizationException::EofError { expectations } => { - let mut diagnostic = self.eof_error(); - if let Some(kinds) = expectations { - diagnostic = diagnostic.when(format!("expecting {}", kinds_str(kinds))); - } - diagnostic - } - } - } - - /// Expect identifier or subtype/range keywords - /// foo'subtype or foo'range - fn expect_attribute_designator(&self) -> DiagnosticResult> { - let des = expect_token!( - self, - token, - Identifier => { - let ident = token.to_identifier_value()?; - ident.map_into(|sym| self.tokenizer.attribute(sym)) - }, - Subtype => WithPos::new(AttributeDesignator::Type(TypeAttribute::Subtype), token.pos.clone()), - Range => WithPos::new(AttributeDesignator::Range(RangeAttribute::Range), token.pos.clone()) - ); - Ok(des) - } -} - pub trait Recover { fn or_recover_until( self, - stream: &BaseTokenStream, + stream: &dyn TokenStream, msgs: &mut dyn DiagnosticHandler, cond: fn(Kind) -> bool, ) -> DiagnosticResult; @@ -288,7 +194,7 @@ pub trait Recover { impl Recover for DiagnosticResult { fn or_recover_until( self, - stream: &BaseTokenStream, + stream: &dyn TokenStream, msgs: &mut dyn DiagnosticHandler, cond: fn(Kind) -> bool, ) -> DiagnosticResult { diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index c5bef4e9..5f7fcc4f 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -11,14 +11,14 @@ use super::names::parse_identifier_list; use super::range::{parse_array_index_constraint, parse_range}; use super::subprogram::parse_subprogram_declaration; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; use crate::ast::*; use crate::ast::{AbstractLiteral, Range}; use crate::data::DiagnosticHandler; use crate::syntax::names::parse_type_mark; /// LRM 5.2.2 Enumeration types -fn parse_enumeration_type_definition(stream: &BaseTokenStream) -> ParseResult { +fn parse_enumeration_type_definition(stream: &dyn TokenStream) -> ParseResult { let mut enum_literals = Vec::new(); loop { expect_token!(stream, @@ -45,7 +45,7 @@ fn parse_enumeration_type_definition(stream: &BaseTokenStream) -> ParseResult ParseResult> { +fn parse_array_index_constraints(stream: &dyn TokenStream) -> ParseResult> { stream.expect_kind(LeftPar)?; let mut indexes = Vec::new(); loop { @@ -61,7 +61,7 @@ fn parse_array_index_constraints(stream: &BaseTokenStream) -> ParseResult ParseResult { +fn parse_array_type_definition(stream: &dyn TokenStream) -> ParseResult { let index_constraints = parse_array_index_constraints(stream)?; stream.expect_kind(Of)?; let element_subtype = parse_subtype_indication(stream)?; @@ -71,7 +71,7 @@ fn parse_array_type_definition(stream: &BaseTokenStream) -> ParseResult ParseResult<(TypeDefinition, Option)> { let mut elem_decls = Vec::new(); @@ -96,7 +96,7 @@ fn parse_record_type_definition( } } -pub fn parse_subtype_declaration(stream: &BaseTokenStream) -> ParseResult { +pub fn parse_subtype_declaration(stream: &dyn TokenStream) -> ParseResult { stream.expect_kind(Subtype)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -111,7 +111,7 @@ pub fn parse_subtype_declaration(stream: &BaseTokenStream) -> ParseResult ParseResult<(ProtectedTypeDeclaration, Option)> { let mut items = Vec::new(); @@ -137,7 +137,7 @@ pub fn parse_protected_type_declaration( /// LRM 5.2.4 Physical types fn parse_physical_type_definition( - stream: &BaseTokenStream, + stream: &dyn TokenStream, range: Range, ) -> ParseResult<(TypeDefinition, Option)> { let primary_unit = WithDecl::new(stream.expect_ident()?); @@ -193,7 +193,7 @@ fn parse_physical_type_definition( /// LRM 6.2 pub fn parse_type_declaration( - stream: &BaseTokenStream, + stream: &dyn TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { peek_token!( diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 9b1e108b..0e8c0018 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -8,10 +8,10 @@ use crate::ast::{DelayMechanism, Waveform, WaveformElement}; use super::common::{parse_optional, ParseResult}; use super::expression::parse_expression; -use super::tokens::{BaseTokenStream, Kind::*, TokenStream}; +use super::tokens::{Kind::*, TokenStream}; /// LRM 10.5 Signal assignment statement -pub fn parse_delay_mechanism(stream: &BaseTokenStream) -> ParseResult> { +pub fn parse_delay_mechanism(stream: &dyn TokenStream) -> ParseResult> { let token = stream.peek_expect()?; match token.kind { Transport => { @@ -33,7 +33,7 @@ pub fn parse_delay_mechanism(stream: &BaseTokenStream) -> ParseResult ParseResult { +pub fn parse_waveform(stream: &dyn TokenStream) -> ParseResult { if stream.skip_if_kind(Unaffected) { return Ok(Waveform::Unaffected); } From 017fc4aee9674fd8cc26112785b2540e421c12c2 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Tue, 25 Jul 2023 21:00:14 +0200 Subject: [PATCH 11/31] Implement completion_tokenstream --- vhdl_lang/src/syntax/test.rs | 1 + vhdl_lang/src/syntax/tokens.rs | 1 + .../syntax/tokens/completion_tokenstream.rs | 36 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 vhdl_lang/src/syntax/tokens/completion_tokenstream.rs diff --git a/vhdl_lang/src/syntax/test.rs b/vhdl_lang/src/syntax/test.rs index e767426d..cb015833 100644 --- a/vhdl_lang/src/syntax/test.rs +++ b/vhdl_lang/src/syntax/test.rs @@ -34,6 +34,7 @@ use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hasher; use std::sync::Arc; +use crate::syntax::tokens::BaseTokenStream; pub struct CodeBuilder { pub symbols: Arc, diff --git a/vhdl_lang/src/syntax/tokens.rs b/vhdl_lang/src/syntax/tokens.rs index dd52accf..0063f9ad 100644 --- a/vhdl_lang/src/syntax/tokens.rs +++ b/vhdl_lang/src/syntax/tokens.rs @@ -8,6 +8,7 @@ mod tokenizer; mod base_tokenstream; mod tokenstream; +mod completion_tokenstream; pub use tokenizer::*; pub use tokenstream::*; diff --git a/vhdl_lang/src/syntax/tokens/completion_tokenstream.rs b/vhdl_lang/src/syntax/tokens/completion_tokenstream.rs new file mode 100644 index 00000000..5f858185 --- /dev/null +++ b/vhdl_lang/src/syntax/tokens/completion_tokenstream.rs @@ -0,0 +1,36 @@ +use crate::{Diagnostic, SrcPos}; +use crate::ast::AttributeDesignator; +use crate::data::{DiagnosticResult, WithPos}; +use crate::syntax::tokens::{BaseTokenStream, Token, TokenizationException, TokenStream}; + +struct CompletionTokenStream<'a> { + base: BaseTokenStream<'a>, + cursor: SrcPos, + suggestions: Vec, +} + +impl TokenStream for CompletionTokenStream { + fn state(&self) -> usize { + self.base.state() + } + + fn set_state(&self, state: usize) { + self.base.set_state(state) + } + + fn token_at(&self, state: usize) -> Option<&Token> { + self.base.token_at(state) + } + + fn state_of(&self, token: &Token) -> Option { + self.base.state_of(token) + } + + fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic { + self.base.handle_diagnostic(exception) + } + + fn expect_attribute_designator(&self) -> DiagnosticResult> { + self.base.expect_attribute_designator() + } +} From 18cf4cbd38b3380cd76656d91541f7cdc76e816b Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Wed, 9 Aug 2023 20:34:53 +0200 Subject: [PATCH 12/31] Use alternative strategy to enable completions --- Cargo.lock | 245 +++++++----------- vhdl_lang/src/analysis.rs | 2 + vhdl_lang/src/analysis/completion.rs | 155 +++++++++++ vhdl_lang/src/analysis/root.rs | 21 +- vhdl_lang/src/ast.rs | 21 ++ vhdl_lang/src/data/source.rs | 4 + vhdl_lang/src/syntax.rs | 2 +- vhdl_lang/src/syntax/test.rs | 4 +- vhdl_lang/src/syntax/tokens.rs | 3 +- .../src/syntax/tokens/base_tokenstream.rs | 145 +++++++++++ .../syntax/tokens/completion_tokenstream.rs | 36 --- vhdl_lang/src/syntax/tokens/tokenstream.rs | 148 +---------- vhdl_ls/src/vhdl_server.rs | 7 +- 13 files changed, 437 insertions(+), 356 deletions(-) create mode 100644 vhdl_lang/src/analysis/completion.rs delete mode 100644 vhdl_lang/src/syntax/tokens/completion_tokenstream.rs diff --git a/Cargo.lock b/Cargo.lock index 0f49dcdd..0813a076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,9 +86,12 @@ checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -98,9 +101,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.3.10" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" dependencies = [ "clap_builder", "clap_derive", @@ -109,9 +112,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.10" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ "anstream", "anstyle", @@ -121,14 +124,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -186,16 +189,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "diff" version = "0.1.13" @@ -230,9 +223,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "env_logger" @@ -249,15 +242,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -276,12 +269,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "fnv" @@ -329,9 +319,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "humantime" @@ -359,34 +349,14 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - [[package]] name = "is-terminal" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.1", + "rustix", "windows-sys", ] @@ -401,9 +371,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "libc" @@ -413,15 +383,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "lock_api" @@ -441,9 +405,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3711e4d6f491dc9edc0f1df80e204f38206775ac92c1241e89b79229a850bc00" +checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" dependencies = [ "crossbeam-channel", "log", @@ -453,9 +417,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.94.0" +version = "0.94.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" dependencies = [ "bitflags 1.3.2", "serde", @@ -495,15 +459,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - [[package]] name = "pad" version = "0.1.6" @@ -550,30 +505,28 @@ checksum = "268ad82d92622fb0a049ff14b01089b0f1bcd5c507fab44724394d328417348a" [[package]] name = "pretty_assertions" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "ctor", "diff", - "output_vt100", "yansi", ] [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -631,85 +584,83 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] -name = "regex-syntax" -version = "0.7.2" +name = "regex-automata" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] -name = "rustix" -version = "0.37.21" +name = "regex-syntax" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "rustix" -version = "0.38.1" +version = "0.38.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" +checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" dependencies = [ "bitflags 2.3.3", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys", "windows-sys", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.156" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.156" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -718,13 +669,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -738,9 +689,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "strsim" @@ -750,20 +701,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -772,15 +712,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.21", + "rustix", "windows-sys", ] @@ -795,22 +734,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -830,9 +769,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", @@ -851,9 +790,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ "indexmap", "serde", @@ -870,9 +809,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -909,7 +848,7 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "vhdl_lang" -version = "0.64.0" +version = "0.65.0" dependencies = [ "assert_matches", "clap", @@ -929,7 +868,7 @@ dependencies = [ [[package]] name = "vhdl_ls" -version = "0.64.0" +version = "0.65.0" dependencies = [ "clap", "env_logger", @@ -1049,9 +988,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" dependencies = [ "memchr", ] diff --git a/vhdl_lang/src/analysis.rs b/vhdl_lang/src/analysis.rs index 4c3353f5..48ce80c8 100644 --- a/vhdl_lang/src/analysis.rs +++ b/vhdl_lang/src/analysis.rs @@ -29,6 +29,8 @@ mod static_expression; mod target; mod visibility; +mod completion; + #[cfg(test)] mod tests; diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs new file mode 100644 index 00000000..d1f91c79 --- /dev/null +++ b/vhdl_lang/src/analysis/completion.rs @@ -0,0 +1,155 @@ +use std::default::Default; +use crate::analysis::DesignRoot; +use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, UnitKey}; +use crate::data::{ContentReader, Symbol}; +use crate::syntax::Kind::*; +use crate::syntax::{Symbols, Token, Tokenizer, Value}; +use crate::{Position, Source}; +use itertools::Itertools; + +macro_rules! kind { + ($kind: pat) => { + Token { kind: $kind, .. } + }; +} + +macro_rules! ident { + ($bind: pat) => { + Token { + kind: Identifier, + value: Value::Identifier($bind), + .. + } + }; +} + +fn tokenize_input(symbols: &Symbols, source: &Source, cursor: Position) -> Vec { + let contents = source.contents(); + // let symbols = Symbols::default(); + let mut tokenizer = Tokenizer::new(symbols, source, ContentReader::new(&contents)); + let mut tokens = Vec::new(); + loop { + match tokenizer.pop() { + Ok(Some(token)) => { + if token.pos.start() >= cursor { + break; + } + tokens.push(token); + } + Ok(None) => break, + Err(_) => return vec![], + } + } + tokens +} + +impl DesignRoot { + + /// helper function to list the name of all available libraries + fn list_all_libraries(&self) -> Vec { + self.available_libraries() + .map(|k| k.name().to_string()) + .collect() + } + + /// List the name of all primary units for a given library. + /// If the library is non-resolvable, list an empty vector + fn list_primaries_for_lib(&self, lib: &Symbol) -> Vec { + let Some(lib) = self.get_library_units(lib) else { return vec![]; }; + lib.keys() + .filter_map(|key| match key { + UnitKey::Primary(prim) => Some(prim.name().to_string()), + UnitKey::Secondary(_, _) => None, + }) + .collect() + } + + /// Lists all available declarations for a primary unit inside a given library + /// If the library does not exist or there is no primary unit with the given name for that library, + /// return an empty vector + fn list_available_declarations(&self, lib: &Symbol, primary_unit: &Symbol) -> Vec { + let Some(lib) = self.get_library_units(lib) else { return vec![]; }; + let Some(unit) = lib.get(&UnitKey::Primary(primary_unit.clone())) else { return vec![]; }; + let unit = unit.unit.get(); + match unit.unwrap().to_owned() { + AnyDesignUnit::Primary(AnyPrimaryUnit::Package(pkg)) => pkg + .decl + .iter() + .filter_map(|d| d.ident()) + .unique() + .chain(vec!["all".to_string()].into_iter()) + .collect_vec(), + _ => Vec::default(), + } + } + + pub fn list_completion_options(&self, source: &Source, cursor: Position) -> Vec { + let tokens = tokenize_input(&self.symbols, source, cursor); + let cursor_at_end = tokens.last().map(|tok| tok.pos.end() == cursor).unwrap_or(false); + + match &tokens[..] { + [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { + self.list_all_libraries() + } + [.., kind!(Use), ident!(library), kind!(Dot)] + | [.., kind!(Use), ident!(library), kind!(Dot), kind!(Identifier)] => { + self.list_primaries_for_lib(library) + } + [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot)] + | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { + self.list_available_declarations(library, selected) + }, + [.., kind!(Entity), kind!(Identifier)] => { + if cursor_at_end { + vec![] + } else { + vec!["is".to_string()] + } + }, + [.., kind!(Architecture), kind!(Identifier)] => { + if cursor_at_end { + vec![] + } else { + vec!["of".to_string()] + } + }, + _ => vec![], + } + } +} + +#[cfg(test)] +mod test { + use assert_matches::assert_matches; + use super::*; + use crate::analysis::completion::tokenize_input; + use crate::syntax::test::Code; + + #[test] + fn tokenizing_an_empty_input() { + let input = Code::new(""); + let tokens = tokenize_input(&input.symbols, input.source(), Position::new(0, 0)); + assert_eq!(tokens.len(), 0); + } + + #[test] + fn tokenizing_stops_at_the_cursors_position() { + let input = Code::new("entity my_ent is"); + // mid of `my_ent` + let mut cursor = Position::new(0, 11); + let tokens = tokenize_input(&input.symbols, input.source(), cursor); + assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier)]); + // end of `my_ent` + cursor = Position::new(0, 13); + let tokens = tokenize_input(&input.symbols, input.source(), cursor); + assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier)]); + // start of `is` + cursor = Position::new(0, 14); + let tokens = tokenize_input(&input.symbols, input.source(), cursor); + assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier)]); + // inside of `is` + cursor = Position::new(0, 15); + let tokens = tokenize_input(&input.symbols, input.source(), cursor); + assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier), kind!(Is)]); + } +} diff --git a/vhdl_lang/src/analysis/root.rs b/vhdl_lang/src/analysis/root.rs index 0b699c9c..03565278 100644 --- a/vhdl_lang/src/analysis/root.rs +++ b/vhdl_lang/src/analysis/root.rs @@ -322,6 +322,11 @@ impl DesignRoot { .map(|library| &library.units) } + /// Iterates over all available library symbols. + pub fn available_libraries(&self) -> impl Iterator { + self.libraries.keys() + } + pub(crate) fn get_design_entity<'a>( &'a self, library_name: &Symbol, @@ -431,12 +436,6 @@ impl DesignRoot { Vec::default() } - pub fn list_completion_options<'a>(&'a self, source: &Source, cursor: Position) -> Vec { - let mut searcher = SuggestionSearcher::new(self, cursor, source); - let _ = self.search(&mut searcher); - searcher.result - } - #[cfg(test)] pub fn search_reference_pos(&self, source: &Source, cursor: Position) -> Option { self.search_reference(source, cursor) @@ -1191,21 +1190,21 @@ package pkg is new gpkg generic map (const => foo); vec![ Diagnostic::error( code.s("pkg", 2), - "A primary unit has already been declared with name 'pkg' in library 'libname'" + "A primary unit has already been declared with name 'pkg' in library 'libname'", ).related(code.s("pkg", 1), "Previously defined here"), Diagnostic::error( code.s("entname", 2), - "A primary unit has already been declared with name 'entname' in library 'libname'" + "A primary unit has already been declared with name 'entname' in library 'libname'", ).related(code.s("entname", 1), "Previously defined here"), Diagnostic::error( code.s("pkg", 3), - "A primary unit has already been declared with name 'pkg' in library 'libname'" + "A primary unit has already been declared with name 'pkg' in library 'libname'", ).related(code.s("pkg", 1), "Previously defined here"), Diagnostic::error( code.s("pkg", 4), - "A primary unit has already been declared with name 'pkg' in library 'libname'" + "A primary unit has already been declared with name 'pkg' in library 'libname'", ).related(code.s("pkg", 1), "Previously defined here"), - ] + ], ); } diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index 1c285f01..fccc2425 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -757,6 +757,27 @@ pub enum Declaration { Configuration(ConfigurationSpecification), } +impl Declaration { + pub fn ident(&self) -> Option { + match self { + Declaration::Object(o) => Some(o.ident.tree.item.to_string()), + Declaration::File(f) => Some(f.ident.tree.item.to_string()), + Declaration::Type(t) => Some(t.ident.tree.item.to_string()), + Declaration::Component(c) => Some(c.ident.tree.item.to_string()), + Declaration::Attribute(a) => match a { + Attribute::Specification(spec) => Some(spec.ident.item.to_string()), + Attribute::Declaration(decl) => Some(decl.ident.tree.item.to_string()), + }, + Declaration::Alias(a) => Some(a.designator.to_string()), + Declaration::SubprogramDeclaration(decl) => Some(decl.subpgm_designator().to_string()), + Declaration::SubprogramBody(_) => None, + Declaration::Use(_) => None, + Declaration::Package(p) => Some(p.ident.to_string()), + Declaration::Configuration(_) => None, + } + } +} + /// LRM 10.2 Wait statement #[derive(PartialEq, Debug, Clone)] pub struct WaitStatement { diff --git a/vhdl_lang/src/data/source.rs b/vhdl_lang/src/data/source.rs index 4a38f477..f6ba18ef 100644 --- a/vhdl_lang/src/data/source.rs +++ b/vhdl_lang/src/data/source.rs @@ -237,6 +237,10 @@ impl Range { pub fn new(start: Position, end: Position) -> Range { Range { start, end } } + + pub fn contains(&self, position: Position) -> bool { + self.start <= position && self.end >= position + } } /// A lexical range within a specific source file. diff --git a/vhdl_lang/src/syntax.rs b/vhdl_lang/src/syntax.rs index 173a4ca2..aa82d908 100644 --- a/vhdl_lang/src/syntax.rs +++ b/vhdl_lang/src/syntax.rs @@ -32,4 +32,4 @@ mod waveform; pub mod test; pub use parser::{ParserResult, VHDLParser}; -pub use tokens::Symbols; +pub use tokens::*; diff --git a/vhdl_lang/src/syntax/test.rs b/vhdl_lang/src/syntax/test.rs index cb015833..fe00dcc8 100644 --- a/vhdl_lang/src/syntax/test.rs +++ b/vhdl_lang/src/syntax/test.rs @@ -21,20 +21,20 @@ use super::range::{parse_discrete_range, parse_range}; use super::sequential_statement::parse_sequential_statement; use super::subprogram::{parse_signature, parse_subprogram_declaration_no_semi}; use super::subtype_indication::parse_subtype_indication; -use super::tokens::{TokenStream, Comment, Kind, Symbols, Token, Tokenizer}; +use super::tokens::{Comment, Kind, Symbols, Token, TokenStream, Tokenizer}; use super::type_declaration::parse_type_declaration; use super::waveform::parse_waveform; use crate::ast; use crate::ast::*; use crate::data::Range; use crate::data::*; +use crate::syntax::tokens::BaseTokenStream; use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::Entry; use std::collections::HashMap; use std::fmt::Debug; use std::hash::Hasher; use std::sync::Arc; -use crate::syntax::tokens::BaseTokenStream; pub struct CodeBuilder { pub symbols: Arc, diff --git a/vhdl_lang/src/syntax/tokens.rs b/vhdl_lang/src/syntax/tokens.rs index 0063f9ad..48316815 100644 --- a/vhdl_lang/src/syntax/tokens.rs +++ b/vhdl_lang/src/syntax/tokens.rs @@ -8,8 +8,7 @@ mod tokenizer; mod base_tokenstream; mod tokenstream; -mod completion_tokenstream; +pub use base_tokenstream::*; pub use tokenizer::*; pub use tokenstream::*; -pub use base_tokenstream::*; diff --git a/vhdl_lang/src/syntax/tokens/base_tokenstream.rs b/vhdl_lang/src/syntax/tokens/base_tokenstream.rs index 17066e44..c537daf3 100644 --- a/vhdl_lang/src/syntax/tokens/base_tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/base_tokenstream.rs @@ -97,3 +97,148 @@ impl<'a> TokenStream for BaseTokenStream<'a> { Ok(des) } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::{ContentReader, Diagnostic, NoDiagnostics}; + use crate::syntax::test::Code; + + macro_rules! new_stream { + ($code:ident, $stream:ident) => { + let source = $code.source(); + let contents = source.contents(); + let tokenizer = Tokenizer::new(&$code.symbols, source, ContentReader::new(&contents)); + let $stream = BaseTokenStream::new(tokenizer, &mut NoDiagnostics); + }; + } + + #[test] + fn pop_and_peek() { + let code = Code::new("hello world again"); + let tokens = code.tokenize(); + new_stream!(code, stream); + + stream.skip(); + assert_eq!(stream.peek(), Some(&tokens[1])); + stream.skip(); + assert_eq!(stream.peek(), Some(&tokens[2])); + stream.skip(); + assert_eq!(stream.peek(), None); + stream.skip(); + assert_eq!(stream.peek(), None); + } + + #[test] + fn idx_of() { + let code = Code::new("hello world again"); + new_stream!(code, stream); + + let mut idx = 0; + while let Some(token) = stream.peek() { + assert_eq!(idx, stream.state_of(token).unwrap()); + idx += 1; + stream.skip(); + } + } + + #[test] + fn prev_token() { + let code = Code::new("hello world again"); + new_stream!(code, stream); + + let mut prev = None; + while let Some(token) = stream.peek() { + if let Some(prev) = prev { + assert_eq!(prev, stream.token_before(token).unwrap()); + } + prev = Some(token); + stream.skip(); + } + } + + #[test] + fn is_peek_kinds() { + let code = Code::new("hello 1 +"); + new_stream!(code, stream); + + assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral, Plus]),); + assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral])); + assert!(stream.next_kinds_are(&[Identifier])); + assert!(!stream.next_kinds_are(&[Identifier, AbstractLiteral, AbstractLiteral]),); + assert!(!stream.next_kinds_are(&[AbstractLiteral])); + } + + #[test] + fn expect() { + let code = Code::new("hello"); + let tokens = code.tokenize(); + new_stream!(code, stream); + + assert_eq!(stream.peek_expect(), Ok(&tokens[0])); + stream.skip(); + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn set_state_taken_before_peek() { + let code = Code::new("hello world"); + let tokens = code.tokenize(); + new_stream!(code, stream); + + let state = stream.state(); + assert_eq!(stream.peek(), Some(&tokens[0])); + stream.skip(); + assert_eq!(stream.peek(), Some(&tokens[1])); + stream.set_state(state); + assert_eq!(stream.peek(), Some(&tokens[0])); + } + + #[test] + fn expect_when_eof_empty() { + let code = Code::new(""); + new_stream!(code, stream); + + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn expect_eof_after_whitespace() { + let code = Code::new("a "); + new_stream!(code, stream); + + stream.skip(); + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn expect_eof_after_comment() { + let code = Code::new("a -- foo"); + new_stream!(code, stream); + + stream.skip(); + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn skip_until() { + let code = Code::new("a begin for + ;"); + new_stream!(code, stream); + + assert!(stream.skip_until(|ref k| matches!(k, Plus)).is_ok()); + assert_eq!(stream.peek().map(|t| t.kind), Some(Plus)); + } +} + diff --git a/vhdl_lang/src/syntax/tokens/completion_tokenstream.rs b/vhdl_lang/src/syntax/tokens/completion_tokenstream.rs deleted file mode 100644 index 5f858185..00000000 --- a/vhdl_lang/src/syntax/tokens/completion_tokenstream.rs +++ /dev/null @@ -1,36 +0,0 @@ -use crate::{Diagnostic, SrcPos}; -use crate::ast::AttributeDesignator; -use crate::data::{DiagnosticResult, WithPos}; -use crate::syntax::tokens::{BaseTokenStream, Token, TokenizationException, TokenStream}; - -struct CompletionTokenStream<'a> { - base: BaseTokenStream<'a>, - cursor: SrcPos, - suggestions: Vec, -} - -impl TokenStream for CompletionTokenStream { - fn state(&self) -> usize { - self.base.state() - } - - fn set_state(&self, state: usize) { - self.base.set_state(state) - } - - fn token_at(&self, state: usize) -> Option<&Token> { - self.base.token_at(state) - } - - fn state_of(&self, token: &Token) -> Option { - self.base.state_of(token) - } - - fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic { - self.base.handle_diagnostic(exception) - } - - fn expect_attribute_designator(&self) -> DiagnosticResult> { - self.base.expect_attribute_designator() - } -} diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index cbca8ca2..cd551988 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -10,8 +10,8 @@ use crate::ast::{AttributeDesignator, Ident}; use crate::data::{DiagnosticHandler, DiagnosticResult, WithPos}; use crate::{Diagnostic, SrcPos}; -/// A TokenStream is an immutable collection of tokens with a mutable state. -/// The state points to a certain tokens. Methods exist to mutate that state and seek +/// A TokenStream is an immutable collection of tokens with mutable state. +/// The state points to a certain token. Methods exist to mutate that state and seek /// to another token, e.g. to skip a token or go to a previous one. pub trait TokenStream { /// Returns the current state. @@ -218,147 +218,3 @@ impl Recover for DiagnosticResult { } } } - -#[cfg(test)] -mod tests { - use super::*; - use crate::data::{ContentReader, Diagnostic, NoDiagnostics}; - use crate::syntax::test::Code; - - macro_rules! new_stream { - ($code:ident, $stream:ident) => { - let source = $code.source(); - let contents = source.contents(); - let tokenizer = Tokenizer::new(&$code.symbols, source, ContentReader::new(&contents)); - let $stream = TokenStream::new(tokenizer, &mut NoDiagnostics); - }; - } - - #[test] - fn pop_and_peek() { - let code = Code::new("hello world again"); - let tokens = code.tokenize(); - new_stream!(code, stream); - - stream.skip(); - assert_eq!(stream.peek(), Some(&tokens[1])); - stream.skip(); - assert_eq!(stream.peek(), Some(&tokens[2])); - stream.skip(); - assert_eq!(stream.peek(), None); - stream.skip(); - assert_eq!(stream.peek(), None); - } - - #[test] - fn idx_of() { - let code = Code::new("hello world again"); - new_stream!(code, stream); - - let mut idx = 0; - while let Some(token) = stream.peek() { - assert_eq!(idx, stream.idx_of(token).unwrap()); - idx += 1; - stream.skip(); - } - } - - #[test] - fn prev_token() { - let code = Code::new("hello world again"); - new_stream!(code, stream); - - let mut prev = None; - while let Some(token) = stream.peek() { - if let Some(prev) = prev { - assert_eq!(prev, stream.token_before(token).unwrap()); - } - prev = Some(token); - stream.skip(); - } - } - - #[test] - fn is_peek_kinds() { - let code = Code::new("hello 1 +"); - new_stream!(code, stream); - - assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral, Plus]),); - assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral])); - assert!(stream.next_kinds_are(&[Identifier])); - assert!(!stream.next_kinds_are(&[Identifier, AbstractLiteral, AbstractLiteral]),); - assert!(!stream.next_kinds_are(&[AbstractLiteral])); - } - - #[test] - fn expect() { - let code = Code::new("hello"); - let tokens = code.tokenize(); - new_stream!(code, stream); - - assert_eq!(stream.peek_expect(), Ok(&tokens[0])); - stream.skip(); - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn set_state_taken_before_peek() { - let code = Code::new("hello world"); - let tokens = code.tokenize(); - new_stream!(code, stream); - - let state = stream.state(); - assert_eq!(stream.peek(), Some(&tokens[0])); - stream.skip(); - assert_eq!(stream.peek(), Some(&tokens[1])); - stream.set_state(state); - assert_eq!(stream.peek(), Some(&tokens[0])); - } - - #[test] - fn expect_when_eof_empty() { - let code = Code::new(""); - new_stream!(code, stream); - - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn expect_eof_after_whitespace() { - let code = Code::new("a "); - new_stream!(code, stream); - - stream.skip(); - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn expect_eof_after_comment() { - let code = Code::new("a -- foo"); - new_stream!(code, stream); - - stream.skip(); - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn skip_until() { - let code = Code::new("a begin for + ;"); - new_stream!(code, stream); - - assert!(stream.skip_until(|ref k| matches!(k, Plus)).is_ok()); - assert_eq!(stream.peek().map(|t| t.kind), Some(Plus)); - } -} diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index 4e9839f9..b71e86b7 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -270,7 +270,7 @@ impl VHDLServer { // Do not enable completions for files that are not part of the project return CompletionList {..Default::default()}; }; - let source= from_lsp_pos(params.text_document_position.position); + let cursor = from_lsp_pos(params.text_document_position.position); // 2) get "context", e.g. in entity declaration, in function declaration, e.t.c // (let's assume global context for now) @@ -283,10 +283,7 @@ impl VHDLServer { // 4) Run the parser until the point of the cursor. Then exit with possible completions let options = self .project - .list_completion_options( - &source, - from_lsp_pos(params.text_document_position.position), - ) + .list_completion_options(&source, cursor) .into_iter() .map(|option| CompletionItem { label: option, From cc456ec4b287ac895865088c98b54b3567f45fcb Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Wed, 9 Aug 2023 21:30:32 +0200 Subject: [PATCH 13/31] Revert breaking changes --- Cargo.lock | 241 ++++++----- vhdl_lang/src/analysis/completion.rs | 24 +- vhdl_lang/src/analysis/root.rs | 10 +- vhdl_lang/src/ast.rs | 21 - vhdl_lang/src/ast/search.rs | 54 --- vhdl_lang/src/syntax/alias_declaration.rs | 2 +- vhdl_lang/src/syntax/attributes.rs | 6 +- vhdl_lang/src/syntax/common.rs | 4 +- vhdl_lang/src/syntax/component_declaration.rs | 6 +- vhdl_lang/src/syntax/concurrent_statement.rs | 34 +- vhdl_lang/src/syntax/configuration.rs | 22 +- vhdl_lang/src/syntax/context.rs | 8 +- vhdl_lang/src/syntax/declarative_part.rs | 6 +- vhdl_lang/src/syntax/design_unit.rs | 10 +- vhdl_lang/src/syntax/expression.rs | 20 +- vhdl_lang/src/syntax/interface_declaration.rs | 32 +- vhdl_lang/src/syntax/names.rs | 30 +- vhdl_lang/src/syntax/object_declaration.rs | 14 +- vhdl_lang/src/syntax/parser.rs | 4 +- vhdl_lang/src/syntax/range.rs | 10 +- vhdl_lang/src/syntax/sequential_statement.rs | 48 +-- vhdl_lang/src/syntax/subprogram.rs | 12 +- vhdl_lang/src/syntax/subtype_indication.rs | 12 +- vhdl_lang/src/syntax/test.rs | 42 +- vhdl_lang/src/syntax/tokens.rs | 2 - .../src/syntax/tokens/base_tokenstream.rs | 244 ------------ vhdl_lang/src/syntax/tokens/tokenstream.rs | 375 +++++++++++++----- vhdl_lang/src/syntax/type_declaration.rs | 16 +- vhdl_lang/src/syntax/waveform.rs | 4 +- vhdl_ls/src/vhdl_server.rs | 9 +- 30 files changed, 622 insertions(+), 700 deletions(-) delete mode 100644 vhdl_lang/src/syntax/tokens/base_tokenstream.rs diff --git a/Cargo.lock b/Cargo.lock index 0813a076..a73f1544 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -86,12 +86,9 @@ checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cc" -version = "1.0.82" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" -dependencies = [ - "libc", -] +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -101,9 +98,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.3.21" +version = "4.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" dependencies = [ "clap_builder", "clap_derive", @@ -112,9 +109,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.21" +version = "4.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" dependencies = [ "anstream", "anstyle", @@ -124,14 +121,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -189,6 +186,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "diff" version = "0.1.13" @@ -223,9 +230,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.9.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "env_logger" @@ -242,15 +249,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", @@ -269,9 +276,12 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] [[package]] name = "fnv" @@ -319,9 +329,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "humantime" @@ -349,14 +359,34 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ "hermit-abi", - "rustix", + "rustix 0.38.1", "windows-sys", ] @@ -371,9 +401,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" @@ -383,9 +413,15 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "lock_api" @@ -405,9 +441,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" +checksum = "3711e4d6f491dc9edc0f1df80e204f38206775ac92c1241e89b79229a850bc00" dependencies = [ "crossbeam-channel", "log", @@ -417,9 +453,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.94.1" +version = "0.94.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237" dependencies = [ "bitflags 1.3.2", "serde", @@ -459,6 +495,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "output_vt100" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" +dependencies = [ + "winapi", +] + [[package]] name = "pad" version = "0.1.6" @@ -505,28 +550,30 @@ checksum = "268ad82d92622fb0a049ff14b01089b0f1bcd5c507fab44724394d328417348a" [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" dependencies = [ + "ctor", "diff", + "output_vt100", "yansi", ] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.32" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -584,83 +631,85 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-automata", "regex-syntax", ] [[package]] -name = "regex-automata" -version = "0.3.6" +name = "regex-syntax" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] -name = "regex-syntax" -version = "0.7.4" +name = "rustix" +version = "0.37.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", +] [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" dependencies = [ "bitflags 2.3.3", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.3", "windows-sys", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "scopeguard" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.183" +version = "1.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -669,13 +718,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -689,9 +738,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "strsim" @@ -701,9 +750,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.28" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" dependencies = [ "proc-macro2", "quote", @@ -712,14 +772,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.1" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.21", "windows-sys", ] @@ -734,22 +795,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -769,9 +830,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.7.6" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" dependencies = [ "serde", "serde_spanned", @@ -790,9 +851,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" dependencies = [ "indexmap", "serde", @@ -809,9 +870,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -988,9 +1049,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.5.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" dependencies = [ "memchr", ] diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index d1f91c79..07e361be 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,6 +1,6 @@ use std::default::Default; use crate::analysis::DesignRoot; -use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, UnitKey}; +use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; use crate::data::{ContentReader, Symbol}; use crate::syntax::Kind::*; use crate::syntax::{Symbols, Token, Tokenizer, Value}; @@ -23,6 +23,26 @@ macro_rules! ident { }; } +fn declaration_to_string(decl: &Declaration) -> Option { + match decl { + Declaration::Object(o) => Some(o.ident.tree.item.to_string()), + Declaration::File(f) => Some(f.ident.tree.item.to_string()), + Declaration::Type(t) => Some(t.ident.tree.item.to_string()), + Declaration::Component(c) => Some(c.ident.tree.item.to_string()), + Declaration::Attribute(a) => match a { + crate::ast::Attribute::Specification(spec) => Some(spec.ident.item.to_string()), + crate::ast::Attribute::Declaration(decl) => Some(decl.ident.tree.item.to_string()), + }, + Declaration::Alias(a) => Some(a.designator.to_string()), + Declaration::SubprogramDeclaration(decl) => Some(decl.subpgm_designator().to_string()), + Declaration::SubprogramBody(_) => None, + Declaration::Use(_) => None, + Declaration::Package(p) => Some(p.ident.to_string()), + Declaration::Configuration(_) => None, + } +} + + fn tokenize_input(symbols: &Symbols, source: &Source, cursor: Position) -> Vec { let contents = source.contents(); // let symbols = Symbols::default(); @@ -75,7 +95,7 @@ impl DesignRoot { AnyDesignUnit::Primary(AnyPrimaryUnit::Package(pkg)) => pkg .decl .iter() - .filter_map(|d| d.ident()) + .filter_map(declaration_to_string) .unique() .chain(vec!["all".to_string()].into_iter()) .collect_vec(), diff --git a/vhdl_lang/src/analysis/root.rs b/vhdl_lang/src/analysis/root.rs index 03565278..c8a51abc 100644 --- a/vhdl_lang/src/analysis/root.rs +++ b/vhdl_lang/src/analysis/root.rs @@ -1190,21 +1190,21 @@ package pkg is new gpkg generic map (const => foo); vec![ Diagnostic::error( code.s("pkg", 2), - "A primary unit has already been declared with name 'pkg' in library 'libname'", + "A primary unit has already been declared with name 'pkg' in library 'libname'" ).related(code.s("pkg", 1), "Previously defined here"), Diagnostic::error( code.s("entname", 2), - "A primary unit has already been declared with name 'entname' in library 'libname'", + "A primary unit has already been declared with name 'entname' in library 'libname'" ).related(code.s("entname", 1), "Previously defined here"), Diagnostic::error( code.s("pkg", 3), - "A primary unit has already been declared with name 'pkg' in library 'libname'", + "A primary unit has already been declared with name 'pkg' in library 'libname'" ).related(code.s("pkg", 1), "Previously defined here"), Diagnostic::error( code.s("pkg", 4), - "A primary unit has already been declared with name 'pkg' in library 'libname'", + "A primary unit has already been declared with name 'pkg' in library 'libname'" ).related(code.s("pkg", 1), "Previously defined here"), - ], + ] ); } diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index fccc2425..1c285f01 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -757,27 +757,6 @@ pub enum Declaration { Configuration(ConfigurationSpecification), } -impl Declaration { - pub fn ident(&self) -> Option { - match self { - Declaration::Object(o) => Some(o.ident.tree.item.to_string()), - Declaration::File(f) => Some(f.ident.tree.item.to_string()), - Declaration::Type(t) => Some(t.ident.tree.item.to_string()), - Declaration::Component(c) => Some(c.ident.tree.item.to_string()), - Declaration::Attribute(a) => match a { - Attribute::Specification(spec) => Some(spec.ident.item.to_string()), - Attribute::Declaration(decl) => Some(decl.ident.tree.item.to_string()), - }, - Declaration::Alias(a) => Some(a.designator.to_string()), - Declaration::SubprogramDeclaration(decl) => Some(decl.subpgm_designator().to_string()), - Declaration::SubprogramBody(_) => None, - Declaration::Use(_) => None, - Declaration::Package(p) => Some(p.ident.to_string()), - Declaration::Configuration(_) => None, - } - } -} - /// LRM 10.2 Wait statement #[derive(PartialEq, Debug, Clone)] pub struct WaitStatement { diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index 8535580e..b5f4df81 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -1777,60 +1777,6 @@ impl std::fmt::Display for FoundDeclaration<'_> { } } -pub struct SuggestionSearcher<'a> { - pub root: &'a DesignRoot, - pub cursor: Position, - pub source: &'a Source, - pub result: Vec, -} - -impl<'a> SuggestionSearcher<'a> { - pub fn new( - root: &'a DesignRoot, - cursor: Position, - source: &'a Source, - ) -> SuggestionSearcher<'a> { - SuggestionSearcher { - root, - cursor, - source, - result: vec![], - } - } - - fn cursor_inside_of(&self, pos: &SrcPos) -> bool { - pos.start() <= self.cursor && self.cursor <= pos.end() - } - - fn search_entity(&mut self, entity: EntityId, pos: &SrcPos) -> SearchState { - let ent = self.root.get_ent(entity); - self.result - .push(format!("{:?}: {:?}", ent.describe(), pos.range)); - self.result.push(ent.describe()); - NotFinished - } -} - -impl<'a> Searcher for SuggestionSearcher<'a> { - fn search_pos_with_ref(&mut self, pos: &SrcPos, reference: &mut Reference) -> SearchState { - if !self.cursor_inside_of(pos) { - return Finished(NotFound); - } - match reference { - Some(eid) => self.search_entity(eid.clone(), pos), - None => Finished(NotFound), - } - } - - fn search_source(&mut self, source: &Source) -> SearchState { - if source == self.source { - NotFinished - } else { - Finished(NotFound) - } - } -} - #[derive(Default)] pub struct FindAllUnresolved { pub count: usize, diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index 1b6e278c..156299da 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -11,7 +11,7 @@ use super::subtype_indication::parse_subtype_indication; use super::tokens::{Kind::*, TokenStream}; use crate::ast::{AliasDeclaration, WithDecl}; -pub fn parse_alias_declaration(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_alias_declaration(stream: &TokenStream) -> ParseResult { stream.expect_kind(Alias)?; let designator = WithDecl::new(parse_designator(stream)?); let subtype_indication = { diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index a6901cb0..e44a9542 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -14,7 +14,7 @@ use crate::ast::{ EntityTag, WithRef, }; -fn parse_entity_class(stream: &dyn TokenStream) -> ParseResult { +fn parse_entity_class(stream: &TokenStream) -> ParseResult { Ok(expect_token!(stream, token, Entity => EntityClass::Entity, Architecture => EntityClass::Architecture, @@ -31,7 +31,7 @@ fn parse_entity_class(stream: &dyn TokenStream) -> ParseResult { )) } -pub fn parse_entity_name_list(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult> { Ok(expect_token!(stream, token, Identifier | StringLiteral => { let mut entity_name_list = Vec::new(); @@ -73,7 +73,7 @@ pub fn parse_entity_name_list(stream: &dyn TokenStream) -> ParseResult ParseResult> { +pub fn parse_attribute(stream: &TokenStream) -> ParseResult> { stream.expect_kind(Attribute)?; let ident = stream.expect_ident()?; Ok(expect_token!(stream, token, diff --git a/vhdl_lang/src/syntax/common.rs b/vhdl_lang/src/syntax/common.rs index 82af91e8..4fa7a699 100644 --- a/vhdl_lang/src/syntax/common.rs +++ b/vhdl_lang/src/syntax/common.rs @@ -13,12 +13,12 @@ use crate::SrcPos; /// Parse optional part followed by optional keyword pub fn parse_optional( - stream: &dyn TokenStream, + stream: &TokenStream, keyword: Kind, parse_fun: F, ) -> ParseResult> where - F: FnOnce(&dyn TokenStream) -> ParseResult, + F: FnOnce(&TokenStream) -> ParseResult, { let optional = { if stream.skip_if_kind(keyword) { diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index 96b05e8b..8a85c663 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -13,7 +13,7 @@ use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; use crate::data::{Diagnostic, DiagnosticHandler}; pub fn parse_optional_generic_list( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { let mut list = None; @@ -38,7 +38,7 @@ pub fn parse_optional_generic_list( } pub fn parse_optional_port_list( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { let mut list = None; @@ -72,7 +72,7 @@ pub fn parse_optional_port_list( } pub fn parse_component_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Component)?; diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index 87f808d5..6461b226 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -26,7 +26,7 @@ use crate::data::*; /// LRM 11.2 Block statement pub fn parse_block_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -62,7 +62,7 @@ pub fn parse_block_statement( } fn parse_block_header( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut generic_clause = None; @@ -156,7 +156,7 @@ fn parse_block_header( /// LRM 11.3 Process statement pub fn parse_process_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, postponed: bool, diagnostics: &mut dyn DiagnosticHandler, @@ -252,7 +252,7 @@ fn to_procedure_call( /// Assume target and <= is parsed already fn parse_assignment_known_target( - stream: &dyn TokenStream, + stream: &TokenStream, target: WithPos, ) -> ParseResult { // @TODO postponed @@ -272,7 +272,7 @@ fn parse_assignment_known_target( } fn parse_assignment_or_procedure_call( - stream: &dyn TokenStream, + stream: &TokenStream, target: WithPos, ) -> ParseResult { expect_token!(stream, token, @@ -285,7 +285,7 @@ fn parse_assignment_or_procedure_call( } fn parse_selected_signal_assignment( - stream: &dyn TokenStream, + stream: &TokenStream, postponed: bool, ) -> ParseResult { stream.expect_kind(With)?; @@ -307,7 +307,7 @@ fn parse_selected_signal_assignment( } pub fn parse_concurrent_assert_statement( - stream: &dyn TokenStream, + stream: &TokenStream, postponed: bool, ) -> ParseResult { Ok(ConcurrentAssertStatement { @@ -318,7 +318,7 @@ pub fn parse_concurrent_assert_statement( #[allow(clippy::type_complexity)] pub fn parse_generic_and_port_map( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult<( Option>, Option>, @@ -344,7 +344,7 @@ pub fn parse_generic_and_port_map( } pub fn parse_instantiation_statement( - stream: &dyn TokenStream, + stream: &TokenStream, unit: InstantiatedUnit, ) -> ParseResult { let (generic_map, port_map) = parse_generic_and_port_map(stream)?; @@ -359,7 +359,7 @@ pub fn parse_instantiation_statement( } fn parse_optional_declarative_part( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult>> { if is_declarative_part(stream, true)? { @@ -372,7 +372,7 @@ fn parse_optional_declarative_part( } fn parse_generate_body( - stream: &dyn TokenStream, + stream: &TokenStream, alternative_label: Option>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -409,7 +409,7 @@ fn parse_generate_body( /// 11.8 Generate statements fn parse_for_generate_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -434,7 +434,7 @@ fn parse_for_generate_statement( /// 11.8 Generate statements fn parse_if_generate_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -504,7 +504,7 @@ fn parse_if_generate_statement( /// 11.8 Generate statements fn parse_case_generate_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -554,7 +554,7 @@ fn parse_case_generate_statement( } pub fn parse_concurrent_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -640,7 +640,7 @@ pub fn parse_concurrent_statement( } pub fn parse_labeled_concurrent_statements( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut statements = Vec::new(); @@ -658,7 +658,7 @@ pub fn parse_labeled_concurrent_statements( } pub fn parse_labeled_concurrent_statement( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let start = stream.peek_expect()?; diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index 1859f075..a794c04a 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -14,7 +14,7 @@ use crate::ast::*; use crate::data::*; /// LRM 7.3.2.2 -fn parse_entity_aspect(stream: &dyn TokenStream) -> ParseResult { +fn parse_entity_aspect(stream: &TokenStream) -> ParseResult { let entity_aspect = expect_token!( stream, token, @@ -39,7 +39,7 @@ fn parse_entity_aspect(stream: &dyn TokenStream) -> ParseResult { fn parse_binding_indication_known_entity_aspect( entity_aspect: Option, - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult { let (generic_map, port_map) = parse_generic_and_port_map(stream)?; @@ -52,7 +52,7 @@ fn parse_binding_indication_known_entity_aspect( } /// LRM 7.3.2 -fn parse_binding_indication(stream: &dyn TokenStream) -> ParseResult { +fn parse_binding_indication(stream: &TokenStream) -> ParseResult { let entity_aspect = if stream.skip_if_kind(Use) { Some(parse_entity_aspect(stream)?) } else { @@ -62,7 +62,7 @@ fn parse_binding_indication(stream: &dyn TokenStream) -> ParseResult ParseResult { @@ -116,7 +116,7 @@ enum ComponentSpecificationOrName { } fn parse_component_specification_or_name( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult { peek_token!( stream, token, @@ -177,7 +177,7 @@ fn parse_component_specification_or_name( } fn parse_configuration_item_known_keyword( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { match parse_component_specification_or_name(stream)? { @@ -193,7 +193,7 @@ fn parse_configuration_item_known_keyword( } fn parse_block_configuration_known_name( - stream: &dyn TokenStream, + stream: &TokenStream, name: WithPos, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -224,7 +224,7 @@ fn parse_block_configuration_known_name( } fn parse_block_configuration_known_keyword( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let name = parse_name(stream)?; @@ -232,7 +232,7 @@ fn parse_block_configuration_known_keyword( } fn parse_vunit_binding_indication_list_known_keyword( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult> { let mut indications = Vec::new(); loop { @@ -265,7 +265,7 @@ fn parse_vunit_binding_indication_list_known_keyword( /// LRM 3.4 Configuration declaration pub fn parse_configuration_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Configuration)?; @@ -311,7 +311,7 @@ pub fn parse_configuration_declaration( /// LRM 7.3 Configuration Specification pub fn parse_configuration_specification( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult { stream.expect_kind(For)?; match parse_component_specification_or_name(stream)? { diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index dfe3b284..69725e83 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -12,7 +12,7 @@ use crate::ast::*; use crate::data::*; /// LRM 13. Design units and their analysis -pub fn parse_library_clause(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_library_clause(stream: &TokenStream) -> ParseResult> { let library_token = stream.expect_kind(Library)?; let mut name_list = Vec::with_capacity(1); loop { @@ -29,7 +29,7 @@ pub fn parse_library_clause(stream: &dyn TokenStream) -> ParseResult ParseResult> { +pub fn parse_use_clause(stream: &TokenStream) -> ParseResult> { let use_token = stream.expect_kind(Use)?; let mut name_list = Vec::with_capacity(1); @@ -52,7 +52,7 @@ pub enum DeclarationOrReference { Reference(WithPos), } -pub fn parse_context_reference(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_context_reference(stream: &TokenStream) -> ParseResult> { let context_token = stream.expect_kind(Context)?; let name = parse_name(stream)?; @@ -72,7 +72,7 @@ pub fn parse_context_reference(stream: &dyn TokenStream) -> ParseResult ParseResult { let context_token = stream.expect_kind(Context)?; diff --git a/vhdl_lang/src/syntax/declarative_part.rs b/vhdl_lang/src/syntax/declarative_part.rs index 38576de4..d492e60f 100644 --- a/vhdl_lang/src/syntax/declarative_part.rs +++ b/vhdl_lang/src/syntax/declarative_part.rs @@ -18,7 +18,7 @@ use super::type_declaration::parse_type_declaration; use crate::ast::{ContextClause, Declaration, PackageInstantiation}; use crate::data::DiagnosticHandler; -pub fn parse_package_instantiation(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_package_instantiation(stream: &TokenStream) -> ParseResult { stream.expect_kind(Package)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -43,7 +43,7 @@ pub fn parse_package_instantiation(stream: &dyn TokenStream) -> ParseResult ParseResult { +pub fn is_declarative_part(stream: &TokenStream, begin_is_end: bool) -> ParseResult { Ok(check_declarative_part(stream.peek_expect()?, !begin_is_end, begin_is_end).is_ok()) } @@ -65,7 +65,7 @@ fn check_declarative_part(token: &Token, may_end: bool, may_begin: bool) -> Pars } pub fn parse_declarative_part( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { let mut declarations: Vec = Vec::new(); diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 740a5f6c..74b39ab5 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -22,7 +22,7 @@ use crate::data::*; /// Parse an entity declaration, token is initial entity token /// If a parse error occurs the stream is consumed until and end entity pub fn parse_entity_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Entity)?; @@ -57,7 +57,7 @@ pub fn parse_entity_declaration( /// LRM 3.3.1 pub fn parse_architecture_body( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Architecture)?; @@ -88,7 +88,7 @@ pub fn parse_architecture_body( /// LRM 4.7 Package declarations pub fn parse_package_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Package)?; @@ -120,7 +120,7 @@ pub fn parse_package_declaration( /// LRM 4.8 Package bodies pub fn parse_package_body( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { stream.expect_kind(Package)?; @@ -159,7 +159,7 @@ fn context_item_message(context_item: &ContextItem, message: impl AsRef) -> } pub fn parse_design_file( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut context_clause = vec![]; diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index 8956c825..6549873e 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -142,7 +142,7 @@ fn kind_to_binary_op(kind: Kind) -> Option<(Operator, usize)> { } pub fn parse_aggregate_initial_choices( - stream: &dyn TokenStream, + stream: &TokenStream, choices: Vec>, ) -> ParseResult>> { let mut choices = choices; @@ -191,7 +191,7 @@ pub fn parse_aggregate_initial_choices( } } -pub fn parse_aggregate(stream: &dyn TokenStream) -> ParseResult>> { +pub fn parse_aggregate(stream: &TokenStream) -> ParseResult>> { stream.expect_kind(LeftPar)?; if let Some(token) = stream.pop_if_kind(RightPar) { return Ok(WithPos::from(Vec::new(), token.pos.clone())); @@ -201,7 +201,7 @@ pub fn parse_aggregate(stream: &dyn TokenStream) -> ParseResult, direction: Direction, ) -> ParseResult> { @@ -217,7 +217,7 @@ fn parse_half_range( Ok(WithPos::new(range, pos)) } -fn parse_choice(stream: &dyn TokenStream) -> ParseResult> { +fn parse_choice(stream: &TokenStream) -> ParseResult> { if let Some(token) = stream.pop_if_kind(Others) { return Ok(WithPos::new(Choice::Others, token.pos.clone())); } @@ -234,7 +234,7 @@ fn parse_choice(stream: &dyn TokenStream) -> ParseResult> { } } -pub fn parse_choices(stream: &dyn TokenStream) -> ParseResult>> { +pub fn parse_choices(stream: &TokenStream) -> ParseResult>> { let mut choices = Vec::new(); loop { choices.push(parse_choice(stream)?); @@ -247,7 +247,7 @@ pub fn parse_choices(stream: &dyn TokenStream) -> ParseResult ParseResult> { +fn parse_allocator(stream: &TokenStream) -> ParseResult> { stream.expect_kind(New)?; let type_mark = parse_type_mark(stream)?; @@ -318,7 +318,7 @@ fn name_to_selected_name(name: Name) -> Option { } } -fn parse_expression_or_aggregate(stream: &dyn TokenStream) -> ParseResult> { +fn parse_expression_or_aggregate(stream: &TokenStream) -> ParseResult> { let mut choices = parse_choices(stream)?; if choices.len() == 1 @@ -369,7 +369,7 @@ fn parse_expression_or_aggregate(stream: &dyn TokenStream) -> ParseResult ParseResult> { +fn parse_primary(stream: &TokenStream) -> ParseResult> { let token = stream.peek_expect()?; match token.kind { Identifier | LtLt => { @@ -479,7 +479,7 @@ fn parse_primary(stream: &dyn TokenStream) -> ParseResult> { } } -fn parse_expr(stream: &dyn TokenStream, min_precedence: usize) -> ParseResult> { +fn parse_expr(stream: &TokenStream, min_precedence: usize) -> ParseResult> { let mut lhs = parse_primary(stream)?; while let Some(token) = stream.peek() { if token.kind == RightPar { @@ -524,7 +524,7 @@ fn parse_expr(stream: &dyn TokenStream, min_precedence: usize) -> ParseResult ParseResult> { +pub fn parse_expression(stream: &TokenStream) -> ParseResult> { let state = stream.state(); parse_expr(stream, 0).map_err(|err| { stream.set_state(state); diff --git a/vhdl_lang/src/syntax/interface_declaration.rs b/vhdl_lang/src/syntax/interface_declaration.rs index 41c63399..bc44a7c7 100644 --- a/vhdl_lang/src/syntax/interface_declaration.rs +++ b/vhdl_lang/src/syntax/interface_declaration.rs @@ -14,7 +14,7 @@ use super::tokens::{Kind::*, *}; use crate::ast::*; use crate::data::*; -fn parse_optional_mode(stream: &dyn TokenStream) -> ParseResult>> { +fn parse_optional_mode(stream: &TokenStream) -> ParseResult>> { let token = stream.peek_expect()?; let mode = match token.kind { In => Mode::In, @@ -37,7 +37,7 @@ fn unexpected_object_class_kind(list_type: InterfaceType, token: &Token) -> Diag } fn parse_optional_object_class( - stream: &dyn TokenStream, + stream: &TokenStream, list_type: InterfaceType, ) -> ParseResult>> { let token = stream.peek_expect()?; @@ -54,7 +54,7 @@ fn parse_optional_object_class( } fn parse_interface_file_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult> { let file_objects = parse_file_declaration_no_semi(stream)?; for file_object in file_objects.iter() { @@ -84,7 +84,7 @@ fn parse_interface_file_declaration( } fn parse_interface_object_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, list_type: InterfaceType, ) -> ParseResult> { let explicit_object_class = parse_optional_object_class(stream, list_type)?; @@ -158,7 +158,7 @@ fn parse_interface_object_declaration( .collect()) } -fn parse_subprogram_default(stream: &dyn TokenStream) -> ParseResult> { +fn parse_subprogram_default(stream: &TokenStream) -> ParseResult> { if stream.skip_if_kind(Is) { let default = { peek_token!( @@ -177,7 +177,7 @@ fn parse_subprogram_default(stream: &dyn TokenStream) -> ParseResult ParseResult { +fn parse_interface_package(stream: &TokenStream) -> ParseResult { stream.expect_kind(Package)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -212,7 +212,7 @@ fn parse_interface_package(stream: &dyn TokenStream) -> ParseResult ParseResult> { @@ -241,7 +241,7 @@ fn parse_interface_declaration( /// Parse ; separator in generic or port lists. /// Expect ; for all but the last item -fn parse_semicolon_separator(stream: &dyn TokenStream) -> ParseResult<()> { +fn parse_semicolon_separator(stream: &TokenStream) -> ParseResult<()> { peek_token!( stream, token, SemiColon => { @@ -269,7 +269,7 @@ fn is_sync_kind(list_type: InterfaceType, kind: Kind) -> bool { } fn parse_interface_list( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, list_type: InterfaceType, ) -> ParseResult> { @@ -335,21 +335,21 @@ fn parse_interface_list( } pub fn parse_generic_interface_list( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Generic) } pub fn parse_port_interface_list( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Port) } pub fn parse_parameter_interface_list( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { parse_interface_list(stream, diagnostics, InterfaceType::Parameter) @@ -357,7 +357,7 @@ pub fn parse_parameter_interface_list( #[cfg(test)] fn parse_one_interface_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, list_type: InterfaceType, ) -> ParseResult { let mut diagnostics = Vec::new(); @@ -370,17 +370,17 @@ fn parse_one_interface_declaration( } #[cfg(test)] -pub fn parse_parameter(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_parameter(stream: &TokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Parameter) } #[cfg(test)] -pub fn parse_port(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_port(stream: &TokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Port) } #[cfg(test)] -pub fn parse_generic(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_generic(stream: &TokenStream) -> ParseResult { parse_one_interface_declaration(stream, InterfaceType::Generic) } diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index 27d95af1..0556afd1 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -14,7 +14,7 @@ use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; -pub fn parse_designator(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_designator(stream: &TokenStream) -> ParseResult> { Ok(expect_token!( stream, token, @@ -24,7 +24,7 @@ pub fn parse_designator(stream: &dyn TokenStream) -> ParseResult ParseResult> { +pub fn parse_selected_name(stream: &TokenStream) -> ParseResult> { let mut name = parse_designator(stream)? .into_ref() .map_into(SelectedName::Designator); @@ -39,13 +39,13 @@ pub fn parse_selected_name(stream: &dyn TokenStream) -> ParseResult ParseResult> { +pub fn parse_type_mark(stream: &TokenStream) -> ParseResult> { let name = parse_selected_name(stream)?; parse_type_mark_starting_with_name(stream, name) } pub fn parse_type_mark_starting_with_name( - stream: &dyn TokenStream, + stream: &TokenStream, name: WithPos, ) -> ParseResult> { let state = stream.state(); @@ -96,7 +96,7 @@ pub fn expression_to_ident(name: WithPos) -> ParseResult { to_simple_name(name) } -pub fn parse_identifier_list(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_identifier_list(stream: &TokenStream) -> ParseResult> { let mut idents = Vec::new(); loop { idents.push(stream.expect_ident()?); @@ -152,7 +152,7 @@ fn assoc_to_expression(assoc: AssociationElement) -> ParseResult ParseResult> { +fn parse_actual_part(stream: &TokenStream) -> ParseResult> { if let Some(token) = stream.pop_if_kind(Open) { Ok(WithPos::from(ActualPart::Open, token.pos.clone())) } else { @@ -160,7 +160,7 @@ fn parse_actual_part(stream: &dyn TokenStream) -> ParseResult ParseResult { +fn parse_association_element(stream: &TokenStream) -> ParseResult { let actual = parse_actual_part(stream)?; if stream.skip_if_kind(RightArrow) { Ok(AssociationElement { @@ -175,13 +175,13 @@ fn parse_association_element(stream: &dyn TokenStream) -> ParseResult ParseResult> { +pub fn parse_association_list(stream: &TokenStream) -> ParseResult> { stream.expect_kind(LeftPar)?; parse_association_list_no_leftpar(stream) } pub fn parse_association_list_no_leftpar( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult> { let mut association_elements = Vec::with_capacity(1); loop { @@ -198,7 +198,7 @@ pub fn parse_association_list_no_leftpar( } fn parse_function_call( - stream: &dyn TokenStream, + stream: &TokenStream, prefix: WithPos, first: AssociationElement, ) -> ParseResult> { @@ -225,7 +225,7 @@ fn parse_function_call( } fn parse_attribute_name( - stream: &dyn TokenStream, + stream: &TokenStream, name: WithPos, signature: Option>, ) -> ParseResult> { @@ -257,7 +257,7 @@ enum DesignatorOrAll { All, } -fn parse_suffix(stream: &dyn TokenStream) -> ParseResult> { +fn parse_suffix(stream: &TokenStream) -> ParseResult> { let name = { expect_token!( stream, @@ -274,7 +274,7 @@ fn parse_suffix(stream: &dyn TokenStream) -> ParseResult> -fn parse_inner_external_name(stream: &dyn TokenStream) -> ParseResult { +fn parse_inner_external_name(stream: &TokenStream) -> ParseResult { let token = stream.peek_expect()?; let class = try_init_token_kind!( token, @@ -327,7 +327,7 @@ fn parse_inner_external_name(stream: &dyn TokenStream) -> ParseResult ParseResult> { +fn _parse_name(stream: &TokenStream) -> ParseResult> { let mut name = { if let Some(token) = stream.pop_if_kind(LtLt) { let external_name = Name::External(Box::new(parse_inner_external_name(stream)?)); @@ -472,7 +472,7 @@ pub fn into_range(assoc: AssociationElement) -> Result ParseResult> { +pub fn parse_name(stream: &TokenStream) -> ParseResult> { let state = stream.state(); _parse_name(stream).map_err(|err| { stream.set_state(state); diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index ffef4342..17ab5d82 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -13,9 +13,7 @@ use super::tokens::{Kind::*, TokenStream}; use crate::ast::*; use crate::data::WithPos; -pub fn parse_optional_assignment( - stream: &dyn TokenStream, -) -> ParseResult>> { +pub fn parse_optional_assignment(stream: &TokenStream) -> ParseResult>> { if stream.pop_if_kind(ColonEq).is_some() { let expr = parse_expression(stream)?; Ok(Some(expr)) @@ -25,7 +23,7 @@ pub fn parse_optional_assignment( } fn parse_object_declaration_kind( - stream: &dyn TokenStream, + stream: &TokenStream, class: ObjectClass, ) -> ParseResult> { match class { @@ -60,7 +58,7 @@ fn parse_object_declaration_kind( .collect()) } -pub fn parse_object_declaration(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_object_declaration(stream: &TokenStream) -> ParseResult> { let token = stream.peek_expect()?; let result = try_init_token_kind!( token, @@ -75,9 +73,7 @@ pub fn parse_object_declaration(stream: &dyn TokenStream) -> ParseResult ParseResult> { +pub fn parse_file_declaration_no_semi(stream: &TokenStream) -> ParseResult> { stream.expect_kind(File)?; let idents = parse_identifier_list(stream)?; stream.expect_kind(Colon)?; @@ -110,7 +106,7 @@ pub fn parse_file_declaration_no_semi( .collect()) } -pub fn parse_file_declaration(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_file_declaration(stream: &TokenStream) -> ParseResult> { let result = parse_file_declaration_no_semi(stream)?; stream.expect_kind(SemiColon)?; Ok(result) diff --git a/vhdl_lang/src/syntax/parser.rs b/vhdl_lang/src/syntax/parser.rs index cf155807..f87ff107 100644 --- a/vhdl_lang/src/syntax/parser.rs +++ b/vhdl_lang/src/syntax/parser.rs @@ -5,7 +5,7 @@ // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com use super::design_unit::parse_design_file; -use super::tokens::{BaseTokenStream, Symbols, Tokenizer}; +use super::tokens::{Symbols, TokenStream, Tokenizer}; use crate::ast::DesignFile; use crate::data::*; use std::io; @@ -30,7 +30,7 @@ impl VHDLParser { ) -> DesignFile { let contents = source.contents(); let tokenizer = Tokenizer::new(&self.symbols, source, ContentReader::new(&contents)); - let stream = BaseTokenStream::new(tokenizer, diagnostics); + let stream = TokenStream::new(tokenizer, diagnostics); match parse_design_file(&stream, diagnostics) { Ok(design_file) => design_file, diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index b494247d..376e5e17 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -13,7 +13,7 @@ use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; -pub fn parse_direction(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_direction(stream: &TokenStream) -> ParseResult { Ok(expect_token!( stream, token, To => Direction::Ascending, @@ -26,7 +26,7 @@ enum NameOrRange { Range(WithPos), } -fn parse_name_or_range(stream: &dyn TokenStream) -> ParseResult { +fn parse_name_or_range(stream: &TokenStream) -> ParseResult { let expr = parse_expression(stream)?; match stream.peek_kind() { @@ -72,14 +72,14 @@ fn parse_name_or_range(stream: &dyn TokenStream) -> ParseResult { /// {selected_name}'range /// {selected_name}'reverse_range /// 2. {expr} to|downto {expr} -pub fn parse_range(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_range(stream: &TokenStream) -> ParseResult> { match parse_name_or_range(stream)? { NameOrRange::Range(range) => Ok(range), NameOrRange::Name(name) => Err(Diagnostic::error(&name, "Expected range")), } } -pub fn parse_discrete_range(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_discrete_range(stream: &TokenStream) -> ParseResult { match parse_name_or_range(stream) { Ok(NameOrRange::Range(range)) => Ok(DiscreteRange::Range(range.item)), Ok(NameOrRange::Name(name)) => { @@ -91,7 +91,7 @@ pub fn parse_discrete_range(stream: &dyn TokenStream) -> ParseResult ParseResult { +pub fn parse_array_index_constraint(stream: &TokenStream) -> ParseResult { match parse_name_or_range(stream) { Ok(NameOrRange::Range(range)) => Ok(ArrayIndex::Discrete(DiscreteRange::Range(range.item))), Ok(NameOrRange::Name(name)) => { diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index 25da86cf..f061c3a3 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -17,7 +17,7 @@ use crate::data::*; use crate::syntax::common::check_label_identifier_mismatch; /// LRM 10.2 Wait statement -fn parse_wait_statement(stream: &dyn TokenStream) -> ParseResult { +fn parse_wait_statement(stream: &TokenStream) -> ParseResult { stream.expect_kind(Wait)?; let mut sensitivity_clause = vec![]; if stream.skip_if_kind(On) { @@ -41,7 +41,7 @@ fn parse_wait_statement(stream: &dyn TokenStream) -> ParseResult } /// LRM 10.3 Assertion statement -pub fn parse_assert_statement(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_assert_statement(stream: &TokenStream) -> ParseResult { stream.expect_kind(Assert)?; let condition = parse_expression(stream)?; let report = parse_optional(stream, Report, parse_expression)?; @@ -56,7 +56,7 @@ pub fn parse_assert_statement(stream: &dyn TokenStream) -> ParseResult ParseResult { +fn parse_report_statement(stream: &TokenStream) -> ParseResult { stream.expect_kind(Report)?; let report = parse_expression(stream)?; let severity = parse_optional(stream, Severity, parse_expression)?; @@ -66,7 +66,7 @@ fn parse_report_statement(stream: &dyn TokenStream) -> ParseResult ParseResult> { let mut statements = Vec::new(); @@ -85,7 +85,7 @@ pub fn parse_labeled_sequential_statements( /// LRM 10.8 If statement fn parse_if_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -146,7 +146,7 @@ fn parse_if_statement( /// LRM 10.9 Case statement fn parse_case_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -194,7 +194,7 @@ fn parse_case_statement( /// LRM 10.10 Loop statement fn parse_loop_statement( - stream: &dyn TokenStream, + stream: &TokenStream, label: Option<&Ident>, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -236,7 +236,7 @@ fn parse_loop_statement( } /// LRM 10.11 Next statement -fn parse_next_statement(stream: &dyn TokenStream) -> ParseResult { +fn parse_next_statement(stream: &TokenStream) -> ParseResult { stream.expect_kind(Next)?; let loop_label = stream.pop_optional_ident(); let condition = parse_optional(stream, When, parse_expression)?; @@ -248,7 +248,7 @@ fn parse_next_statement(stream: &dyn TokenStream) -> ParseResult } /// LRM 10.12 Exit statement -fn parse_exit_statement(stream: &dyn TokenStream) -> ParseResult { +fn parse_exit_statement(stream: &TokenStream) -> ParseResult { stream.expect_kind(Exit)?; let loop_label = stream.pop_optional_ident(); let condition = parse_optional(stream, When, parse_expression)?; @@ -260,7 +260,7 @@ fn parse_exit_statement(stream: &dyn TokenStream) -> ParseResult } /// LRM 10.13 Return statement -fn parse_return_statement(stream: &dyn TokenStream) -> ParseResult { +fn parse_return_statement(stream: &TokenStream) -> ParseResult { stream.expect_kind(Return)?; let expression = { if stream.peek_kind() == Some(SemiColon) { @@ -275,24 +275,24 @@ fn parse_return_statement(stream: &dyn TokenStream) -> ParseResult ParseResult> { parse_assignment_right_hand(stream, parse_waveform) } /// LRM 10.6 Variable assignment statement fn parse_variable_assignment_right_hand( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult>> { parse_assignment_right_hand(stream, parse_expression) } fn parse_assignment_right_hand( - stream: &dyn TokenStream, + stream: &TokenStream, parse_item: F, ) -> ParseResult> where - F: Fn(&dyn TokenStream) -> ParseResult, + F: Fn(&TokenStream) -> ParseResult, { let item = parse_item(stream)?; @@ -310,12 +310,12 @@ where } fn parse_conditonals( - stream: &dyn TokenStream, + stream: &TokenStream, initial_item: T, parse_item: F, ) -> ParseResult> where - F: Fn(&dyn TokenStream) -> ParseResult, + F: Fn(&TokenStream) -> ParseResult, { let condition = parse_expression(stream)?; let cond_expr = Conditional { @@ -362,12 +362,12 @@ where } pub fn parse_selection( - stream: &dyn TokenStream, + stream: &TokenStream, expression: WithPos, parse_item: F, ) -> ParseResult> where - F: Fn(&dyn TokenStream) -> ParseResult, + F: Fn(&TokenStream) -> ParseResult, { let mut alternatives = Vec::with_capacity(2); @@ -391,7 +391,7 @@ where }) } -fn parse_optional_force_mode(stream: &dyn TokenStream) -> ParseResult> { +fn parse_optional_force_mode(stream: &TokenStream) -> ParseResult> { let token = stream.peek_expect()?; let optional_force_mode = match token.kind { In => { @@ -409,7 +409,7 @@ fn parse_optional_force_mode(stream: &dyn TokenStream) -> ParseResult, ) -> ParseResult { Ok(expect_token!( @@ -472,7 +472,7 @@ fn parse_assignment_or_procedure_call( )) } -pub fn parse_target(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_target(stream: &TokenStream) -> ParseResult> { if stream.next_kind_is(LeftPar) { Ok(parse_aggregate(stream)?.map_into(Target::Aggregate)) } else { @@ -480,7 +480,7 @@ pub fn parse_target(stream: &dyn TokenStream) -> ParseResult> { } } -fn parse_selected_assignment(stream: &dyn TokenStream) -> ParseResult { +fn parse_selected_assignment(stream: &TokenStream) -> ParseResult { let expression = parse_expression(stream)?; stream.expect_kind(Select)?; let target = parse_target(stream)?; @@ -513,7 +513,7 @@ fn parse_selected_assignment(stream: &dyn TokenStream) -> ParseResult, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -551,7 +551,7 @@ fn parse_unlabeled_sequential_statement( } pub fn parse_sequential_statement( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let start = stream.peek_expect()?; diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index d958e496..719cbf66 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -13,7 +13,7 @@ use super::tokens::{kinds_error, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; -pub fn parse_signature(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_signature(stream: &TokenStream) -> ParseResult> { let left_square = stream.expect_kind(LeftSquare)?; let start_pos = &left_square.pos; let mut type_marks = Vec::new(); @@ -67,7 +67,7 @@ pub fn parse_signature(stream: &dyn TokenStream) -> ParseResult ParseResult> { +fn parse_designator(stream: &TokenStream) -> ParseResult> { Ok(expect_token!( stream, token, @@ -77,7 +77,7 @@ fn parse_designator(stream: &dyn TokenStream) -> ParseResult ParseResult { let (is_function, is_pure) = { @@ -125,7 +125,7 @@ pub fn parse_subprogram_declaration_no_semi( } pub fn parse_subprogram_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let res = parse_subprogram_declaration_no_semi(stream, diagnostics); @@ -135,7 +135,7 @@ pub fn parse_subprogram_declaration( /// LRM 4.3 Subprogram bodies pub fn parse_subprogram_body( - stream: &dyn TokenStream, + stream: &TokenStream, specification: SubprogramDeclaration, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -173,7 +173,7 @@ pub fn parse_subprogram_body( } pub fn parse_subprogram( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let specification = parse_subprogram_declaration_no_semi(stream, diagnostics)?; diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index fb10a491..93f12997 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -12,14 +12,14 @@ use super::tokens::{kinds_error, Kind::*, TokenStream}; use crate::ast::*; use crate::data::{SrcPos, WithPos}; -fn parse_record_element_constraint(stream: &dyn TokenStream) -> ParseResult { +fn parse_record_element_constraint(stream: &TokenStream) -> ParseResult { let ident = stream.expect_ident()?; let constraint = Box::new(parse_composite_constraint(stream)?); Ok(ElementConstraint { ident, constraint }) } fn parse_array_constraint( - stream: &dyn TokenStream, + stream: &TokenStream, leftpar_pos: SrcPos, // Open is None initial: Option, @@ -52,7 +52,7 @@ fn parse_array_constraint( )) } -fn parse_composite_constraint(stream: &dyn TokenStream) -> ParseResult> { +fn parse_composite_constraint(stream: &TokenStream) -> ParseResult> { // There is no finite lookahead that can differentiate // between array and record element constraint let leftpar_pos = stream.expect_kind(LeftPar)?.pos.clone(); @@ -103,7 +103,7 @@ fn parse_composite_constraint(stream: &dyn TokenStream) -> ParseResult ParseResult>> { if let Some(token) = stream.peek() { let constraint = match token.kind { @@ -125,7 +125,7 @@ pub fn parse_subtype_constraint( } pub fn parse_element_resolution_indication( - stream: &dyn TokenStream, + stream: &TokenStream, ) -> ParseResult { stream.expect_kind(LeftPar)?; @@ -178,7 +178,7 @@ pub fn parse_element_resolution_indication( )) } -pub fn parse_subtype_indication(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_subtype_indication(stream: &TokenStream) -> ParseResult { let (resolution, type_mark) = { if stream.peek_kind() == Some(LeftPar) { let resolution = parse_element_resolution_indication(stream)?; diff --git a/vhdl_lang/src/syntax/test.rs b/vhdl_lang/src/syntax/test.rs index fe00dcc8..727451c0 100644 --- a/vhdl_lang/src/syntax/test.rs +++ b/vhdl_lang/src/syntax/test.rs @@ -28,7 +28,6 @@ use crate::ast; use crate::ast::*; use crate::data::Range; use crate::data::*; -use crate::syntax::tokens::BaseTokenStream; use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::Entry; use std::collections::HashMap; @@ -198,7 +197,7 @@ impl Code { /// Helper method to run lower level parsing function at specific substring pub fn parse(&self, parse_fun: F) -> R where - F: FnOnce(&dyn TokenStream) -> R, + F: FnOnce(&TokenStream) -> R, { let contents = self.pos.source.contents(); let source = Source::from_contents( @@ -208,7 +207,7 @@ impl Code { let contents = source.contents(); let reader = ContentReader::new(&contents); let tokenizer = Tokenizer::new(&self.symbols, &source, reader); - let mut stream = BaseTokenStream::new(tokenizer, &mut NoDiagnostics); + let mut stream = TokenStream::new(tokenizer, &mut NoDiagnostics); forward(&stream, self.pos.start()); parse_fun(&mut stream) } @@ -216,7 +215,7 @@ impl Code { /// Expect Ok() value pub fn parse_ok(&self, parse_fun: F) -> R where - F: FnOnce(&dyn TokenStream) -> ParseResult, + F: FnOnce(&TokenStream) -> ParseResult, { match self.parse(parse_fun) { Ok(res) => res, @@ -228,21 +227,21 @@ impl Code { pub fn with_partial_stream(&self, parse_fun: F) -> R where - F: FnOnce(&dyn TokenStream) -> R, + F: FnOnce(&TokenStream) -> R, { let contents = self.pos.source.contents(); let reader = ContentReader::new(&contents); let tokenizer = Tokenizer::new(&self.symbols, &self.pos.source, reader); - let mut stream = BaseTokenStream::new(tokenizer, &mut NoDiagnostics); + let mut stream = TokenStream::new(tokenizer, &mut NoDiagnostics); parse_fun(&mut stream) } pub fn with_stream(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&dyn TokenStream) -> ParseResult, + F: FnOnce(&TokenStream) -> ParseResult, { - let parse_fun_eof = |stream: &dyn TokenStream| { + let parse_fun_eof = |stream: &TokenStream| { let result = parse_fun(stream); match result { Err(err) => { @@ -266,9 +265,9 @@ impl Code { pub fn with_stream_err(&self, parse_fun: F) -> Diagnostic where R: Debug, - F: FnOnce(&dyn TokenStream) -> ParseResult, + F: FnOnce(&TokenStream) -> ParseResult, { - let parse_fun_eof = |stream: &dyn TokenStream| { + let parse_fun_eof = |stream: &TokenStream| { let result = parse_fun(stream); match result { Err(err) => { @@ -290,29 +289,28 @@ impl Code { pub fn with_partial_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> R, + F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> R, { let mut diagnostics = Vec::new(); - let result = self - .with_partial_stream(|stream: &dyn TokenStream| parse_fun(stream, &mut diagnostics)); + let result = + self.with_partial_stream(|stream: &TokenStream| parse_fun(stream, &mut diagnostics)); (result, diagnostics) } pub fn with_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let mut diagnostics = Vec::new(); - let result = - self.with_stream(|stream: &dyn TokenStream| parse_fun(stream, &mut diagnostics)); + let result = self.with_stream(|stream: &TokenStream| parse_fun(stream, &mut diagnostics)); (result, diagnostics) } pub fn with_stream_no_diagnostics(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let (result, diagnostics) = self.with_stream_diagnostics(parse_fun); check_no_diagnostics(&diagnostics); @@ -327,11 +325,11 @@ impl Code { } /// Helper to create a identifier at first occurence of name pub fn ident(&self) -> Ident { - self.parse_ok(|stream: &dyn TokenStream| stream.expect_ident()) + self.parse_ok(|stream: &TokenStream| stream.expect_ident()) } pub fn decl_ident(&self) -> WithDecl { - WithDecl::new(self.parse_ok(|stream: &dyn TokenStream| stream.expect_ident())) + WithDecl::new(self.parse_ok(|stream: &TokenStream| stream.expect_ident())) } pub fn designator(&self) -> WithPos { @@ -346,7 +344,7 @@ impl Code { } pub fn character(&self) -> WithPos { - self.parse_ok(|stream: &dyn TokenStream| { + self.parse_ok(|stream: &TokenStream| { stream.expect_kind(Kind::Character)?.to_character_value() }) } @@ -437,7 +435,7 @@ impl Code { pub fn parse_ok_no_diagnostics(&self, parse_fun: F) -> R where - F: FnOnce(&dyn TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, { let mut diagnostics = Vec::new(); let res = self.parse_ok(|stream| parse_fun(stream, &mut diagnostics)); @@ -529,7 +527,7 @@ fn substr_range(source: &Source, range: Range, substr: &str, occurence: usize) - } /// Fast forward tokenstream until position -fn forward(stream: &dyn TokenStream, start: Position) { +fn forward(stream: &TokenStream, start: Position) { loop { let token = stream.peek_expect().unwrap(); if token.pos.start() >= start { diff --git a/vhdl_lang/src/syntax/tokens.rs b/vhdl_lang/src/syntax/tokens.rs index 48316815..2cc3e2a9 100644 --- a/vhdl_lang/src/syntax/tokens.rs +++ b/vhdl_lang/src/syntax/tokens.rs @@ -6,9 +6,7 @@ #[macro_use] mod tokenizer; -mod base_tokenstream; mod tokenstream; -pub use base_tokenstream::*; pub use tokenizer::*; pub use tokenstream::*; diff --git a/vhdl_lang/src/syntax/tokens/base_tokenstream.rs b/vhdl_lang/src/syntax/tokens/base_tokenstream.rs deleted file mode 100644 index c537daf3..00000000 --- a/vhdl_lang/src/syntax/tokens/base_tokenstream.rs +++ /dev/null @@ -1,244 +0,0 @@ -use super::tokenizer::Kind::*; -use super::tokenizer::*; -use crate::ast::{AttributeDesignator, RangeAttribute, TypeAttribute}; -use crate::data::{DiagnosticHandler, DiagnosticResult, WithPos}; -use crate::syntax::tokens::{TokenStream, TokenizationException}; -use crate::Diagnostic; -use std::cell::Cell; - -pub struct BaseTokenStream<'a> { - tokenizer: Tokenizer<'a>, - idx: Cell, - tokens: Vec, -} - -/// The token stream maintains a collection of tokens and a current state. -/// The state is an index into the vector of tokens and -impl<'a> BaseTokenStream<'a> { - pub fn new( - mut tokenizer: Tokenizer<'a>, - diagnostics: &mut dyn DiagnosticHandler, - ) -> BaseTokenStream<'a> { - let mut tokens = Vec::new(); - loop { - match tokenizer.pop() { - Ok(Some(token)) => tokens.push(token), - Ok(None) => break, - Err(err) => diagnostics.push(err), - } - } - BaseTokenStream { - tokenizer, - idx: Cell::new(0), - tokens, - } - } - - fn eof_error(&self) -> Diagnostic { - let end = self.tokenizer.source.contents().end(); - Diagnostic::error( - self.tokenizer.source.pos(end, end.next_char()), - "Unexpected EOF", - ) - } -} - -impl<'a> TokenStream for BaseTokenStream<'a> { - fn state(&self) -> usize { - self.idx.get() - } - - fn set_state(&self, state: usize) { - self.idx.replace(state); - } - - fn token_at(&self, state: usize) -> Option<&Token> { - self.tokens.get(state) - } - - fn state_of(&self, token: &Token) -> Option { - let base = self.tokens.as_ptr() as usize; - let ptr = (token as *const Token) as usize; - let idx = ptr.checked_sub(base)? / std::mem::size_of::(); - - if idx < self.tokens.len() { - Some(idx) - } else { - None - } - } - - fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic { - match exception { - TokenizationException::KindsError { pos, kinds } => kinds_error(pos, kinds), - TokenizationException::EofError { expectations } => { - let mut diagnostic = self.eof_error(); - if let Some(kinds) = expectations { - diagnostic = diagnostic.when(format!("expecting {}", kinds_str(kinds))); - } - diagnostic - } - } - } - - /// Expect identifier or subtype/range keywords - /// foo'subtype or foo'range - fn expect_attribute_designator(&self) -> DiagnosticResult> { - let des = expect_token!( - self, - token, - Identifier => { - let ident = token.to_identifier_value()?; - ident.map_into(|sym| self.tokenizer.attribute(sym)) - }, - Subtype => WithPos::new(AttributeDesignator::Type(TypeAttribute::Subtype), token.pos.clone()), - Range => WithPos::new(AttributeDesignator::Range(RangeAttribute::Range), token.pos.clone()) - ); - Ok(des) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::data::{ContentReader, Diagnostic, NoDiagnostics}; - use crate::syntax::test::Code; - - macro_rules! new_stream { - ($code:ident, $stream:ident) => { - let source = $code.source(); - let contents = source.contents(); - let tokenizer = Tokenizer::new(&$code.symbols, source, ContentReader::new(&contents)); - let $stream = BaseTokenStream::new(tokenizer, &mut NoDiagnostics); - }; - } - - #[test] - fn pop_and_peek() { - let code = Code::new("hello world again"); - let tokens = code.tokenize(); - new_stream!(code, stream); - - stream.skip(); - assert_eq!(stream.peek(), Some(&tokens[1])); - stream.skip(); - assert_eq!(stream.peek(), Some(&tokens[2])); - stream.skip(); - assert_eq!(stream.peek(), None); - stream.skip(); - assert_eq!(stream.peek(), None); - } - - #[test] - fn idx_of() { - let code = Code::new("hello world again"); - new_stream!(code, stream); - - let mut idx = 0; - while let Some(token) = stream.peek() { - assert_eq!(idx, stream.state_of(token).unwrap()); - idx += 1; - stream.skip(); - } - } - - #[test] - fn prev_token() { - let code = Code::new("hello world again"); - new_stream!(code, stream); - - let mut prev = None; - while let Some(token) = stream.peek() { - if let Some(prev) = prev { - assert_eq!(prev, stream.token_before(token).unwrap()); - } - prev = Some(token); - stream.skip(); - } - } - - #[test] - fn is_peek_kinds() { - let code = Code::new("hello 1 +"); - new_stream!(code, stream); - - assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral, Plus]),); - assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral])); - assert!(stream.next_kinds_are(&[Identifier])); - assert!(!stream.next_kinds_are(&[Identifier, AbstractLiteral, AbstractLiteral]),); - assert!(!stream.next_kinds_are(&[AbstractLiteral])); - } - - #[test] - fn expect() { - let code = Code::new("hello"); - let tokens = code.tokenize(); - new_stream!(code, stream); - - assert_eq!(stream.peek_expect(), Ok(&tokens[0])); - stream.skip(); - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn set_state_taken_before_peek() { - let code = Code::new("hello world"); - let tokens = code.tokenize(); - new_stream!(code, stream); - - let state = stream.state(); - assert_eq!(stream.peek(), Some(&tokens[0])); - stream.skip(); - assert_eq!(stream.peek(), Some(&tokens[1])); - stream.set_state(state); - assert_eq!(stream.peek(), Some(&tokens[0])); - } - - #[test] - fn expect_when_eof_empty() { - let code = Code::new(""); - new_stream!(code, stream); - - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn expect_eof_after_whitespace() { - let code = Code::new("a "); - new_stream!(code, stream); - - stream.skip(); - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn expect_eof_after_comment() { - let code = Code::new("a -- foo"); - new_stream!(code, stream); - - stream.skip(); - assert_eq!( - stream.peek_expect(), - Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) - ); - } - - #[test] - fn skip_until() { - let code = Code::new("a begin for + ;"); - new_stream!(code, stream); - - assert!(stream.skip_until(|ref k| matches!(k, Plus)).is_ok()); - assert_eq!(stream.peek().map(|t| t.kind), Some(Plus)); - } -} - diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index cd551988..adc41f2d 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -4,108 +4,92 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com +use std::cell::Cell; + use super::tokenizer::Kind::*; use super::tokenizer::*; -use crate::ast::{AttributeDesignator, Ident}; +use crate::ast::{AttributeDesignator, Ident, RangeAttribute, TypeAttribute}; use crate::data::{DiagnosticHandler, DiagnosticResult, WithPos}; use crate::{Diagnostic, SrcPos}; -/// A TokenStream is an immutable collection of tokens with mutable state. -/// The state points to a certain token. Methods exist to mutate that state and seek -/// to another token, e.g. to skip a token or go to a previous one. -pub trait TokenStream { - /// Returns the current state. - /// `token_at(self.state())` must always return the current token, or `None` if the - /// state is invalid - fn state(&self) -> usize; - - /// Sets the current state. - /// An invalid state is OK but `token_at(invalid_state)` will return `None` - fn set_state(&self, state: usize); - - /// Returns the token at an given state - fn token_at(&self, state: usize) -> Option<&Token>; - - /// Returns the state of a token - fn state_of(&self, token: &Token) -> Option; - - // Default implementations for common operations +pub struct TokenStream<'a> { + tokenizer: Tokenizer<'a>, + idx: Cell, + tokens: Vec, +} - /// Skips the current token, i.e. increments the current state - fn skip(&self) { - self.set_state(self.state() + 1) +impl<'a> TokenStream<'a> { + pub fn new( + mut tokenizer: Tokenizer<'a>, + diagnostics: &mut dyn DiagnosticHandler, + ) -> TokenStream<'a> { + let mut tokens = Vec::new(); + loop { + match tokenizer.pop() { + Ok(Some(token)) => tokens.push(token), + Ok(None) => break, + Err(err) => diagnostics.push(err), + } + } + TokenStream { + tokenizer, + idx: Cell::new(0), + tokens, + } } - /// Returns the token at the current state - fn peek(&self) -> Option<&Token> { - self.token_at(self.state()) + pub fn state(&self) -> usize { + self.get_idx() } - /// Returns the token kind at the current state - fn peek_kind(&self) -> Option { - self.peek().map(|token| token.kind) + pub fn set_state(&self, state: usize) { + self.set_idx(state); } - /// returns the token at the previous state - fn last(&self) -> Option<&Token> { - let state = self.state().checked_sub(1)?; - self.token_at(state) + pub fn skip(&self) { + self.set_idx(self.get_idx() + 1) } - /// Returns `true`, when the nth next token is of kind `kind` - fn nth_kind_is(&self, offset: usize, kind: Kind) -> bool { - if let Some(token) = self.token_at(self.state() + offset) { - token.kind == kind - } else { - false - } + fn get_idx(&self) -> usize { + self.idx.get() } - /// returns true, when the next token is of a certain kind - fn next_kind_is(&self, kind: Kind) -> bool { - self.nth_kind_is(0, kind) + fn set_idx(&self, idx: usize) { + self.idx.replace(idx); } - /// returns true when all next tokens are of a certain kind - fn next_kinds_are(&self, kinds: &[Kind]) -> bool { - kinds - .iter() - .enumerate() - .all(|(idx, kind)| self.nth_kind_is(idx, *kind)) + pub fn peek(&self) -> Option<&Token> { + self.tokens.get(self.get_idx()) } - /// advances (i.e. skips) if the next token is of a particular kind and returns the token - fn pop_if_kind(&self, kind: Kind) -> Option<&Token> { - if let Some(token) = self.peek() { - if token.kind == kind { - self.skip(); - return Some(token); - } - } - None + pub fn last(&self) -> Option<&Token> { + let last_idx = self.get_idx().checked_sub(1)?; + self.tokens.get(last_idx) } - /// advances (i.e. skips) if the next token is of a particular kind and returns true if successfully - fn skip_if_kind(&self, kind: Kind) -> bool { - self.pop_if_kind(kind).is_some() + fn eof_error(&self) -> Diagnostic { + let end = self.tokenizer.source.contents().end(); + Diagnostic::error( + self.tokenizer.source.pos(end, end.next_char()), + "Unexpected EOF", + ) } - /// skips if the current token is an identifier and returns that identifier, if found - fn pop_optional_ident(&self) -> Option { - self.pop_if_kind(Identifier) - .map(|token| token.to_identifier_value().unwrap()) + fn idx_of(&self, token: &Token) -> Option { + let base = self.tokens.as_ptr() as usize; + let ptr = (token as *const Token) as usize; + let idx = ptr.checked_sub(base)? / std::mem::size_of::(); + + if idx < self.tokens.len() { + Some(idx) + } else { + None + } } - /// Returns the token right before the given token - /// - /// Example: - /// entity my_entity is - /// ^ ^ - /// | | token 'is' - /// token_before('is') fn token_before(&self, token: &Token) -> Option<&Token> { - let state = self.state_of(token)?; - self.token_at(state.wrapping_sub(1)) + let idx = self.idx_of(token)?; + self.tokens.get(idx.wrapping_sub(1)) } /// A position that aligns with the previous token @@ -115,7 +99,7 @@ pub trait TokenStream { /// ~ <- want semi colon error here /// signal /// ~~~~~~ <- not here - fn pos_before(&self, token: &Token) -> SrcPos { + pub fn pos_before(&self, token: &Token) -> SrcPos { if let Some(prev_token) = self.token_before(token) { let prev_pos = prev_token.pos.end(); @@ -127,44 +111,67 @@ pub trait TokenStream { token.pos.clone() } - // Diagnostic stuff - - fn handle_diagnostic(&self, exception: TokenizationException) -> Diagnostic; - - // TODO: this should not be an anonymous function (it's too specific) - fn expect_attribute_designator(&self) -> DiagnosticResult>; - - fn expect_kind(&self, kind: Kind) -> DiagnosticResult<&Token> { + pub fn expect_kind(&self, kind: Kind) -> DiagnosticResult<&Token> { if let Some(token) = self.peek() { if token.kind == kind { self.skip(); Ok(token) } else { - Err(self.handle_diagnostic(TokenizationException::KindsError { - pos: self.pos_before(token), - kinds: &[kind], - })) + Err(kinds_error(self.pos_before(token), &[kind])) } } else { - Err(self.handle_diagnostic(TokenizationException::EofError { - expectations: Some(&[kind]), - })) + Err(self + .eof_error() + .when(format!("expecting {}", kinds_str(&[kind])))) } } - fn peek_expect(&self) -> DiagnosticResult<&Token> { + pub fn peek_expect(&self) -> DiagnosticResult<&Token> { if let Some(token) = self.peek() { Ok(token) } else { - Err(self.handle_diagnostic(TokenizationException::EofError { expectations: None })) + Err(self.eof_error()) } } - fn expect_ident(&self) -> DiagnosticResult { - expect_token!(self, token, Identifier => token.to_identifier_value()) + pub fn peek_kind(&self) -> Option { + self.peek().map(|token| token.kind) + } + + pub fn next_kind_is(&self, kind: Kind) -> bool { + self.nth_kind_is(0, kind) + } + + pub fn nth_kind_is(&self, idx: usize, kind: Kind) -> bool { + if let Some(token) = self.tokens.get(self.get_idx() + idx) { + token.kind == kind + } else { + false + } + } + + pub fn next_kinds_are(&self, kinds: &[Kind]) -> bool { + kinds + .iter() + .enumerate() + .all(|(idx, kind)| self.nth_kind_is(idx, *kind)) } - fn skip_until(&self, cond: fn(Kind) -> bool) -> DiagnosticResult<()> { + pub fn pop_if_kind(&self, kind: Kind) -> Option<&Token> { + if let Some(token) = self.peek() { + if token.kind == kind { + self.skip(); + return Some(token); + } + } + None + } + + pub fn skip_if_kind(&self, kind: Kind) -> bool { + self.pop_if_kind(kind).is_some() + } + + pub fn skip_until(&self, cond: fn(Kind) -> bool) -> DiagnosticResult<()> { loop { let token = self.peek_expect()?; if cond(token.kind) { @@ -173,17 +180,37 @@ pub trait TokenStream { self.skip(); } } -} -pub enum TokenizationException<'a> { - KindsError { pos: SrcPos, kinds: &'a [Kind] }, - EofError { expectations: Option<&'a [Kind]> }, + pub fn pop_optional_ident(&self) -> Option { + self.pop_if_kind(Identifier) + .map(|token| token.to_identifier_value().unwrap()) + } + + pub fn expect_ident(&self) -> DiagnosticResult { + expect_token!(self, token, Identifier => token.to_identifier_value()) + } + + /// Expect identifier or subtype/range keywords + /// foo'subtype or foo'range + pub fn expect_attribute_designator(&self) -> DiagnosticResult> { + let des = expect_token!( + self, + token, + Identifier => { + let ident = token.to_identifier_value()?; + ident.map_into(|sym| self.tokenizer.attribute(sym)) + }, + Subtype => WithPos::new(AttributeDesignator::Type(TypeAttribute::Subtype), token.pos.clone()), + Range => WithPos::new(AttributeDesignator::Range(RangeAttribute::Range), token.pos.clone()) + ); + Ok(des) + } } pub trait Recover { fn or_recover_until( self, - stream: &dyn TokenStream, + stream: &TokenStream, msgs: &mut dyn DiagnosticHandler, cond: fn(Kind) -> bool, ) -> DiagnosticResult; @@ -194,7 +221,7 @@ pub trait Recover { impl Recover for DiagnosticResult { fn or_recover_until( self, - stream: &dyn TokenStream, + stream: &TokenStream, msgs: &mut dyn DiagnosticHandler, cond: fn(Kind) -> bool, ) -> DiagnosticResult { @@ -218,3 +245,147 @@ impl Recover for DiagnosticResult { } } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::data::{ContentReader, Diagnostic, NoDiagnostics}; + use crate::syntax::test::Code; + + macro_rules! new_stream { + ($code:ident, $stream:ident) => { + let source = $code.source(); + let contents = source.contents(); + let tokenizer = Tokenizer::new(&$code.symbols, source, ContentReader::new(&contents)); + let $stream = TokenStream::new(tokenizer, &mut NoDiagnostics); + }; + } + + #[test] + fn pop_and_peek() { + let code = Code::new("hello world again"); + let tokens = code.tokenize(); + new_stream!(code, stream); + + stream.skip(); + assert_eq!(stream.peek(), Some(&tokens[1])); + stream.skip(); + assert_eq!(stream.peek(), Some(&tokens[2])); + stream.skip(); + assert_eq!(stream.peek(), None); + stream.skip(); + assert_eq!(stream.peek(), None); + } + + #[test] + fn idx_of() { + let code = Code::new("hello world again"); + new_stream!(code, stream); + + let mut idx = 0; + while let Some(token) = stream.peek() { + assert_eq!(idx, stream.idx_of(token).unwrap()); + idx += 1; + stream.skip(); + } + } + + #[test] + fn prev_token() { + let code = Code::new("hello world again"); + new_stream!(code, stream); + + let mut prev = None; + while let Some(token) = stream.peek() { + if let Some(prev) = prev { + assert_eq!(prev, stream.token_before(token).unwrap()); + } + prev = Some(token); + stream.skip(); + } + } + + #[test] + fn is_peek_kinds() { + let code = Code::new("hello 1 +"); + new_stream!(code, stream); + + assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral, Plus]),); + assert!(stream.next_kinds_are(&[Identifier, AbstractLiteral])); + assert!(stream.next_kinds_are(&[Identifier])); + assert!(!stream.next_kinds_are(&[Identifier, AbstractLiteral, AbstractLiteral]),); + assert!(!stream.next_kinds_are(&[AbstractLiteral])); + } + + #[test] + fn expect() { + let code = Code::new("hello"); + let tokens = code.tokenize(); + new_stream!(code, stream); + + assert_eq!(stream.peek_expect(), Ok(&tokens[0])); + stream.skip(); + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn set_state_taken_before_peek() { + let code = Code::new("hello world"); + let tokens = code.tokenize(); + new_stream!(code, stream); + + let state = stream.state(); + assert_eq!(stream.peek(), Some(&tokens[0])); + stream.skip(); + assert_eq!(stream.peek(), Some(&tokens[1])); + stream.set_state(state); + assert_eq!(stream.peek(), Some(&tokens[0])); + } + + #[test] + fn expect_when_eof_empty() { + let code = Code::new(""); + new_stream!(code, stream); + + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn expect_eof_after_whitespace() { + let code = Code::new("a "); + new_stream!(code, stream); + + stream.skip(); + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn expect_eof_after_comment() { + let code = Code::new("a -- foo"); + new_stream!(code, stream); + + stream.skip(); + assert_eq!( + stream.peek_expect(), + Err(Diagnostic::error(code.eof_pos(), "Unexpected EOF")) + ); + } + + #[test] + fn skip_until() { + let code = Code::new("a begin for + ;"); + new_stream!(code, stream); + + assert!(stream.skip_until(|ref k| matches!(k, Plus)).is_ok()); + assert_eq!(stream.peek().map(|t| t.kind), Some(Plus)); + } +} diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index 5f7fcc4f..525146bc 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -18,7 +18,7 @@ use crate::data::DiagnosticHandler; use crate::syntax::names::parse_type_mark; /// LRM 5.2.2 Enumeration types -fn parse_enumeration_type_definition(stream: &dyn TokenStream) -> ParseResult { +fn parse_enumeration_type_definition(stream: &TokenStream) -> ParseResult { let mut enum_literals = Vec::new(); loop { expect_token!(stream, @@ -45,7 +45,7 @@ fn parse_enumeration_type_definition(stream: &dyn TokenStream) -> ParseResult ParseResult> { +fn parse_array_index_constraints(stream: &TokenStream) -> ParseResult> { stream.expect_kind(LeftPar)?; let mut indexes = Vec::new(); loop { @@ -61,7 +61,7 @@ fn parse_array_index_constraints(stream: &dyn TokenStream) -> ParseResult ParseResult { +fn parse_array_type_definition(stream: &TokenStream) -> ParseResult { let index_constraints = parse_array_index_constraints(stream)?; stream.expect_kind(Of)?; let element_subtype = parse_subtype_indication(stream)?; @@ -71,7 +71,7 @@ fn parse_array_type_definition(stream: &dyn TokenStream) -> ParseResult ParseResult<(TypeDefinition, Option)> { let mut elem_decls = Vec::new(); @@ -96,7 +96,7 @@ fn parse_record_type_definition( } } -pub fn parse_subtype_declaration(stream: &dyn TokenStream) -> ParseResult { +pub fn parse_subtype_declaration(stream: &TokenStream) -> ParseResult { stream.expect_kind(Subtype)?; let ident = stream.expect_ident()?; stream.expect_kind(Is)?; @@ -111,7 +111,7 @@ pub fn parse_subtype_declaration(stream: &dyn TokenStream) -> ParseResult ParseResult<(ProtectedTypeDeclaration, Option)> { let mut items = Vec::new(); @@ -137,7 +137,7 @@ pub fn parse_protected_type_declaration( /// LRM 5.2.4 Physical types fn parse_physical_type_definition( - stream: &dyn TokenStream, + stream: &TokenStream, range: Range, ) -> ParseResult<(TypeDefinition, Option)> { let primary_unit = WithDecl::new(stream.expect_ident()?); @@ -193,7 +193,7 @@ fn parse_physical_type_definition( /// LRM 6.2 pub fn parse_type_declaration( - stream: &dyn TokenStream, + stream: &TokenStream, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { peek_token!( diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 0e8c0018..4e059ab5 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -11,7 +11,7 @@ use super::expression::parse_expression; use super::tokens::{Kind::*, TokenStream}; /// LRM 10.5 Signal assignment statement -pub fn parse_delay_mechanism(stream: &dyn TokenStream) -> ParseResult> { +pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult> { let token = stream.peek_expect()?; match token.kind { Transport => { @@ -33,7 +33,7 @@ pub fn parse_delay_mechanism(stream: &dyn TokenStream) -> ParseResult ParseResult { +pub fn parse_waveform(stream: &TokenStream) -> ParseResult { if stream.skip_if_kind(Unaffected) { return Ok(Waveform::Unaffected); } diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index b71e86b7..8181e694 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -271,16 +271,13 @@ impl VHDLServer { return CompletionList {..Default::default()}; }; let cursor = from_lsp_pos(params.text_document_position.position); - // 2) get "context", e.g. in entity declaration, in function declaration, e.t.c - // (let's assume global context for now) - - // 3) go to last recognizable token before the cursor. For global state: + // 2) Optimization chance: go to last recognizable token before the cursor. For example: // - Any primary unit (e.g. entity declaration, package declaration, ...) // => keyword `entity`, `package`, ... // - Any secondary unit (e.g. package body, architecture) // => keyword `architecture`, ... - // 4) Run the parser until the point of the cursor. Then exit with possible completions + // 3) Run the parser until the point of the cursor. Then exit with possible completions let options = self .project .list_completion_options(&source, cursor) @@ -290,7 +287,7 @@ impl VHDLServer { ..Default::default() }) .collect(); - self.message(Message::log(format!("{:?}", options))); + CompletionList { items: options, is_incomplete: true, From 9dc5ab5508c9caadb96ee3c2746112bd4c13a6d9 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Wed, 9 Aug 2023 22:33:11 +0200 Subject: [PATCH 14/31] fmt --- vhdl_lang/src/analysis/completion.rs | 88 ++++++++++++++++++++++------ 1 file changed, 70 insertions(+), 18 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 07e361be..44b88a1e 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,4 +1,3 @@ -use std::default::Default; use crate::analysis::DesignRoot; use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; use crate::data::{ContentReader, Symbol}; @@ -6,6 +5,7 @@ use crate::syntax::Kind::*; use crate::syntax::{Symbols, Token, Tokenizer, Value}; use crate::{Position, Source}; use itertools::Itertools; +use std::default::Default; macro_rules! kind { ($kind: pat) => { @@ -23,6 +23,12 @@ macro_rules! ident { }; } +/// Returns the completable string representation of a declaration +/// for example: +/// `let alias = parse_vhdl("alias my_alias is ...")` +/// `declaration_to_string(Declaration::Alias(alias)) == "my_alias"` +/// Returns `None` if the declaration has no string representation that can be used for completion +/// purposes. fn declaration_to_string(decl: &Declaration) -> Option { match decl { Declaration::Object(o) => Some(o.ident.tree.item.to_string()), @@ -42,10 +48,29 @@ fn declaration_to_string(decl: &Declaration) -> Option { } } - +/// Tokenizes `source` up to `cursor` but no further. The last token returned is the token +/// where the cursor currently resides or the token right before the cursor. +/// +/// Examples: +/// +/// input = "use ieee.std_logic_1|164.a" +/// ^ cursor position +/// `tokenize_input(input)` -> {USE, ieee, DOT, std_logic_1164} +/// +/// input = "use ieee.std_logic_1164|.a" +/// ^ cursor position +/// `tokenize_input(input)` -> {USE, ieee, DOT, std_logic_1164} +/// +/// input = "use ieee.std_logic_1164.|a" +/// ^ cursor position +/// `tokenize_input(input)` -> {USE, ieee, DOT, std_logic_1164, DOT} +/// input = "use ieee.std_logic_1164.a|" +/// ^ cursor position +/// `tokenize_input(input)` -> {USE, ieee, DOT, std_logic_1164, DOT, a} +/// +/// On error, or if the source is empty, returns an empty vector. fn tokenize_input(symbols: &Symbols, source: &Source, cursor: Position) -> Vec { let contents = source.contents(); - // let symbols = Symbols::default(); let mut tokenizer = Tokenizer::new(symbols, source, ContentReader::new(&contents)); let mut tokens = Vec::new(); loop { @@ -64,7 +89,6 @@ fn tokenize_input(symbols: &Symbols, source: &Source, cursor: Position) -> Vec Vec { self.available_libraries() @@ -105,7 +129,10 @@ impl DesignRoot { pub fn list_completion_options(&self, source: &Source, cursor: Position) -> Vec { let tokens = tokenize_input(&self.symbols, source, cursor); - let cursor_at_end = tokens.last().map(|tok| tok.pos.end() == cursor).unwrap_or(false); + let cursor_at_end = tokens + .last() + .map(|tok| tok.pos.end() == cursor) + .unwrap_or(false); match &tokens[..] { [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { @@ -118,21 +145,21 @@ impl DesignRoot { [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot)] | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { self.list_available_declarations(library, selected) - }, + } [.., kind!(Entity), kind!(Identifier)] => { if cursor_at_end { vec![] } else { vec!["is".to_string()] } - }, + } [.., kind!(Architecture), kind!(Identifier)] => { if cursor_at_end { vec![] } else { vec!["of".to_string()] } - }, + } _ => vec![], } } @@ -140,10 +167,10 @@ impl DesignRoot { #[cfg(test)] mod test { - use assert_matches::assert_matches; use super::*; use crate::analysis::completion::tokenize_input; use crate::syntax::test::Code; + use assert_matches::assert_matches; #[test] fn tokenizing_an_empty_input() { @@ -154,22 +181,47 @@ mod test { #[test] fn tokenizing_stops_at_the_cursors_position() { - let input = Code::new("entity my_ent is"); + let input = Code::new("use ieee.std_logic_1164.all"); // mid of `my_ent` - let mut cursor = Position::new(0, 11); + let mut cursor = Position::new(0, 21); let tokens = tokenize_input(&input.symbols, input.source(), cursor); - assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier)]); + assert_matches!( + tokens[..], + [kind!(Use), kind!(Identifier), kind!(Dot), kind!(Identifier)] + ); // end of `my_ent` - cursor = Position::new(0, 13); + cursor = Position::new(0, 23); let tokens = tokenize_input(&input.symbols, input.source(), cursor); - assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier)]); + assert_matches!( + tokens[..], + [kind!(Use), kind!(Identifier), kind!(Dot), kind!(Identifier)] + ); // start of `is` - cursor = Position::new(0, 14); + cursor = Position::new(0, 24); let tokens = tokenize_input(&input.symbols, input.source(), cursor); - assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier)]); + assert_matches!( + tokens[..], + [ + kind!(Use), + kind!(Identifier), + kind!(Dot), + kind!(Identifier), + kind!(Dot) + ] + ); // inside of `is` - cursor = Position::new(0, 15); + cursor = Position::new(0, 26); let tokens = tokenize_input(&input.symbols, input.source(), cursor); - assert_matches!(tokens[..], [kind!(Entity), kind!(Identifier), kind!(Is)]); + assert_matches!( + tokens[..], + [ + kind!(Use), + kind!(Identifier), + kind!(Dot), + kind!(Identifier), + kind!(Dot), + kind!(All) + ] + ); } } From 76f72f80dbe499143ddd94ddd9b2efc43554ab7d Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Wed, 9 Aug 2023 23:15:34 +0200 Subject: [PATCH 15/31] Allow double deref --- Cargo.lock | 245 +++++++++--------------- vhdl_lang/src/analysis/formal_region.rs | 2 + 2 files changed, 94 insertions(+), 153 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a73f1544..322fbfa0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,9 +52,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" +checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" dependencies = [ "anstyle", "windows-sys", @@ -86,9 +86,12 @@ checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -98,9 +101,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.3.10" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" +checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" dependencies = [ "clap_builder", "clap_derive", @@ -109,9 +112,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.10" +version = "4.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" +checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" dependencies = [ "anstream", "anstyle", @@ -121,14 +124,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.2" +version = "4.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" +checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -186,16 +189,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote", - "syn 1.0.109", -] - [[package]] name = "diff" version = "0.1.13" @@ -230,9 +223,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "env_logger" @@ -249,15 +242,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" dependencies = [ "errno-dragonfly", "libc", @@ -276,12 +269,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" [[package]] name = "fnv" @@ -329,9 +319,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "humantime" @@ -359,34 +349,14 @@ dependencies = [ "hashbrown", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys", -] - [[package]] name = "is-terminal" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" dependencies = [ "hermit-abi", - "rustix 0.38.1", + "rustix", "windows-sys", ] @@ -401,9 +371,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "libc" @@ -413,15 +383,9 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "linux-raw-sys" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" +checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" [[package]] name = "lock_api" @@ -441,9 +405,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3711e4d6f491dc9edc0f1df80e204f38206775ac92c1241e89b79229a850bc00" +checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" dependencies = [ "crossbeam-channel", "log", @@ -453,9 +417,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.94.0" +version = "0.94.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237" +checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" dependencies = [ "bitflags 1.3.2", "serde", @@ -495,15 +459,6 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi", -] - [[package]] name = "pad" version = "0.1.6" @@ -550,30 +505,28 @@ checksum = "268ad82d92622fb0a049ff14b01089b0f1bcd5c507fab44724394d328417348a" [[package]] name = "pretty_assertions" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "ctor", "diff", - "output_vt100", "yansi", ] [[package]] name = "proc-macro2" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.29" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" dependencies = [ "proc-macro2", ] @@ -631,85 +584,83 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.4" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" +checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" dependencies = [ "aho-corasick", "memchr", + "regex-automata", "regex-syntax", ] [[package]] -name = "regex-syntax" -version = "0.7.2" +name = "regex-automata" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" +checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] [[package]] -name = "rustix" -version = "0.37.21" +name = "regex-syntax" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" -dependencies = [ - "bitflags 1.3.2", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys 0.3.8", - "windows-sys", -] +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "rustix" -version = "0.38.1" +version = "0.38.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" +checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" dependencies = [ "bitflags 2.3.3", "errno", "libc", - "linux-raw-sys 0.4.3", + "linux-raw-sys", "windows-sys", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.156" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.156" +version = "1.0.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -718,13 +669,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.12" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" +checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -738,9 +689,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" [[package]] name = "strsim" @@ -750,20 +701,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.22" +version = "2.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" dependencies = [ "proc-macro2", "quote", @@ -772,15 +712,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.6.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" +checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" dependencies = [ - "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix 0.37.21", + "rustix", "windows-sys", ] @@ -795,22 +734,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.22", + "syn", ] [[package]] @@ -830,9 +769,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" +checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" dependencies = [ "serde", "serde_spanned", @@ -851,9 +790,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.11" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ "indexmap", "serde", @@ -870,9 +809,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -1049,9 +988,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.4.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" +checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" dependencies = [ "memchr", ] diff --git a/vhdl_lang/src/analysis/formal_region.rs b/vhdl_lang/src/analysis/formal_region.rs index 25cb1942..df6c29d0 100644 --- a/vhdl_lang/src/analysis/formal_region.rs +++ b/vhdl_lang/src/analysis/formal_region.rs @@ -266,6 +266,8 @@ impl<'a> std::ops::Deref for GpkgInterfaceEnt<'a> { GpkgInterfaceEnt::Type(typ) => typ.deref(), GpkgInterfaceEnt::Constant(obj) => obj.deref(), GpkgInterfaceEnt::Subprogram(subp) => subp.deref(), + // `ent` is of type `&&AnyEnt`. `deref()` returns `&AnyEnt` which is what we want + #[allow(suspicious_double_ref_op)] GpkgInterfaceEnt::Package(ent) => ent.deref(), } } From 54a6e7073acdf617b5704dc1156ce16789349647 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 12:05:23 +0200 Subject: [PATCH 16/31] Refactor: Use entity header instead of generic and port clause --- vhdl_lang/src/analysis/completion.rs | 14 +++++++++ vhdl_lang/src/analysis/design_unit.rs | 4 +-- vhdl_lang/src/ast.rs | 9 ++++-- vhdl_lang/src/ast/display.rs | 15 ++++++--- vhdl_lang/src/ast/search.rs | 4 +-- vhdl_lang/src/syntax/design_unit.rs | 45 ++++++++++++++++----------- 6 files changed, 63 insertions(+), 28 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 44b88a1e..00b95d1f 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -7,6 +7,20 @@ use crate::{Position, Source}; use itertools::Itertools; use std::default::Default; +/// Defines region types to make completions more accurate +pub enum RegionType { + /// The region of a file; not inside an entity, architecture, e.t.c. + Global, + /// Declarative region, i.e. entity declarative part, architecture declarative part, e.t.c. + Declarative, + /// Sequential Statements, i.e. inside a function + SequentialStatements, + /// Concurrent statements, i.e. inside an architecture statement part + ConcurrentStatements, + /// The header of an entity, defines ports and generics + EntityHeader, +} + macro_rules! kind { ($kind: pat) => { Token { kind: $kind, .. } diff --git a/vhdl_lang/src/analysis/design_unit.rs b/vhdl_lang/src/analysis/design_unit.rs index ff1ee001..6d0f2681 100644 --- a/vhdl_lang/src/analysis/design_unit.rs +++ b/vhdl_lang/src/analysis/design_unit.rs @@ -63,10 +63,10 @@ impl<'a> AnalyzeContext<'a> { // Entity name is visible primary_scope.make_potentially_visible(Some(unit.pos()), ent); - if let Some(ref mut list) = unit.generic_clause { + if let Some(ref mut list) = unit.header.generic_clause { self.analyze_interface_list(&primary_scope, ent, list, diagnostics)?; } - if let Some(ref mut list) = unit.port_clause { + if let Some(ref mut list) = unit.header.port_clause { self.analyze_interface_list(&primary_scope, ent, list, diagnostics)?; } self.define_labels_for_concurrent_part( diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index 1c285f01..dc4aa69a 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -1210,13 +1210,18 @@ pub struct ConfigurationDeclaration { pub end_ident_pos: Option, } +#[derive(PartialEq, Debug, Clone, Default)] +pub struct EntityHeader { + pub generic_clause: Option>, + pub port_clause: Option>, +} + /// LRM 3.2 Entity declarations #[derive(PartialEq, Debug, Clone)] pub struct EntityDeclaration { pub context_clause: ContextClause, pub ident: WithDecl, - pub generic_clause: Option>, - pub port_clause: Option>, + pub header: EntityHeader, pub decl: Vec, pub statements: Vec, pub end_ident_pos: Option, diff --git a/vhdl_lang/src/ast/display.rs b/vhdl_lang/src/ast/display.rs index e798c4a7..e0f65b51 100644 --- a/vhdl_lang/src/ast/display.rs +++ b/vhdl_lang/src/ast/display.rs @@ -1043,11 +1043,8 @@ impl Display for ConfigurationDeclaration { } } -impl Display for EntityDeclaration { +impl Display for EntityHeader { fn fmt(&self, f: &mut Formatter<'_>) -> Result { - // Not used: context_clause, decl, statements - write!(f, "entity {} is", self.ident)?; - if let Some(generic_clause) = &self.generic_clause { let mut first = true; for generic in generic_clause { @@ -1077,6 +1074,16 @@ impl Display for EntityDeclaration { write!(f, "\n );")?; } } + Ok(()) + } +} + +impl Display for EntityDeclaration { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + // Not used: context_clause, decl, statements + write!(f, "entity {} is", self.ident)?; + + write!(f, "{}", self.header)?; write!(f, "\nend entity;") } diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index b5f4df81..aa71d293 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -1214,8 +1214,8 @@ impl Search for EntityDeclaration { return_if_found!(searcher .search_decl(FoundDeclaration::Entity(self)) .or_not_found()); - return_if_found!(self.generic_clause.search(searcher)); - return_if_found!(self.port_clause.search(searcher)); + return_if_found!(self.header.generic_clause.search(searcher)); + return_if_found!(self.header.port_clause.search(searcher)); return_if_found!(self.decl.search(searcher)); self.statements.search(searcher) } diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 74b39ab5..19478baf 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -33,6 +33,11 @@ pub fn parse_entity_declaration( let generic_clause = parse_optional_generic_list(stream, diagnostics)?; let port_clause = parse_optional_port_list(stream, diagnostics)?; + let header = EntityHeader { + generic_clause, + port_clause + }; + let decl = parse_declarative_part(stream, diagnostics)?; let statements = if stream.skip_if_kind(Begin) { @@ -48,8 +53,7 @@ pub fn parse_entity_declaration( context_clause: ContextClause::default(), end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), ident, - generic_clause, - port_clause, + header, decl, statements, }) @@ -272,6 +276,7 @@ mod tests { use super::*; use crate::data::Diagnostic; + use crate::syntax::interface_declaration::parse_generic; use crate::syntax::test::{check_diagnostics, check_no_diagnostics, Code}; fn parse_str(code: &str) -> (Code, DesignFile, Vec) { @@ -305,8 +310,7 @@ mod tests { AnyDesignUnit::Primary(AnyPrimaryUnit::Entity(EntityDeclaration { context_clause: ContextClause::default(), ident: ident.into(), - generic_clause: None, - port_clause: None, + header: EntityHeader::default(), decl: vec![], statements: vec![], end_ident_pos, @@ -355,8 +359,10 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - generic_clause: Some(Vec::new()), - port_clause: None, + header: EntityHeader { + generic_clause: Some(vec![]), + port_clause: None, + }, decl: vec![], statements: vec![], end_ident_pos: None, @@ -380,8 +386,10 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - generic_clause: Some(vec![code.s1("runner_cfg : string").generic()]), - port_clause: None, + header: EntityHeader { + generic_clause: Some(vec![code.s1("runner_cfg : string").generic()]), + port_clause: None, + }, decl: vec![], statements: vec![], end_ident_pos: None, @@ -403,8 +411,10 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - generic_clause: None, - port_clause: Some(vec![]), + header: EntityHeader { + generic_clause: None, + port_clause: Some(vec![]), + }, decl: vec![], statements: vec![], end_ident_pos: None, @@ -426,8 +436,7 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - generic_clause: None, - port_clause: None, + header: EntityHeader::default(), decl: vec![], statements: vec![], end_ident_pos: None, @@ -449,8 +458,10 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - generic_clause: None, - port_clause: None, + header: EntityHeader { + port_clause: None, + generic_clause: None, + }, decl: code.s1("constant foo : natural := 0;").declarative_part(), statements: vec![], end_ident_pos: None, @@ -473,8 +484,7 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - generic_clause: None, - port_clause: None, + header: EntityHeader::default(), decl: vec![], statements: vec![code.s1("check(clk, valid);").concurrent_statement()], end_ident_pos: None, @@ -682,8 +692,7 @@ end entity; .map_into(ContextItem::Use), ], ident: code.s1("myent").decl_ident(), - generic_clause: None, - port_clause: None, + header: EntityHeader::default(), decl: vec![], statements: vec![], end_ident_pos: None From 7b103f1d2f7bd806a12ef2f6860be0ac96a1357d Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 12:40:59 +0200 Subject: [PATCH 17/31] Refactor: Architecture declarative part is a region --- vhdl_lang/src/analysis/design_unit.rs | 2 +- vhdl_lang/src/ast.rs | 10 +++++++++- vhdl_lang/src/ast/search.rs | 2 +- vhdl_lang/src/syntax/design_unit.rs | 27 +++++++++++++++++++++------ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/vhdl_lang/src/analysis/design_unit.rs b/vhdl_lang/src/analysis/design_unit.rs index 6d0f2681..32761edd 100644 --- a/vhdl_lang/src/analysis/design_unit.rs +++ b/vhdl_lang/src/analysis/design_unit.rs @@ -272,7 +272,7 @@ impl<'a> AnalyzeContext<'a> { scope.make_potentially_visible(Some(unit.pos()), arch); self.define_labels_for_concurrent_part(&scope, arch, &mut unit.statements, diagnostics)?; - self.analyze_declarative_part(&scope, arch, &mut unit.decl, diagnostics)?; + self.analyze_declarative_part(&scope, arch, &mut unit.decl.item, diagnostics)?; self.analyze_concurrent_part(&scope, arch, &mut unit.statements, diagnostics)?; scope.close(diagnostics); Ok(()) diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index dc4aa69a..8c0e3a09 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -1227,13 +1227,21 @@ pub struct EntityDeclaration { pub end_ident_pos: Option, } +/// Represents a region in the AST. +/// Additionally to some arbitrary payload, a region also knows the range it is in. +#[derive(PartialEq, Debug, Clone)] +pub struct WithRegion { + pub range: crate::data::Range, + pub item: T +} + /// LRM 3.3 Architecture bodies #[derive(PartialEq, Debug, Clone)] pub struct ArchitectureBody { pub context_clause: ContextClause, pub ident: WithDecl, pub entity_name: WithRef, - pub decl: Vec, + pub decl: WithRegion>, pub statements: Vec, pub end_ident_pos: Option, } diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index aa71d293..29a05b1e 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -1231,7 +1231,7 @@ impl Search for ArchitectureBody { return_if_found!(searcher .search_decl(FoundDeclaration::Architecture(self)) .or_not_found()); - return_if_found!(self.decl.search(searcher)); + return_if_found!(self.decl.item.search(searcher)); self.statements.search(searcher) } } diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 19478baf..127877f8 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -18,6 +18,7 @@ use super::declarative_part::{parse_declarative_part, parse_package_instantiatio use super::interface_declaration::parse_generic_interface_list; use crate::ast::*; use crate::data::*; +use crate::syntax::{Kind, Token}; /// Parse an entity declaration, token is initial entity token /// If a parse error occurs the stream is consumed until and end entity @@ -68,10 +69,16 @@ pub fn parse_architecture_body( let ident = WithDecl::new(stream.expect_ident()?); stream.expect_kind(Of)?; let entity_name = stream.expect_ident()?; - stream.expect_kind(Is)?; + let is_tok = stream.expect_kind(Is)?; let decl = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(Begin)?; + let begin_tok = stream.expect_kind(Begin)?; + + let decl_range = is_tok.pos.end().range_to(begin_tok.pos.start()); + let decl_region = WithRegion { + range: decl_range, + item: decl, + }; let statements = parse_labeled_concurrent_statements(stream, diagnostics)?; stream.expect_kind(End)?; @@ -85,7 +92,7 @@ pub fn parse_architecture_body( end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), ident, entity_name: entity_name.into_ref(), - decl, + decl: decl_region, statements, }) } @@ -273,6 +280,7 @@ pub fn parse_design_file( #[cfg(test)] mod tests { + use crate::ast::AttributeDesignator::Pos; use super::*; use crate::data::Diagnostic; @@ -525,12 +533,16 @@ end; ident: WithDecl, entity_name: Ident, end_ident_pos: Option, + decl_range: crate::data::Range, ) -> AnyDesignUnit { AnyDesignUnit::Secondary(AnySecondaryUnit::Architecture(ArchitectureBody { context_clause: ContextClause::default(), ident, entity_name: entity_name.into_ref(), - decl: Vec::new(), + decl: WithRegion { + item: Vec::new(), + range: decl_range, + }, statements: vec![], end_ident_pos, })) @@ -551,6 +563,7 @@ end architecture; WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), None, + Position::new(1, 34).range_to(Position::new(2, 0)), )] ); } @@ -569,7 +582,8 @@ end architecture arch_name; [simple_architecture( WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), - Some(code.s("arch_name", 2).pos()) + Some(code.s("arch_name", 2).pos()), + Position::new(1, 34).range_to(Position::new(2, 0)), )] ); } @@ -588,7 +602,8 @@ end; [simple_architecture( WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), - None + None, + Position::new(1, 34).range_to(Position::new(2, 0)), )] ); } From 9261b872699d7f507cc870bfa80d34e5fa2f2214 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 14:04:17 +0200 Subject: [PATCH 18/31] Implement capabilities for regions --- vhdl_lang/src/analysis/completion.rs | 116 ++++++++++++++++++--------- vhdl_lang/src/ast.rs | 2 +- vhdl_lang/src/ast/search.rs | 25 ++++++ vhdl_lang/src/syntax/design_unit.rs | 5 +- 4 files changed, 107 insertions(+), 41 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 00b95d1f..a8ac1b1b 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,4 +1,5 @@ use crate::analysis::DesignRoot; +use crate::ast::search::{Finished, Found, NotFinished, RegionCategory, SearchState, Searcher}; use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; use crate::data::{ContentReader, Symbol}; use crate::syntax::Kind::*; @@ -7,18 +8,29 @@ use crate::{Position, Source}; use itertools::Itertools; use std::default::Default; -/// Defines region types to make completions more accurate -pub enum RegionType { - /// The region of a file; not inside an entity, architecture, e.t.c. - Global, - /// Declarative region, i.e. entity declarative part, architecture declarative part, e.t.c. - Declarative, - /// Sequential Statements, i.e. inside a function - SequentialStatements, - /// Concurrent statements, i.e. inside an architecture statement part - ConcurrentStatements, - /// The header of an entity, defines ports and generics - EntityHeader, +struct RegionSearcher { + pub region: Option, + cursor: Position, +} + +impl RegionSearcher { + pub fn new(cursor: Position) -> RegionSearcher { + RegionSearcher { + region: None, + cursor, + } + } +} + +impl Searcher for RegionSearcher { + fn search_region(&mut self, region: crate::Range, kind: RegionCategory) -> SearchState { + if region.contains(self.cursor) { + self.region = Some(kind); + Finished(Found) + } else { + NotFinished + } + } } macro_rules! kind { @@ -148,33 +160,63 @@ impl DesignRoot { .map(|tok| tok.pos.end() == cursor) .unwrap_or(false); - match &tokens[..] { - [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { - self.list_all_libraries() - } - [.., kind!(Use), ident!(library), kind!(Dot)] - | [.., kind!(Use), ident!(library), kind!(Dot), kind!(Identifier)] => { - self.list_primaries_for_lib(library) - } - [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot)] - | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { - self.list_available_declarations(library, selected) - } - [.., kind!(Entity), kind!(Identifier)] => { - if cursor_at_end { - vec![] - } else { - vec!["is".to_string()] + let mut region_searcher = RegionSearcher::new(cursor); + let _ = self.search(&mut region_searcher); + match region_searcher.region { + Some(RegionCategory::Declarative) => match &tokens[..] { + [.., kind!(SemiColon)] | [.., kind!(SemiColon), kind!(Identifier)] => { + vec![ + "procedure".to_string(), + "pure function".to_string(), + "impure function".to_string(), + "function".to_string(), + "package".to_string(), + "type".to_string(), + "subtype".to_string(), + "constant".to_string(), + "signal".to_string(), + "variable".to_string(), + "shared variable".to_string(), + "file".to_string(), + "alias".to_string(), + "attribute".to_string(), + "component".to_string(), + "group".to_string(), + "configuration".to_string(), + "disconnect".to_string(), + "use".to_string(), + ] } - } - [.., kind!(Architecture), kind!(Identifier)] => { - if cursor_at_end { - vec![] - } else { - vec!["of".to_string()] + _ => vec![], + }, + _ => match &tokens[..] { + [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { + self.list_all_libraries() } - } - _ => vec![], + [.., kind!(Use), ident!(library), kind!(Dot)] + | [.., kind!(Use), ident!(library), kind!(Dot), kind!(Identifier)] => { + self.list_primaries_for_lib(library) + } + [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot)] + | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { + self.list_available_declarations(library, selected) + } + [.., kind!(Entity), kind!(Identifier)] => { + if cursor_at_end { + vec![] + } else { + vec!["is".to_string()] + } + } + [.., kind!(Architecture), kind!(Identifier)] => { + if cursor_at_end { + vec![] + } else { + vec!["of".to_string()] + } + } + _ => vec![], + }, } } } diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index 8c0e3a09..896f4284 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -1232,7 +1232,7 @@ pub struct EntityDeclaration { #[derive(PartialEq, Debug, Clone)] pub struct WithRegion { pub range: crate::data::Range, - pub item: T + pub item: T, } /// LRM 3.3 Architecture bodies diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index 29a05b1e..615afb67 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -70,12 +70,33 @@ pub enum FoundDeclaration<'a> { SequentialStatement(&'a Ident, &'a mut Reference), } +#[derive(PartialEq)] +/// Defines region types to make completions more accurate +pub enum RegionCategory { + /// The region of a file; not inside an entity, architecture, e.t.c. + Global, + /// Declarative region, i.e. entity declarative part, architecture declarative part, e.t.c. + Declarative, + /// Sequential Statements, i.e. inside a function + SequentialStatements, + /// Concurrent statements, i.e. inside an architecture statement part + ConcurrentStatements, + /// The header of an entity, defines ports and generics + EntityHeader, + /// The region is unknown / erroneous + Unknown, +} + pub trait Searcher { /// Search an position that has a reference to a declaration fn search_pos_with_ref(&mut self, _pos: &SrcPos, _ref: &mut Reference) -> SearchState { NotFinished } + fn search_region(&mut self, _region: crate::data::Range, _kind: RegionCategory) -> SearchState { + NotFinished + } + /// Search a designator that has a reference to a declaration fn search_designator_ref( &mut self, @@ -98,6 +119,7 @@ pub trait Searcher { fn search_with_pos(&mut self, _pos: &SrcPos) -> SearchState { NotFinished } + fn search_source(&mut self, _source: &Source) -> SearchState { NotFinished } @@ -1231,6 +1253,9 @@ impl Search for ArchitectureBody { return_if_found!(searcher .search_decl(FoundDeclaration::Architecture(self)) .or_not_found()); + return_if_found!(searcher + .search_region(self.decl.range, RegionCategory::Declarative) + .or_not_found()); return_if_found!(self.decl.item.search(searcher)); self.statements.search(searcher) } diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 127877f8..a8c257bd 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -18,7 +18,6 @@ use super::declarative_part::{parse_declarative_part, parse_package_instantiatio use super::interface_declaration::parse_generic_interface_list; use crate::ast::*; use crate::data::*; -use crate::syntax::{Kind, Token}; /// Parse an entity declaration, token is initial entity token /// If a parse error occurs the stream is consumed until and end entity @@ -36,7 +35,7 @@ pub fn parse_entity_declaration( let header = EntityHeader { generic_clause, - port_clause + port_clause, }; let decl = parse_declarative_part(stream, diagnostics)?; @@ -280,8 +279,8 @@ pub fn parse_design_file( #[cfg(test)] mod tests { - use crate::ast::AttributeDesignator::Pos; use super::*; + use crate::ast::AttributeDesignator::Pos; use crate::data::Diagnostic; use crate::syntax::interface_declaration::parse_generic; From d8bda3dbf3433cea210f3491f3f1f66412974f92 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 16:46:09 +0200 Subject: [PATCH 19/31] Only search throught the current source when looking at completions --- vhdl_lang/src/analysis/completion.rs | 106 +++++++++++++++++++++++--- vhdl_lang/src/analysis/declarative.rs | 6 +- vhdl_lang/src/ast.rs | 4 +- vhdl_lang/src/ast/search.rs | 12 ++- vhdl_lang/src/syntax/design_unit.rs | 2 - vhdl_lang/src/syntax/subprogram.rs | 50 +++++++++--- 6 files changed, 147 insertions(+), 33 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index a8ac1b1b..b14645f1 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,5 +1,5 @@ use crate::analysis::DesignRoot; -use crate::ast::search::{Finished, Found, NotFinished, RegionCategory, SearchState, Searcher}; +use crate::ast::search::{NotFinished, RegionCategory, SearchState, Searcher, NotFound, Finished}; use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; use crate::data::{ContentReader, Symbol}; use crate::syntax::Kind::*; @@ -8,31 +8,110 @@ use crate::{Position, Source}; use itertools::Itertools; use std::default::Default; -struct RegionSearcher { - pub region: Option, +struct RegionSearcher<'a> { + region: Option<(RegionCategory, crate::Range)>, cursor: Position, + source: &'a Source, } -impl RegionSearcher { - pub fn new(cursor: Position) -> RegionSearcher { +impl <'a> RegionSearcher<'a> { + pub fn new(cursor: Position, source: &Source) -> RegionSearcher { RegionSearcher { region: None, cursor, + source } } + + pub fn region(&self) -> Option { + self.region.as_ref().map(|reg| reg.0.clone()) + } } -impl Searcher for RegionSearcher { +impl <'a> Searcher for RegionSearcher<'a> { fn search_region(&mut self, region: crate::Range, kind: RegionCategory) -> SearchState { if region.contains(self.cursor) { - self.region = Some(kind); - Finished(Found) - } else { + match &self.region { + Some((_, old_region)) => { + // The new region is more specific than the old region + if region.start >= old_region.start && region.end <= old_region.end { + self.region = Some((kind, region)) + } + } + None => self.region = Some((kind, region)), + } + } + NotFinished + } + + fn search_source(&mut self, source: &Source) -> SearchState { + if source == self.source { NotFinished + } else { + Finished(NotFound) } } } +#[cfg(test)] +mod region_searcher_test { + use crate::analysis::tests::LibraryBuilder; + use super::*; + + #[test] + pub fn test_searcher_finds_region() { + let mut builder = LibraryBuilder::new(); + let code = builder.code("work", "\ +entity my_ent is +end entity; + +architecture arch of my_ent is + signal x: natural := 4; +begin + +end; + "); + let (root, _) = builder.get_analyzed_root(); + let mut searcher = RegionSearcher::new(Position::new(4, 12), code.source()); + let _ = root.search(& mut searcher); + assert_eq!(searcher.region(), Some(RegionCategory::Declarative)); + searcher = RegionSearcher::new(Position::new(6, 0), code.source()); + assert_eq!(searcher.region(), None); + } + + #[test] + pub fn test_searcher_finds_specific_region() { + let mut builder = LibraryBuilder::new(); + let code = builder.code("work", "\ +entity my_ent is +end entity; + +architecture arch of my_ent is + procedure my_proc is + variable x: bit := '0'; + begin + x := '1'; + + x := '1'; + + end procedure; +begin + +end; + "); + let (root, _) = builder.get_analyzed_root(); + let mut searcher = RegionSearcher::new(Position::new(5, 10), code.source()); + let _ = root.search(& mut searcher); + assert_eq!(searcher.region(), Some(RegionCategory::Declarative)); + searcher = RegionSearcher::new(Position::new(7, 12), code.source()); + let _ = root.search(& mut searcher); + assert_eq!(searcher.region(), Some(RegionCategory::SequentialStatements)); + searcher = RegionSearcher::new(Position::new(8, 0), code.source()); + let _ = root.search(& mut searcher); + assert_eq!(searcher.region(), Some(RegionCategory::SequentialStatements)); + } +} + macro_rules! kind { ($kind: pat) => { Token { kind: $kind, .. } @@ -160,11 +239,11 @@ impl DesignRoot { .map(|tok| tok.pos.end() == cursor) .unwrap_or(false); - let mut region_searcher = RegionSearcher::new(cursor); + let mut region_searcher = RegionSearcher::new(cursor, source); let _ = self.search(&mut region_searcher); - match region_searcher.region { + match region_searcher.region() { Some(RegionCategory::Declarative) => match &tokens[..] { - [.., kind!(SemiColon)] | [.., kind!(SemiColon), kind!(Identifier)] => { + [.., kind!(SemiColon | Is)] | [.., kind!(SemiColon | Is), kind!(Identifier)] => { vec![ "procedure".to_string(), "pure function".to_string(), @@ -189,6 +268,9 @@ impl DesignRoot { } _ => vec![], }, + Some(RegionCategory::SequentialStatements) => { + vec![] + } _ => match &tokens[..] { [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { self.list_all_libraries() diff --git a/vhdl_lang/src/analysis/declarative.rs b/vhdl_lang/src/analysis/declarative.rs index a372b9a0..ebec87ff 100644 --- a/vhdl_lang/src/analysis/declarative.rs +++ b/vhdl_lang/src/analysis/declarative.rs @@ -497,20 +497,20 @@ impl<'a> AnalyzeContext<'a> { self.define_labels_for_sequential_part( &subpgm_region, subpgm_ent.into(), - &mut body.statements, + &mut body.statements.item, diagnostics, )?; self.analyze_declarative_part( &subpgm_region, subpgm_ent.into(), - &mut body.declarations, + &mut body.declarations.item, diagnostics, )?; self.analyze_sequential_part( &subpgm_region, subpgm_ent.into(), - &mut body.statements, + &mut body.statements.item, diagnostics, )?; } diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index 896f4284..fbbb3758 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -652,8 +652,8 @@ pub struct FunctionSpecification { #[derive(PartialEq, Debug, Clone)] pub struct SubprogramBody { pub specification: SubprogramDeclaration, - pub declarations: Vec, - pub statements: Vec, + pub declarations: WithRegion>, + pub statements: WithRegion>, pub end_ident_pos: Option, } diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index 615afb67..606f082a 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -70,7 +70,7 @@ pub enum FoundDeclaration<'a> { SequentialStatement(&'a Ident, &'a mut Reference), } -#[derive(PartialEq)] +#[derive(PartialEq, Clone, Debug)] /// Defines region types to make completions more accurate pub enum RegionCategory { /// The region of a file; not inside an entity, architecture, e.t.c. @@ -988,8 +988,14 @@ impl Search for Declaration { } Declaration::SubprogramBody(body) => { return_if_found!(body.specification.search(searcher)); - return_if_found!(body.declarations.search(searcher)); - return_if_found!(body.statements.search(searcher)); + return_if_found!(searcher + .search_region(body.declarations.range, RegionCategory::Declarative) + .or_not_found()); + return_if_found!(body.declarations.item.search(searcher)); + return_if_found!(searcher + .search_region(body.statements.range, RegionCategory::SequentialStatements) + .or_not_found()); + return_if_found!(body.statements.item.search(searcher)); if let Some(ref end_ident_pos) = body.end_ident_pos { return_if_found!(searcher .search_pos_with_ref(end_ident_pos, body.specification.reference_mut()) diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index a8c257bd..2d8550ec 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -280,10 +280,8 @@ pub fn parse_design_file( #[cfg(test)] mod tests { use super::*; - use crate::ast::AttributeDesignator::Pos; use crate::data::Diagnostic; - use crate::syntax::interface_declaration::parse_generic; use crate::syntax::test::{check_diagnostics, check_no_diagnostics, Code}; fn parse_str(code: &str) -> (Code, DesignFile, Vec) { diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 719cbf66..813af869 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -12,6 +12,7 @@ use super::sequential_statement::parse_labeled_sequential_statements; use super::tokens::{kinds_error, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; +use crate::syntax::Token; pub fn parse_signature(stream: &TokenStream) -> ParseResult> { let left_square = stream.expect_kind(LeftSquare)?; @@ -136,6 +137,7 @@ pub fn parse_subprogram_declaration( /// LRM 4.3 Subprogram bodies pub fn parse_subprogram_body( stream: &TokenStream, + is_tok: &Token, specification: SubprogramDeclaration, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -146,13 +148,15 @@ pub fn parse_subprogram_body( } }; let declarations = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(Begin)?; + let begin_tok = stream.expect_kind(Begin)?; + let decl_range = is_tok.pos.end().range_to(begin_tok.pos.start()); let statements = parse_labeled_sequential_statements(stream, diagnostics)?; expect_token!( stream, - end_token, + end_tok, End => { + let stmt_range = begin_tok.pos.end().range_to(end_tok.pos.start()); stream.pop_if_kind(end_kind); let end_ident = if matches!(stream.peek_kind(), Some(Identifier | StringLiteral)) { @@ -165,8 +169,14 @@ pub fn parse_subprogram_body( Ok(SubprogramBody { end_ident_pos: check_end_identifier_mismatch(specification.subpgm_designator(), end_ident, diagnostics), specification, - declarations, - statements, + declarations: WithRegion { + range: decl_range, + item: declarations + }, + statements: WithRegion { + range: stmt_range, + item: statements + }, }) } ) @@ -181,7 +191,7 @@ pub fn parse_subprogram( stream, token, Is => { - Ok(Declaration::SubprogramBody(parse_subprogram_body(stream, specification, diagnostics)?)) + Ok(Declaration::SubprogramBody(parse_subprogram_body(stream, token, specification, diagnostics)?)) }, SemiColon => { Ok(Declaration::SubprogramDeclaration(specification)) @@ -442,8 +452,14 @@ end function; let statements = vec![code.s1("return foo + arg;").sequential_statement()]; let body = SubprogramBody { specification, - declarations, - statements, + declarations: WithRegion { + item: declarations, + range: Position::new(0, 45).range_to(Position::new(2, 0)), + }, + statements: WithRegion { + item: statements, + range: Position::new(2, 5).range_to(Position::new(4, 0)), + }, end_ident_pos: None, }; assert_eq!( @@ -482,8 +498,14 @@ end function foo; .subprogram_decl(); let body = SubprogramBody { specification, - declarations: vec![], - statements: vec![], + declarations: WithRegion { + item: vec![], + range: Position::new(0, 45).range_to(Position::new(1, 0)), + }, + statements: WithRegion { + item: vec![], + range: Position::new(1, 5).range_to(Position::new(2, 0)), + }, end_ident_pos: Some(code.s("foo", 2).pos()), }; assert_eq!( @@ -506,8 +528,14 @@ end function \"+\"; .subprogram_decl(); let body = SubprogramBody { specification, - declarations: vec![], - statements: vec![], + declarations: WithRegion { + item: vec![], + range: Position::new(0, 45).range_to(Position::new(1, 0)), + }, + statements: WithRegion { + item: vec![], + range: Position::new(1, 5).range_to(Position::new(2, 0)), + }, end_ident_pos: Some(code.s("\"+\"", 2).pos()), }; assert_eq!( From 3765cfdf536d22746c05fcaa7728fb021eee6c19 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 17:03:24 +0200 Subject: [PATCH 20/31] fmt --- vhdl_lang/src/analysis/completion.rs | 42 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index b14645f1..b9f00b42 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,5 +1,5 @@ use crate::analysis::DesignRoot; -use crate::ast::search::{NotFinished, RegionCategory, SearchState, Searcher, NotFound, Finished}; +use crate::ast::search::{Finished, NotFinished, NotFound, RegionCategory, SearchState, Searcher}; use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; use crate::data::{ContentReader, Symbol}; use crate::syntax::Kind::*; @@ -14,12 +14,12 @@ struct RegionSearcher<'a> { source: &'a Source, } -impl <'a> RegionSearcher<'a> { +impl<'a> RegionSearcher<'a> { pub fn new(cursor: Position, source: &Source) -> RegionSearcher { RegionSearcher { region: None, cursor, - source + source, } } @@ -28,7 +28,7 @@ impl <'a> RegionSearcher<'a> { } } -impl <'a> Searcher for RegionSearcher<'a> { +impl<'a> Searcher for RegionSearcher<'a> { fn search_region(&mut self, region: crate::Range, kind: RegionCategory) -> SearchState { if region.contains(self.cursor) { match &self.region { @@ -55,13 +55,15 @@ impl <'a> Searcher for RegionSearcher<'a> { #[cfg(test)] mod region_searcher_test { - use crate::analysis::tests::LibraryBuilder; use super::*; + use crate::analysis::tests::LibraryBuilder; #[test] pub fn test_searcher_finds_region() { let mut builder = LibraryBuilder::new(); - let code = builder.code("work", "\ + let code = builder.code( + "work", + "\ entity my_ent is end entity; @@ -70,10 +72,11 @@ architecture arch of my_ent is begin end; - "); + ", + ); let (root, _) = builder.get_analyzed_root(); let mut searcher = RegionSearcher::new(Position::new(4, 12), code.source()); - let _ = root.search(& mut searcher); + let _ = root.search(&mut searcher); assert_eq!(searcher.region(), Some(RegionCategory::Declarative)); searcher = RegionSearcher::new(Position::new(6, 0), code.source()); assert_eq!(searcher.region(), None); @@ -82,7 +85,9 @@ end; #[test] pub fn test_searcher_finds_specific_region() { let mut builder = LibraryBuilder::new(); - let code = builder.code("work", "\ + let code = builder.code( + "work", + "\ entity my_ent is end entity; @@ -98,17 +103,24 @@ architecture arch of my_ent is begin end; - "); + ", + ); let (root, _) = builder.get_analyzed_root(); let mut searcher = RegionSearcher::new(Position::new(5, 10), code.source()); - let _ = root.search(& mut searcher); + let _ = root.search(&mut searcher); assert_eq!(searcher.region(), Some(RegionCategory::Declarative)); searcher = RegionSearcher::new(Position::new(7, 12), code.source()); - let _ = root.search(& mut searcher); - assert_eq!(searcher.region(), Some(RegionCategory::SequentialStatements)); + let _ = root.search(&mut searcher); + assert_eq!( + searcher.region(), + Some(RegionCategory::SequentialStatements) + ); searcher = RegionSearcher::new(Position::new(8, 0), code.source()); - let _ = root.search(& mut searcher); - assert_eq!(searcher.region(), Some(RegionCategory::SequentialStatements)); + let _ = root.search(&mut searcher); + assert_eq!( + searcher.region(), + Some(RegionCategory::SequentialStatements) + ); } } From 085c9bdf9e0eaa39dbbde1c8e77ffff78cc73fd3 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 17:24:56 +0200 Subject: [PATCH 21/31] Add documentation --- vhdl_lang/src/analysis/completion.rs | 95 +++++++++++++++++++++------- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index b9f00b42..380cbcaa 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -8,6 +8,27 @@ use crate::{Position, Source}; use itertools::Itertools; use std::default::Default; +/// Finds the category of a region (i.e. whether the region is a declarative region, +/// a region with statements, e.t.c) for a given source file and cursor position. +/// Also takes nested regions into account and returns the most specific one. +/// For example, for an architecture: +/// ```vhdl +/// architecture arch of some_ent is +/// +/// procedure proc is +/// +/// begin +/// +/// end proc; +/// +/// begin +/// +/// end arch +/// ``` +/// If the cursor is inside the lines labeled with +/// - ``, the region is `RegionCategory::DeclarativeRegion` +/// - ``, the region is also `RegionCategory::DeclarativeRegion` +/// - ``, the region is `RegionCategory::SequentialStatements` struct RegionSearcher<'a> { region: Option<(RegionCategory, crate::Range)>, cursor: Position, @@ -205,6 +226,45 @@ fn tokenize_input(symbols: &Symbols, source: &Source, cursor: Position) -> Vec &'static [&'static str] { + &[ + "procedure", + "pure function", + "impure function", + "function", + "package", + "type", + "subtype", + "constant", + "signal", + "variable", + "shared variable", + "file", + "alias", + "attribute", + "component", + "group", + "configuration", + "disconnect", + "use", + ] +} + +fn completions_for_sequential_region() -> &'static [&'static str] { + &[ + "wait", + "assert", + "report", + "if", + "case", + "loop", + "next", + "exit", + "return", + "null" + ] +} + impl DesignRoot { /// helper function to list the name of all available libraries fn list_all_libraries(&self) -> Vec { @@ -256,32 +316,23 @@ impl DesignRoot { match region_searcher.region() { Some(RegionCategory::Declarative) => match &tokens[..] { [.., kind!(SemiColon | Is)] | [.., kind!(SemiColon | Is), kind!(Identifier)] => { - vec![ - "procedure".to_string(), - "pure function".to_string(), - "impure function".to_string(), - "function".to_string(), - "package".to_string(), - "type".to_string(), - "subtype".to_string(), - "constant".to_string(), - "signal".to_string(), - "variable".to_string(), - "shared variable".to_string(), - "file".to_string(), - "alias".to_string(), - "attribute".to_string(), - "component".to_string(), - "group".to_string(), - "configuration".to_string(), - "disconnect".to_string(), - "use".to_string(), - ] + completions_for_declarative_region() + .iter() + .map(|it| it.to_string()) + .collect_vec() } _ => vec![], }, Some(RegionCategory::SequentialStatements) => { - vec![] + match &tokens[..] { + [.., kind!(SemiColon | Begin)] | [.., kind!(SemiColon | Begin), kind!(Identifier)] => { + completions_for_sequential_region() + .iter() + .map(|it| it.to_string()) + .collect_vec() + } + _ => vec![], + } } _ => match &tokens[..] { [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { From 10eaef2e839cd01d3e3be8b20bd0e529c8632a96 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 17:33:53 +0200 Subject: [PATCH 22/31] fmt --- vhdl_lang/src/analysis/completion.rs | 30 ++++++++++------------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 380cbcaa..95b2a1c9 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -252,16 +252,7 @@ fn completions_for_declarative_region() -> &'static [&'static str] { fn completions_for_sequential_region() -> &'static [&'static str] { &[ - "wait", - "assert", - "report", - "if", - "case", - "loop", - "next", - "exit", - "return", - "null" + "wait", "assert", "report", "if", "case", "loop", "next", "exit", "return", "null", ] } @@ -323,17 +314,16 @@ impl DesignRoot { } _ => vec![], }, - Some(RegionCategory::SequentialStatements) => { - match &tokens[..] { - [.., kind!(SemiColon | Begin)] | [.., kind!(SemiColon | Begin), kind!(Identifier)] => { - completions_for_sequential_region() - .iter() - .map(|it| it.to_string()) - .collect_vec() - } - _ => vec![], + Some(RegionCategory::SequentialStatements) => match &tokens[..] { + [.., kind!(SemiColon | Begin)] + | [.., kind!(SemiColon | Begin), kind!(Identifier)] => { + completions_for_sequential_region() + .iter() + .map(|it| it.to_string()) + .collect_vec() } - } + _ => vec![], + }, _ => match &tokens[..] { [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { self.list_all_libraries() From d040f7fccc2398c73a5e56c9330e41ad39a299ac Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Thu, 10 Aug 2023 17:48:07 +0200 Subject: [PATCH 23/31] make sequential statements recoverable --- vhdl_lang/src/syntax/sequential_statement.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index f061c3a3..36a2a6b0 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -76,9 +76,13 @@ pub fn parse_labeled_sequential_statements( End | Else | Elsif | When => { break Ok(statements); } - _ => { - statements.push(parse_sequential_statement(stream, diagnostics)?); - } + _ => match parse_sequential_statement(stream, diagnostics) { + Ok(stmt) => statements.push(stmt), + Err(diag) => { + diagnostics.push(diag); + let _ = stream.skip_until(|kind| matches!(kind, End | Else | Elsif | When)); + } + }, } } } From b77b93b9fdbfbe2a9b8d78490a99aa56f940ba86 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 9 Sep 2023 13:12:45 +0200 Subject: [PATCH 24/31] clippy, fmt --- vhdl_lang/src/analysis/completion.rs | 14 ++++++++++---- vhdl_ls/src/vhdl_server.rs | 4 +++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 95b2a1c9..729d219e 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -267,7 +267,9 @@ impl DesignRoot { /// List the name of all primary units for a given library. /// If the library is non-resolvable, list an empty vector fn list_primaries_for_lib(&self, lib: &Symbol) -> Vec { - let Some(lib) = self.get_library_units(lib) else { return vec![]; }; + let Some(lib) = self.get_library_units(lib) else { + return vec![]; + }; lib.keys() .filter_map(|key| match key { UnitKey::Primary(prim) => Some(prim.name().to_string()), @@ -280,8 +282,12 @@ impl DesignRoot { /// If the library does not exist or there is no primary unit with the given name for that library, /// return an empty vector fn list_available_declarations(&self, lib: &Symbol, primary_unit: &Symbol) -> Vec { - let Some(lib) = self.get_library_units(lib) else { return vec![]; }; - let Some(unit) = lib.get(&UnitKey::Primary(primary_unit.clone())) else { return vec![]; }; + let Some(lib) = self.get_library_units(lib) else { + return vec![]; + }; + let Some(unit) = lib.get(&UnitKey::Primary(primary_unit.clone())) else { + return vec![]; + }; let unit = unit.unit.get(); match unit.unwrap().to_owned() { AnyDesignUnit::Primary(AnyPrimaryUnit::Package(pkg)) => pkg @@ -289,7 +295,7 @@ impl DesignRoot { .iter() .filter_map(declaration_to_string) .unique() - .chain(vec!["all".to_string()].into_iter()) + .chain(vec!["all".to_string()]) .collect_vec(), _ => Vec::default(), } diff --git a/vhdl_ls/src/vhdl_server.rs b/vhdl_ls/src/vhdl_server.rs index 8181e694..5c8d1efe 100644 --- a/vhdl_ls/src/vhdl_server.rs +++ b/vhdl_ls/src/vhdl_server.rs @@ -268,7 +268,9 @@ impl VHDLServer { // 1) get source position, and source file let Some(source) = self.project.get_source(file) else { // Do not enable completions for files that are not part of the project - return CompletionList {..Default::default()}; + return CompletionList { + ..Default::default() + }; }; let cursor = from_lsp_pos(params.text_document_position.position); // 2) Optimization chance: go to last recognizable token before the cursor. For example: From 9c3580fa3d478a296d91ee277009abe9313842d9 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 9 Sep 2023 13:13:28 +0200 Subject: [PATCH 25/31] restore Cargo.lock --- Cargo.lock | 245 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 153 insertions(+), 92 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 322fbfa0..a73f1544 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,9 +52,9 @@ dependencies = [ [[package]] name = "anstyle-wincon" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c677ab05e09154296dd37acecd46420c17b9713e8366facafa8fc0885167cf4c" +checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188" dependencies = [ "anstyle", "windows-sys", @@ -86,12 +86,9 @@ checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42" [[package]] name = "cc" -version = "1.0.82" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" -dependencies = [ - "libc", -] +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -101,9 +98,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.3.21" +version = "4.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c27cdf28c0f604ba3f512b0c9a409f8de8513e4816705deb0498b627e7c3a3fd" +checksum = "384e169cc618c613d5e3ca6404dda77a8685a63e08660dcc64abaf7da7cb0c7a" dependencies = [ "clap_builder", "clap_derive", @@ -112,9 +109,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.3.21" +version = "4.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a9f1ab5e9f01a9b81f202e8562eb9a10de70abf9eaeac1be465c28b75aa4aa" +checksum = "ef137bbe35aab78bdb468ccfba75a5f4d8321ae011d34063770780545176af2d" dependencies = [ "anstream", "anstyle", @@ -124,14 +121,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.3.12" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050" +checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -189,6 +186,16 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + [[package]] name = "diff" version = "0.1.13" @@ -223,9 +230,9 @@ checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" [[package]] name = "either" -version = "1.9.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "env_logger" @@ -242,15 +249,15 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" +checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", @@ -269,9 +276,12 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] [[package]] name = "fnv" @@ -319,9 +329,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "humantime" @@ -349,14 +359,34 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys", +] + [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "24fddda5af7e54bf7da53067d6e802dbcc381d0a8eef629df528e3ebf68755cb" dependencies = [ "hermit-abi", - "rustix", + "rustix 0.38.1", "windows-sys", ] @@ -371,9 +401,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" @@ -383,9 +413,15 @@ checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0" [[package]] name = "lock_api" @@ -405,9 +441,9 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "lsp-server" -version = "0.7.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ea9ae5a5082ca3b6ae824fc7666cd206b99168a4d4c769ad8fe9cc740df6a6" +checksum = "3711e4d6f491dc9edc0f1df80e204f38206775ac92c1241e89b79229a850bc00" dependencies = [ "crossbeam-channel", "log", @@ -417,9 +453,9 @@ dependencies = [ [[package]] name = "lsp-types" -version = "0.94.1" +version = "0.94.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66bfd44a06ae10647fe3f8214762e9369fd4248df1350924b4ef9e770a85ea1" +checksum = "0b63735a13a1f9cd4f4835223d828ed9c2e35c8c5e61837774399f558b6a1237" dependencies = [ "bitflags 1.3.2", "serde", @@ -459,6 +495,15 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +[[package]] +name = "output_vt100" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" +dependencies = [ + "winapi", +] + [[package]] name = "pad" version = "0.1.6" @@ -505,28 +550,30 @@ checksum = "268ad82d92622fb0a049ff14b01089b0f1bcd5c507fab44724394d328417348a" [[package]] name = "pretty_assertions" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" dependencies = [ + "ctor", "diff", + "output_vt100", "yansi", ] [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.32" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -584,83 +631,85 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f" dependencies = [ "aho-corasick", "memchr", - "regex-automata", "regex-syntax", ] [[package]] -name = "regex-automata" -version = "0.3.6" +name = "regex-syntax" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] +checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" [[package]] -name = "regex-syntax" -version = "0.7.4" +name = "rustix" +version = "0.37.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "62f25693a73057a1b4cb56179dd3c7ea21a7c6c5ee7d85781f5749b46f34b79c" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys", +] [[package]] name = "rustix" -version = "0.38.7" +version = "0.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172891ebdceb05aa0005f533a6cbfca599ddd7d966f6f5d4d9b2e70478e70399" +checksum = "fbc6396159432b5c8490d4e301d8c705f61860b8b6c863bf79942ce5401968f3" dependencies = [ "bitflags 2.3.3", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.3", "windows-sys", ] [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "scopeguard" -version = "1.2.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "serde" -version = "1.0.183" +version = "1.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" +checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.183" +version = "1.0.156" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" +checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 1.0.109", ] [[package]] name = "serde_json" -version = "1.0.104" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -669,13 +718,13 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.16" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" +checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -689,9 +738,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "strsim" @@ -701,9 +750,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.28" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" dependencies = [ "proc-macro2", "quote", @@ -712,14 +772,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.7.1" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", "fastrand", "redox_syscall 0.3.5", - "rustix", + "rustix 0.37.21", "windows-sys", ] @@ -734,22 +795,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.44" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.44" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.22", ] [[package]] @@ -769,9 +830,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.7.6" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "1ebafdf5ad1220cb59e7d17cf4d2c72015297b75b19a10472f99b89225089240" dependencies = [ "serde", "serde_spanned", @@ -790,9 +851,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7" dependencies = [ "indexmap", "serde", @@ -809,9 +870,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "unicode-normalization" @@ -988,9 +1049,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.5.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acaaa1190073b2b101e15083c38ee8ec891b5e05cbee516521e94ec008f61e64" +checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448" dependencies = [ "memchr", ] From 21bc45453e6e7e019399b4db1aa109815da634a0 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 9 Sep 2023 13:31:14 +0200 Subject: [PATCH 26/31] Don't complete simple items --- vhdl_lang/src/analysis/completion.rs | 67 ---------------------------- 1 file changed, 67 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 729d219e..df706f81 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -226,36 +226,6 @@ fn tokenize_input(symbols: &Symbols, source: &Source, cursor: Position) -> Vec &'static [&'static str] { - &[ - "procedure", - "pure function", - "impure function", - "function", - "package", - "type", - "subtype", - "constant", - "signal", - "variable", - "shared variable", - "file", - "alias", - "attribute", - "component", - "group", - "configuration", - "disconnect", - "use", - ] -} - -fn completions_for_sequential_region() -> &'static [&'static str] { - &[ - "wait", "assert", "report", "if", "case", "loop", "next", "exit", "return", "null", - ] -} - impl DesignRoot { /// helper function to list the name of all available libraries fn list_all_libraries(&self) -> Vec { @@ -303,33 +273,10 @@ impl DesignRoot { pub fn list_completion_options(&self, source: &Source, cursor: Position) -> Vec { let tokens = tokenize_input(&self.symbols, source, cursor); - let cursor_at_end = tokens - .last() - .map(|tok| tok.pos.end() == cursor) - .unwrap_or(false); let mut region_searcher = RegionSearcher::new(cursor, source); let _ = self.search(&mut region_searcher); match region_searcher.region() { - Some(RegionCategory::Declarative) => match &tokens[..] { - [.., kind!(SemiColon | Is)] | [.., kind!(SemiColon | Is), kind!(Identifier)] => { - completions_for_declarative_region() - .iter() - .map(|it| it.to_string()) - .collect_vec() - } - _ => vec![], - }, - Some(RegionCategory::SequentialStatements) => match &tokens[..] { - [.., kind!(SemiColon | Begin)] - | [.., kind!(SemiColon | Begin), kind!(Identifier)] => { - completions_for_sequential_region() - .iter() - .map(|it| it.to_string()) - .collect_vec() - } - _ => vec![], - }, _ => match &tokens[..] { [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { self.list_all_libraries() @@ -342,20 +289,6 @@ impl DesignRoot { | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { self.list_available_declarations(library, selected) } - [.., kind!(Entity), kind!(Identifier)] => { - if cursor_at_end { - vec![] - } else { - vec!["is".to_string()] - } - } - [.., kind!(Architecture), kind!(Identifier)] => { - if cursor_at_end { - vec![] - } else { - vec!["of".to_string()] - } - } _ => vec![], }, } From 708102f7ab121c6bc7ac2bb2f19a2f78b816f163 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 9 Sep 2023 13:31:52 +0200 Subject: [PATCH 27/31] Remove hardcoded positions --- vhdl_lang/src/syntax/design_unit.rs | 6 +++--- vhdl_lang/src/syntax/subprogram.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 2d8550ec..58e9b540 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -560,7 +560,7 @@ end architecture; WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), None, - Position::new(1, 34).range_to(Position::new(2, 0)), + code.s1("\nbegin").s1("\n").pos().range(), )] ); } @@ -580,7 +580,7 @@ end architecture arch_name; WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), Some(code.s("arch_name", 2).pos()), - Position::new(1, 34).range_to(Position::new(2, 0)), + code.s1("\nbegin").s1("\n").pos().range(), )] ); } @@ -600,7 +600,7 @@ end; WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), None, - Position::new(1, 34).range_to(Position::new(2, 0)), + code.s1("\nbegin").s1("\n").pos().range(), )] ); } diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 813af869..de3475a7 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -454,11 +454,11 @@ end function; specification, declarations: WithRegion { item: declarations, - range: Position::new(0, 45).range_to(Position::new(2, 0)), + range: code.s1("\n constant foo : natural := 0;\n").pos().range(), }, statements: WithRegion { item: statements, - range: Position::new(2, 5).range_to(Position::new(4, 0)), + range: code.s1("\n return foo + arg;\n").pos().range(), }, end_ident_pos: None, }; @@ -500,11 +500,11 @@ end function foo; specification, declarations: WithRegion { item: vec![], - range: Position::new(0, 45).range_to(Position::new(1, 0)), + range: code.s1("\nbegin").s1("\n").pos().range, }, statements: WithRegion { item: vec![], - range: Position::new(1, 5).range_to(Position::new(2, 0)), + range: code.s1("begin\n").s1("\n").pos().range, }, end_ident_pos: Some(code.s("foo", 2).pos()), }; @@ -530,11 +530,11 @@ end function \"+\"; specification, declarations: WithRegion { item: vec![], - range: Position::new(0, 45).range_to(Position::new(1, 0)), + range: code.s1("\nbegin").s1("\n").pos().range, }, statements: WithRegion { item: vec![], - range: Position::new(1, 5).range_to(Position::new(2, 0)), + range: code.s1("begin\n").s1("\n").pos().range, }, end_ident_pos: Some(code.s("\"+\"", 2).pos()), }; From fe888fafc15a551dd00d1a2b20b93418b9db91fb Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 9 Sep 2023 13:45:30 +0200 Subject: [PATCH 28/31] clippy --- vhdl_lang/src/analysis/completion.rs | 45 ++++++++-------------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index df706f81..36bb8673 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -35,20 +35,6 @@ struct RegionSearcher<'a> { source: &'a Source, } -impl<'a> RegionSearcher<'a> { - pub fn new(cursor: Position, source: &Source) -> RegionSearcher { - RegionSearcher { - region: None, - cursor, - source, - } - } - - pub fn region(&self) -> Option { - self.region.as_ref().map(|reg| reg.0.clone()) - } -} - impl<'a> Searcher for RegionSearcher<'a> { fn search_region(&mut self, region: crate::Range, kind: RegionCategory) -> SearchState { if region.contains(self.cursor) { @@ -273,24 +259,19 @@ impl DesignRoot { pub fn list_completion_options(&self, source: &Source, cursor: Position) -> Vec { let tokens = tokenize_input(&self.symbols, source, cursor); - - let mut region_searcher = RegionSearcher::new(cursor, source); - let _ = self.search(&mut region_searcher); - match region_searcher.region() { - _ => match &tokens[..] { - [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { - self.list_all_libraries() - } - [.., kind!(Use), ident!(library), kind!(Dot)] - | [.., kind!(Use), ident!(library), kind!(Dot), kind!(Identifier)] => { - self.list_primaries_for_lib(library) - } - [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot)] - | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { - self.list_available_declarations(library, selected) - } - _ => vec![], - }, + match &tokens[..] { + [.., kind!(Library)] | [.., kind!(Use)] | [.., kind!(Use), kind!(Identifier)] => { + self.list_all_libraries() + } + [.., kind!(Use), ident!(library), kind!(Dot)] + | [.., kind!(Use), ident!(library), kind!(Dot), kind!(Identifier)] => { + self.list_primaries_for_lib(library) + } + [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot)] + | [.., kind!(Use), ident!(library), kind!(Dot), ident!(selected), kind!(Dot), kind!(StringLiteral | Identifier)] => { + self.list_available_declarations(library, selected) + } + _ => vec![], } } } From 4588cd081ebcea64fa8a9e4fea80713a420bc29a Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sat, 9 Sep 2023 13:57:04 +0200 Subject: [PATCH 29/31] remove unused tests --- vhdl_lang/src/analysis/completion.rs | 71 ---------------------------- 1 file changed, 71 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 36bb8673..3ea67be3 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -60,77 +60,6 @@ impl<'a> Searcher for RegionSearcher<'a> { } } -#[cfg(test)] -mod region_searcher_test { - use super::*; - use crate::analysis::tests::LibraryBuilder; - - #[test] - pub fn test_searcher_finds_region() { - let mut builder = LibraryBuilder::new(); - let code = builder.code( - "work", - "\ -entity my_ent is -end entity; - -architecture arch of my_ent is - signal x: natural := 4; -begin - -end; - ", - ); - let (root, _) = builder.get_analyzed_root(); - let mut searcher = RegionSearcher::new(Position::new(4, 12), code.source()); - let _ = root.search(&mut searcher); - assert_eq!(searcher.region(), Some(RegionCategory::Declarative)); - searcher = RegionSearcher::new(Position::new(6, 0), code.source()); - assert_eq!(searcher.region(), None); - } - - #[test] - pub fn test_searcher_finds_specific_region() { - let mut builder = LibraryBuilder::new(); - let code = builder.code( - "work", - "\ -entity my_ent is -end entity; - -architecture arch of my_ent is - procedure my_proc is - variable x: bit := '0'; - begin - x := '1'; - - x := '1'; - - end procedure; -begin - -end; - ", - ); - let (root, _) = builder.get_analyzed_root(); - let mut searcher = RegionSearcher::new(Position::new(5, 10), code.source()); - let _ = root.search(&mut searcher); - assert_eq!(searcher.region(), Some(RegionCategory::Declarative)); - searcher = RegionSearcher::new(Position::new(7, 12), code.source()); - let _ = root.search(&mut searcher); - assert_eq!( - searcher.region(), - Some(RegionCategory::SequentialStatements) - ); - searcher = RegionSearcher::new(Position::new(8, 0), code.source()); - let _ = root.search(&mut searcher); - assert_eq!( - searcher.region(), - Some(RegionCategory::SequentialStatements) - ); - } -} - macro_rules! kind { ($kind: pat) => { Token { kind: $kind, .. } From 87b80d5e39171ed336bfba9b9c7a81ec5ff05db8 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sun, 10 Sep 2023 17:07:09 +0200 Subject: [PATCH 30/31] remove region related code --- vhdl_lang/src/analysis/completion.rs | 53 -------------------- vhdl_lang/src/analysis/declarative.rs | 6 +-- vhdl_lang/src/analysis/design_unit.rs | 6 +-- vhdl_lang/src/ast.rs | 23 ++------- vhdl_lang/src/ast/display.rs | 15 ++---- vhdl_lang/src/ast/search.rs | 41 ++-------------- vhdl_lang/src/syntax/design_unit.rs | 69 ++++++++++----------------- vhdl_lang/src/syntax/subprogram.rs | 50 +++++-------------- 8 files changed, 55 insertions(+), 208 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 3ea67be3..6e37e154 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -1,5 +1,4 @@ use crate::analysis::DesignRoot; -use crate::ast::search::{Finished, NotFinished, NotFound, RegionCategory, SearchState, Searcher}; use crate::ast::{AnyDesignUnit, AnyPrimaryUnit, Declaration, UnitKey}; use crate::data::{ContentReader, Symbol}; use crate::syntax::Kind::*; @@ -8,58 +7,6 @@ use crate::{Position, Source}; use itertools::Itertools; use std::default::Default; -/// Finds the category of a region (i.e. whether the region is a declarative region, -/// a region with statements, e.t.c) for a given source file and cursor position. -/// Also takes nested regions into account and returns the most specific one. -/// For example, for an architecture: -/// ```vhdl -/// architecture arch of some_ent is -/// -/// procedure proc is -/// -/// begin -/// -/// end proc; -/// -/// begin -/// -/// end arch -/// ``` -/// If the cursor is inside the lines labeled with -/// - ``, the region is `RegionCategory::DeclarativeRegion` -/// - ``, the region is also `RegionCategory::DeclarativeRegion` -/// - ``, the region is `RegionCategory::SequentialStatements` -struct RegionSearcher<'a> { - region: Option<(RegionCategory, crate::Range)>, - cursor: Position, - source: &'a Source, -} - -impl<'a> Searcher for RegionSearcher<'a> { - fn search_region(&mut self, region: crate::Range, kind: RegionCategory) -> SearchState { - if region.contains(self.cursor) { - match &self.region { - Some((_, old_region)) => { - // The new region is more specific than the old region - if region.start >= old_region.start && region.end <= old_region.end { - self.region = Some((kind, region)) - } - } - None => self.region = Some((kind, region)), - } - } - NotFinished - } - - fn search_source(&mut self, source: &Source) -> SearchState { - if source == self.source { - NotFinished - } else { - Finished(NotFound) - } - } -} - macro_rules! kind { ($kind: pat) => { Token { kind: $kind, .. } diff --git a/vhdl_lang/src/analysis/declarative.rs b/vhdl_lang/src/analysis/declarative.rs index ebec87ff..a372b9a0 100644 --- a/vhdl_lang/src/analysis/declarative.rs +++ b/vhdl_lang/src/analysis/declarative.rs @@ -497,20 +497,20 @@ impl<'a> AnalyzeContext<'a> { self.define_labels_for_sequential_part( &subpgm_region, subpgm_ent.into(), - &mut body.statements.item, + &mut body.statements, diagnostics, )?; self.analyze_declarative_part( &subpgm_region, subpgm_ent.into(), - &mut body.declarations.item, + &mut body.declarations, diagnostics, )?; self.analyze_sequential_part( &subpgm_region, subpgm_ent.into(), - &mut body.statements.item, + &mut body.statements, diagnostics, )?; } diff --git a/vhdl_lang/src/analysis/design_unit.rs b/vhdl_lang/src/analysis/design_unit.rs index 32761edd..ff1ee001 100644 --- a/vhdl_lang/src/analysis/design_unit.rs +++ b/vhdl_lang/src/analysis/design_unit.rs @@ -63,10 +63,10 @@ impl<'a> AnalyzeContext<'a> { // Entity name is visible primary_scope.make_potentially_visible(Some(unit.pos()), ent); - if let Some(ref mut list) = unit.header.generic_clause { + if let Some(ref mut list) = unit.generic_clause { self.analyze_interface_list(&primary_scope, ent, list, diagnostics)?; } - if let Some(ref mut list) = unit.header.port_clause { + if let Some(ref mut list) = unit.port_clause { self.analyze_interface_list(&primary_scope, ent, list, diagnostics)?; } self.define_labels_for_concurrent_part( @@ -272,7 +272,7 @@ impl<'a> AnalyzeContext<'a> { scope.make_potentially_visible(Some(unit.pos()), arch); self.define_labels_for_concurrent_part(&scope, arch, &mut unit.statements, diagnostics)?; - self.analyze_declarative_part(&scope, arch, &mut unit.decl.item, diagnostics)?; + self.analyze_declarative_part(&scope, arch, &mut unit.decl, diagnostics)?; self.analyze_concurrent_part(&scope, arch, &mut unit.statements, diagnostics)?; scope.close(diagnostics); Ok(()) diff --git a/vhdl_lang/src/ast.rs b/vhdl_lang/src/ast.rs index fbbb3758..1c285f01 100644 --- a/vhdl_lang/src/ast.rs +++ b/vhdl_lang/src/ast.rs @@ -652,8 +652,8 @@ pub struct FunctionSpecification { #[derive(PartialEq, Debug, Clone)] pub struct SubprogramBody { pub specification: SubprogramDeclaration, - pub declarations: WithRegion>, - pub statements: WithRegion>, + pub declarations: Vec, + pub statements: Vec, pub end_ident_pos: Option, } @@ -1210,38 +1210,25 @@ pub struct ConfigurationDeclaration { pub end_ident_pos: Option, } -#[derive(PartialEq, Debug, Clone, Default)] -pub struct EntityHeader { - pub generic_clause: Option>, - pub port_clause: Option>, -} - /// LRM 3.2 Entity declarations #[derive(PartialEq, Debug, Clone)] pub struct EntityDeclaration { pub context_clause: ContextClause, pub ident: WithDecl, - pub header: EntityHeader, + pub generic_clause: Option>, + pub port_clause: Option>, pub decl: Vec, pub statements: Vec, pub end_ident_pos: Option, } -/// Represents a region in the AST. -/// Additionally to some arbitrary payload, a region also knows the range it is in. -#[derive(PartialEq, Debug, Clone)] -pub struct WithRegion { - pub range: crate::data::Range, - pub item: T, -} - /// LRM 3.3 Architecture bodies #[derive(PartialEq, Debug, Clone)] pub struct ArchitectureBody { pub context_clause: ContextClause, pub ident: WithDecl, pub entity_name: WithRef, - pub decl: WithRegion>, + pub decl: Vec, pub statements: Vec, pub end_ident_pos: Option, } diff --git a/vhdl_lang/src/ast/display.rs b/vhdl_lang/src/ast/display.rs index e0f65b51..e798c4a7 100644 --- a/vhdl_lang/src/ast/display.rs +++ b/vhdl_lang/src/ast/display.rs @@ -1043,8 +1043,11 @@ impl Display for ConfigurationDeclaration { } } -impl Display for EntityHeader { +impl Display for EntityDeclaration { fn fmt(&self, f: &mut Formatter<'_>) -> Result { + // Not used: context_clause, decl, statements + write!(f, "entity {} is", self.ident)?; + if let Some(generic_clause) = &self.generic_clause { let mut first = true; for generic in generic_clause { @@ -1074,16 +1077,6 @@ impl Display for EntityHeader { write!(f, "\n );")?; } } - Ok(()) - } -} - -impl Display for EntityDeclaration { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - // Not used: context_clause, decl, statements - write!(f, "entity {} is", self.ident)?; - - write!(f, "{}", self.header)?; write!(f, "\nend entity;") } diff --git a/vhdl_lang/src/ast/search.rs b/vhdl_lang/src/ast/search.rs index 606f082a..b5f4df81 100644 --- a/vhdl_lang/src/ast/search.rs +++ b/vhdl_lang/src/ast/search.rs @@ -70,33 +70,12 @@ pub enum FoundDeclaration<'a> { SequentialStatement(&'a Ident, &'a mut Reference), } -#[derive(PartialEq, Clone, Debug)] -/// Defines region types to make completions more accurate -pub enum RegionCategory { - /// The region of a file; not inside an entity, architecture, e.t.c. - Global, - /// Declarative region, i.e. entity declarative part, architecture declarative part, e.t.c. - Declarative, - /// Sequential Statements, i.e. inside a function - SequentialStatements, - /// Concurrent statements, i.e. inside an architecture statement part - ConcurrentStatements, - /// The header of an entity, defines ports and generics - EntityHeader, - /// The region is unknown / erroneous - Unknown, -} - pub trait Searcher { /// Search an position that has a reference to a declaration fn search_pos_with_ref(&mut self, _pos: &SrcPos, _ref: &mut Reference) -> SearchState { NotFinished } - fn search_region(&mut self, _region: crate::data::Range, _kind: RegionCategory) -> SearchState { - NotFinished - } - /// Search a designator that has a reference to a declaration fn search_designator_ref( &mut self, @@ -119,7 +98,6 @@ pub trait Searcher { fn search_with_pos(&mut self, _pos: &SrcPos) -> SearchState { NotFinished } - fn search_source(&mut self, _source: &Source) -> SearchState { NotFinished } @@ -988,14 +966,8 @@ impl Search for Declaration { } Declaration::SubprogramBody(body) => { return_if_found!(body.specification.search(searcher)); - return_if_found!(searcher - .search_region(body.declarations.range, RegionCategory::Declarative) - .or_not_found()); - return_if_found!(body.declarations.item.search(searcher)); - return_if_found!(searcher - .search_region(body.statements.range, RegionCategory::SequentialStatements) - .or_not_found()); - return_if_found!(body.statements.item.search(searcher)); + return_if_found!(body.declarations.search(searcher)); + return_if_found!(body.statements.search(searcher)); if let Some(ref end_ident_pos) = body.end_ident_pos { return_if_found!(searcher .search_pos_with_ref(end_ident_pos, body.specification.reference_mut()) @@ -1242,8 +1214,8 @@ impl Search for EntityDeclaration { return_if_found!(searcher .search_decl(FoundDeclaration::Entity(self)) .or_not_found()); - return_if_found!(self.header.generic_clause.search(searcher)); - return_if_found!(self.header.port_clause.search(searcher)); + return_if_found!(self.generic_clause.search(searcher)); + return_if_found!(self.port_clause.search(searcher)); return_if_found!(self.decl.search(searcher)); self.statements.search(searcher) } @@ -1259,10 +1231,7 @@ impl Search for ArchitectureBody { return_if_found!(searcher .search_decl(FoundDeclaration::Architecture(self)) .or_not_found()); - return_if_found!(searcher - .search_region(self.decl.range, RegionCategory::Declarative) - .or_not_found()); - return_if_found!(self.decl.item.search(searcher)); + return_if_found!(self.decl.search(searcher)); self.statements.search(searcher) } } diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index 58e9b540..74b39ab5 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -33,11 +33,6 @@ pub fn parse_entity_declaration( let generic_clause = parse_optional_generic_list(stream, diagnostics)?; let port_clause = parse_optional_port_list(stream, diagnostics)?; - let header = EntityHeader { - generic_clause, - port_clause, - }; - let decl = parse_declarative_part(stream, diagnostics)?; let statements = if stream.skip_if_kind(Begin) { @@ -53,7 +48,8 @@ pub fn parse_entity_declaration( context_clause: ContextClause::default(), end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), ident, - header, + generic_clause, + port_clause, decl, statements, }) @@ -68,16 +64,10 @@ pub fn parse_architecture_body( let ident = WithDecl::new(stream.expect_ident()?); stream.expect_kind(Of)?; let entity_name = stream.expect_ident()?; - let is_tok = stream.expect_kind(Is)?; + stream.expect_kind(Is)?; let decl = parse_declarative_part(stream, diagnostics)?; - let begin_tok = stream.expect_kind(Begin)?; - - let decl_range = is_tok.pos.end().range_to(begin_tok.pos.start()); - let decl_region = WithRegion { - range: decl_range, - item: decl, - }; + stream.expect_kind(Begin)?; let statements = parse_labeled_concurrent_statements(stream, diagnostics)?; stream.expect_kind(End)?; @@ -91,7 +81,7 @@ pub fn parse_architecture_body( end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), ident, entity_name: entity_name.into_ref(), - decl: decl_region, + decl, statements, }) } @@ -315,7 +305,8 @@ mod tests { AnyDesignUnit::Primary(AnyPrimaryUnit::Entity(EntityDeclaration { context_clause: ContextClause::default(), ident: ident.into(), - header: EntityHeader::default(), + generic_clause: None, + port_clause: None, decl: vec![], statements: vec![], end_ident_pos, @@ -364,10 +355,8 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - header: EntityHeader { - generic_clause: Some(vec![]), - port_clause: None, - }, + generic_clause: Some(Vec::new()), + port_clause: None, decl: vec![], statements: vec![], end_ident_pos: None, @@ -391,10 +380,8 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - header: EntityHeader { - generic_clause: Some(vec![code.s1("runner_cfg : string").generic()]), - port_clause: None, - }, + generic_clause: Some(vec![code.s1("runner_cfg : string").generic()]), + port_clause: None, decl: vec![], statements: vec![], end_ident_pos: None, @@ -416,10 +403,8 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - header: EntityHeader { - generic_clause: None, - port_clause: Some(vec![]), - }, + generic_clause: None, + port_clause: Some(vec![]), decl: vec![], statements: vec![], end_ident_pos: None, @@ -441,7 +426,8 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - header: EntityHeader::default(), + generic_clause: None, + port_clause: None, decl: vec![], statements: vec![], end_ident_pos: None, @@ -463,10 +449,8 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - header: EntityHeader { - port_clause: None, - generic_clause: None, - }, + generic_clause: None, + port_clause: None, decl: code.s1("constant foo : natural := 0;").declarative_part(), statements: vec![], end_ident_pos: None, @@ -489,7 +473,8 @@ end entity; EntityDeclaration { context_clause: ContextClause::default(), ident: code.s1("myent").decl_ident(), - header: EntityHeader::default(), + generic_clause: None, + port_clause: None, decl: vec![], statements: vec![code.s1("check(clk, valid);").concurrent_statement()], end_ident_pos: None, @@ -530,16 +515,12 @@ end; ident: WithDecl, entity_name: Ident, end_ident_pos: Option, - decl_range: crate::data::Range, ) -> AnyDesignUnit { AnyDesignUnit::Secondary(AnySecondaryUnit::Architecture(ArchitectureBody { context_clause: ContextClause::default(), ident, entity_name: entity_name.into_ref(), - decl: WithRegion { - item: Vec::new(), - range: decl_range, - }, + decl: Vec::new(), statements: vec![], end_ident_pos, })) @@ -560,7 +541,6 @@ end architecture; WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), None, - code.s1("\nbegin").s1("\n").pos().range(), )] ); } @@ -579,8 +559,7 @@ end architecture arch_name; [simple_architecture( WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), - Some(code.s("arch_name", 2).pos()), - code.s1("\nbegin").s1("\n").pos().range(), + Some(code.s("arch_name", 2).pos()) )] ); } @@ -599,8 +578,7 @@ end; [simple_architecture( WithDecl::new(code.s1("arch_name").ident()), code.s1("myent").ident(), - None, - code.s1("\nbegin").s1("\n").pos().range(), + None )] ); } @@ -704,7 +682,8 @@ end entity; .map_into(ContextItem::Use), ], ident: code.s1("myent").decl_ident(), - header: EntityHeader::default(), + generic_clause: None, + port_clause: None, decl: vec![], statements: vec![], end_ident_pos: None diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index de3475a7..719cbf66 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -12,7 +12,6 @@ use super::sequential_statement::parse_labeled_sequential_statements; use super::tokens::{kinds_error, Kind::*, TokenStream}; use crate::ast::*; use crate::data::*; -use crate::syntax::Token; pub fn parse_signature(stream: &TokenStream) -> ParseResult> { let left_square = stream.expect_kind(LeftSquare)?; @@ -137,7 +136,6 @@ pub fn parse_subprogram_declaration( /// LRM 4.3 Subprogram bodies pub fn parse_subprogram_body( stream: &TokenStream, - is_tok: &Token, specification: SubprogramDeclaration, diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { @@ -148,15 +146,13 @@ pub fn parse_subprogram_body( } }; let declarations = parse_declarative_part(stream, diagnostics)?; - let begin_tok = stream.expect_kind(Begin)?; - let decl_range = is_tok.pos.end().range_to(begin_tok.pos.start()); + stream.expect_kind(Begin)?; let statements = parse_labeled_sequential_statements(stream, diagnostics)?; expect_token!( stream, - end_tok, + end_token, End => { - let stmt_range = begin_tok.pos.end().range_to(end_tok.pos.start()); stream.pop_if_kind(end_kind); let end_ident = if matches!(stream.peek_kind(), Some(Identifier | StringLiteral)) { @@ -169,14 +165,8 @@ pub fn parse_subprogram_body( Ok(SubprogramBody { end_ident_pos: check_end_identifier_mismatch(specification.subpgm_designator(), end_ident, diagnostics), specification, - declarations: WithRegion { - range: decl_range, - item: declarations - }, - statements: WithRegion { - range: stmt_range, - item: statements - }, + declarations, + statements, }) } ) @@ -191,7 +181,7 @@ pub fn parse_subprogram( stream, token, Is => { - Ok(Declaration::SubprogramBody(parse_subprogram_body(stream, token, specification, diagnostics)?)) + Ok(Declaration::SubprogramBody(parse_subprogram_body(stream, specification, diagnostics)?)) }, SemiColon => { Ok(Declaration::SubprogramDeclaration(specification)) @@ -452,14 +442,8 @@ end function; let statements = vec![code.s1("return foo + arg;").sequential_statement()]; let body = SubprogramBody { specification, - declarations: WithRegion { - item: declarations, - range: code.s1("\n constant foo : natural := 0;\n").pos().range(), - }, - statements: WithRegion { - item: statements, - range: code.s1("\n return foo + arg;\n").pos().range(), - }, + declarations, + statements, end_ident_pos: None, }; assert_eq!( @@ -498,14 +482,8 @@ end function foo; .subprogram_decl(); let body = SubprogramBody { specification, - declarations: WithRegion { - item: vec![], - range: code.s1("\nbegin").s1("\n").pos().range, - }, - statements: WithRegion { - item: vec![], - range: code.s1("begin\n").s1("\n").pos().range, - }, + declarations: vec![], + statements: vec![], end_ident_pos: Some(code.s("foo", 2).pos()), }; assert_eq!( @@ -528,14 +506,8 @@ end function \"+\"; .subprogram_decl(); let body = SubprogramBody { specification, - declarations: WithRegion { - item: vec![], - range: code.s1("\nbegin").s1("\n").pos().range, - }, - statements: WithRegion { - item: vec![], - range: code.s1("begin\n").s1("\n").pos().range, - }, + declarations: vec![], + statements: vec![], end_ident_pos: Some(code.s("\"+\"", 2).pos()), }; assert_eq!( From d8dd93862ca60a3da34ce13c1768d5d2b8a0a957 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Sun, 10 Sep 2023 17:54:45 +0200 Subject: [PATCH 31/31] Add testcases; use substring instead of hardcoded positions --- vhdl_lang/src/analysis/completion.rs | 48 +++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/vhdl_lang/src/analysis/completion.rs b/vhdl_lang/src/analysis/completion.rs index 6e37e154..d2440739 100644 --- a/vhdl_lang/src/analysis/completion.rs +++ b/vhdl_lang/src/analysis/completion.rs @@ -156,6 +156,7 @@ impl DesignRoot { mod test { use super::*; use crate::analysis::completion::tokenize_input; + use crate::analysis::tests::LibraryBuilder; use crate::syntax::test::Code; use assert_matches::assert_matches; @@ -169,22 +170,19 @@ mod test { #[test] fn tokenizing_stops_at_the_cursors_position() { let input = Code::new("use ieee.std_logic_1164.all"); - // mid of `my_ent` - let mut cursor = Position::new(0, 21); + let mut cursor = input.s1("std_logic_11").pos().end(); let tokens = tokenize_input(&input.symbols, input.source(), cursor); assert_matches!( tokens[..], [kind!(Use), kind!(Identifier), kind!(Dot), kind!(Identifier)] ); - // end of `my_ent` - cursor = Position::new(0, 23); + cursor = input.s1("std_logic_1164").pos().end(); let tokens = tokenize_input(&input.symbols, input.source(), cursor); assert_matches!( tokens[..], [kind!(Use), kind!(Identifier), kind!(Dot), kind!(Identifier)] ); - // start of `is` - cursor = Position::new(0, 24); + cursor = input.s1("std_logic_1164.").pos().end(); let tokens = tokenize_input(&input.symbols, input.source(), cursor); assert_matches!( tokens[..], @@ -196,8 +194,7 @@ mod test { kind!(Dot) ] ); - // inside of `is` - cursor = Position::new(0, 26); + cursor = input.s1("std_logic_1164.all").pos().end(); let tokens = tokenize_input(&input.symbols, input.source(), cursor); assert_matches!( tokens[..], @@ -211,4 +208,39 @@ mod test { ] ); } + + #[test] + pub fn completing_libraries() { + let input = LibraryBuilder::new(); + let code = Code::new("library "); + let (root, _) = input.get_analyzed_root(); + let cursor = code.s1("library ").pos().end(); + let options = root.list_completion_options(code.source(), cursor); + assert_eq!(options, root.list_all_libraries()) + } + + #[test] + pub fn completing_primaries() { + let (root, _) = LibraryBuilder::new().get_analyzed_root(); + let code = Code::new("use std."); + let cursor = code.pos().end(); + let options = root.list_completion_options(code.source(), cursor); + assert_eq!(options, vec!["textio", "standard", "env"]); + + let code = Code::new("use std.t"); + let cursor = code.pos().end(); + let options = root.list_completion_options(code.source(), cursor); + // Note that the filtering only happens at client side + assert_eq!(options, vec!["textio", "standard", "env"]); + } + + #[test] + pub fn completing_declarations() { + let input = LibraryBuilder::new(); + let code = Code::new("use std.env."); + let (root, _) = input.get_analyzed_root(); + let cursor = code.pos().end(); + let options = root.list_completion_options(code.source(), cursor); + assert_eq!(options, vec!["stop", "finish", "resolution_limit", "all"]) + } }