From b83bc22a95029b7c438807d45d4d073a7533dda7 Mon Sep 17 00:00:00 2001 From: Lukas Scheller Date: Wed, 10 Apr 2024 12:14:47 +0200 Subject: [PATCH] Add parsing context --- vhdl_lang/src/syntax/alias_declaration.rs | 23 +- vhdl_lang/src/syntax/attributes.rs | 43 +- vhdl_lang/src/syntax/common.rs | 22 +- vhdl_lang/src/syntax/component_declaration.rs | 67 ++- vhdl_lang/src/syntax/concurrent_statement.rs | 449 +++++++++--------- vhdl_lang/src/syntax/configuration.rs | 204 ++++---- vhdl_lang/src/syntax/context.rs | 86 ++-- vhdl_lang/src/syntax/declarative_part.rs | 67 ++- vhdl_lang/src/syntax/design_unit.rs | 203 ++++---- vhdl_lang/src/syntax/expression.rs | 146 +++--- vhdl_lang/src/syntax/interface_declaration.rs | 193 ++++---- vhdl_lang/src/syntax/names.rs | 212 ++++----- vhdl_lang/src/syntax/object_declaration.rs | 69 +-- vhdl_lang/src/syntax/parser.rs | 14 +- vhdl_lang/src/syntax/range.rs | 37 +- vhdl_lang/src/syntax/separated_list.rs | 71 ++- vhdl_lang/src/syntax/sequential_statement.rs | 332 +++++++------ vhdl_lang/src/syntax/subprogram.rs | 154 +++--- vhdl_lang/src/syntax/subtype_indication.rs | 99 ++-- vhdl_lang/src/syntax/test.rs | 191 ++++---- vhdl_lang/src/syntax/tokens/tokenstream.rs | 19 +- vhdl_lang/src/syntax/type_declaration.rs | 156 +++--- vhdl_lang/src/syntax/waveform.rs | 27 +- 23 files changed, 1405 insertions(+), 1479 deletions(-) diff --git a/vhdl_lang/src/syntax/alias_declaration.rs b/vhdl_lang/src/syntax/alias_declaration.rs index abc931b6..55d83445 100644 --- a/vhdl_lang/src/syntax/alias_declaration.rs +++ b/vhdl_lang/src/syntax/alias_declaration.rs @@ -8,32 +8,33 @@ 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::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; use crate::ast::{AliasDeclaration, WithDecl}; +use vhdl_lang::syntax::parser::ParsingContext; -pub fn parse_alias_declaration(stream: &TokenStream) -> ParseResult { - let start_token = stream.expect_kind(Alias)?; - let designator = WithDecl::new(parse_designator(stream)?); +pub fn parse_alias_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.expect_kind(Alias)?; + let designator = WithDecl::new(parse_designator(ctx)?); let subtype_indication = { - if stream.skip_if_kind(Colon) { - Some(parse_subtype_indication(stream)?) + if ctx.stream.skip_if_kind(Colon) { + Some(parse_subtype_indication(ctx)?) } else { None } }; - stream.expect_kind(Is)?; - let name = parse_name(stream)?; + ctx.stream.expect_kind(Is)?; + let name = parse_name(ctx)?; let signature = { - if stream.peek_kind() == Some(LeftSquare) { - Some(parse_signature(stream)?) + if ctx.stream.peek_kind() == Some(LeftSquare) { + Some(parse_signature(ctx)?) } else { None } }; - let end_token = stream.expect_kind(SemiColon)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(AliasDeclaration { span: TokenSpan::new(start_token, end_token), diff --git a/vhdl_lang/src/syntax/attributes.rs b/vhdl_lang/src/syntax/attributes.rs index 6897a0a9..046018f9 100644 --- a/vhdl_lang/src/syntax/attributes.rs +++ b/vhdl_lang/src/syntax/attributes.rs @@ -8,14 +8,15 @@ use super::common::ParseResult; use super::expression::parse_expression; use super::names::parse_type_mark; use super::subprogram::parse_signature; -use super::tokens::{Kind::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; use crate::ast::{ Attribute, AttributeDeclaration, AttributeSpecification, Designator, EntityClass, EntityName, EntityTag, WithRef, }; +use vhdl_lang::syntax::parser::ParsingContext; -fn parse_entity_class(stream: &TokenStream) -> ParseResult { - Ok(expect_token!(stream, token, +fn parse_entity_class(ctx: &mut ParsingContext<'_>) -> ParseResult { + Ok(expect_token!(ctx.stream, token, Entity => EntityClass::Entity, Architecture => EntityClass::Architecture, Configuration => EntityClass::Configuration, @@ -35,8 +36,8 @@ fn parse_entity_class(stream: &TokenStream) -> ParseResult { )) } -pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult> { - Ok(expect_token!(stream, token, +pub fn parse_entity_name_list(ctx: &mut ParsingContext<'_>) -> ParseResult> { + Ok(expect_token!(ctx.stream, token, Identifier | StringLiteral => { let mut entity_name_list = Vec::new(); let mut token = token; @@ -49,8 +50,8 @@ pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult ParseResult token); + if ctx.stream.skip_if_kind(Comma) { + token = expect_token!(ctx.stream, token, Identifier | StringLiteral => token); } else { break entity_name_list; } @@ -77,13 +78,13 @@ pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult ParseResult> { - let start_token = stream.expect_kind(Attribute)?; - let ident = stream.expect_ident()?; - Ok(expect_token!(stream, token, +pub fn parse_attribute(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let start_token = ctx.stream.expect_kind(Attribute)?; + let ident = ctx.stream.expect_ident()?; + Ok(expect_token!(ctx.stream, token, Colon => { - let type_mark = parse_type_mark(stream)?; - let end_token = stream.expect_kind(SemiColon)?; + let type_mark = parse_type_mark(ctx)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; vec![Attribute::Declaration(AttributeDeclaration { span: TokenSpan::new(start_token, end_token), ident: ident.into(), @@ -91,12 +92,12 @@ pub fn parse_attribute(stream: &TokenStream) -> ParseResult> { })] }, Of => { - let entity_names = parse_entity_name_list(stream)?; - stream.expect_kind(Colon)?; - let entity_class = parse_entity_class(stream)?; - stream.expect_kind(Is)?; - let expr = parse_expression(stream)?; - let end_token = stream.expect_kind(SemiColon)?; + let entity_names = parse_entity_name_list(ctx)?; + ctx.stream.expect_kind(Colon)?; + let entity_class = parse_entity_class(ctx)?; + ctx.stream.expect_kind(Is)?; + let expr = parse_expression(ctx)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; entity_names .into_iter() diff --git a/vhdl_lang/src/syntax/common.rs b/vhdl_lang/src/syntax/common.rs index 4698258f..b6061a95 100644 --- a/vhdl_lang/src/syntax/common.rs +++ b/vhdl_lang/src/syntax/common.rs @@ -4,25 +4,25 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{Kind, TokenStream}; +use super::tokens::Kind; use crate::ast::Ident; use crate::data::Diagnostic; -use crate::data::DiagnosticHandler; use crate::data::WithPos; +use crate::syntax::parser::ParsingContext; use crate::SrcPos; /// Parse optional part followed by optional keyword pub fn parse_optional( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, keyword: Kind, parse_fun: F, ) -> ParseResult> where - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&mut ParsingContext) -> ParseResult, { let optional = { - if stream.skip_if_kind(keyword) { - Some(parse_fun(stream)?) + if ctx.stream.skip_if_kind(keyword) { + Some(parse_fun(ctx)?) } else { None } @@ -32,15 +32,15 @@ where } pub fn check_end_identifier_mismatch( + ctx: &mut ParsingContext, ident: &WithPos, end_ident: Option>, - diagnostics: &mut dyn DiagnosticHandler, ) -> Option { if let Some(end_ident) = end_ident { if ident.item == end_ident.item { return Some(end_ident.pos); } else { - diagnostics.push(Diagnostic::syntax_error( + ctx.diagnostics.push(Diagnostic::syntax_error( &end_ident.pos, format!("End identifier mismatch, expected {}", ident.item), )); @@ -50,23 +50,23 @@ pub fn check_end_identifier_mismatch } pub fn check_label_identifier_mismatch( + ctx: &mut ParsingContext, label: Option<&Ident>, end_ident: Option, - diagnostics: &mut dyn DiagnosticHandler, ) -> Option { if let Some(ident) = label { if let Some(end_ident) = end_ident { if ident.item == end_ident.item { return Some(end_ident.pos); } else { - diagnostics.push(Diagnostic::syntax_error( + ctx.diagnostics.push(Diagnostic::syntax_error( &end_ident.pos, format!("End label mismatch, expected {}", ident.item), )); } } } else if let Some(end_ident) = end_ident { - diagnostics.push(Diagnostic::syntax_error( + ctx.diagnostics.push(Diagnostic::syntax_error( &end_ident.pos, format!( "End label '{}' found for unlabeled statement", diff --git a/vhdl_lang/src/syntax/component_declaration.rs b/vhdl_lang/src/syntax/component_declaration.rs index 1579eaaa..551fb7de 100644 --- a/vhdl_lang/src/syntax/component_declaration.rs +++ b/vhdl_lang/src/syntax/component_declaration.rs @@ -4,28 +4,28 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::common::check_end_identifier_mismatch; -use super::common::ParseResult; +use super::common::{check_end_identifier_mismatch, ParseResult}; use super::interface_declaration::{parse_generic_interface_list, parse_port_interface_list}; -use super::tokens::{Kind::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; use crate::ast::WithDecl; use crate::ast::{ComponentDeclaration, InterfaceDeclaration}; -use crate::data::{Diagnostic, DiagnosticHandler}; +use crate::data::Diagnostic; +use vhdl_lang::syntax::parser::ParsingContext; pub fn parse_optional_generic_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult>> { let mut list = None; loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { Generic => { - stream.skip(); - let new_list = parse_generic_interface_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + ctx.stream.skip(); + let new_list = parse_generic_interface_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; if list.is_some() { - diagnostics.push(Diagnostic::syntax_error(token, "Duplicate generic clause")); + ctx.diagnostics + .push(Diagnostic::syntax_error(token, "Duplicate generic clause")); } else { list = Some(new_list); } @@ -38,28 +38,28 @@ pub fn parse_optional_generic_list( } pub fn parse_optional_port_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult>> { let mut list = None; loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { Port => { - stream.skip(); - let new_list = parse_port_interface_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + ctx.stream.skip(); + let new_list = parse_port_interface_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; if list.is_some() { - diagnostics.push(Diagnostic::syntax_error(token, "Duplicate port clause")); + ctx.diagnostics + .push(Diagnostic::syntax_error(token, "Duplicate port clause")); } else { list = Some(new_list); } } Generic => { - stream.skip(); - parse_generic_interface_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; - diagnostics.push(Diagnostic::syntax_error( + ctx.stream.skip(); + parse_generic_interface_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; + ctx.diagnostics.push(Diagnostic::syntax_error( token, "Generic clause must come before port clause", )); @@ -72,23 +72,22 @@ pub fn parse_optional_port_list( } pub fn parse_component_declaration( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start_token = stream.expect_kind(Component)?; - let ident = WithDecl::new(stream.expect_ident()?); - stream.pop_if_kind(Is); + let start_token = ctx.stream.expect_kind(Component)?; + let ident = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.pop_if_kind(Is); - let generic_list = parse_optional_generic_list(stream, diagnostics)?; - let port_list = parse_optional_port_list(stream, diagnostics)?; - stream.expect_kind(End)?; - stream.expect_kind(Component)?; - let end_ident = stream.pop_optional_ident(); - let end_token = stream.expect_kind(SemiColon)?; + let generic_list = parse_optional_generic_list(ctx)?; + let port_list = parse_optional_port_list(ctx)?; + ctx.stream.expect_kind(End)?; + ctx.stream.expect_kind(Component)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(ComponentDeclaration { span: TokenSpan::new(start_token, end_token), - end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident.tree, end_ident), ident, generic_list: generic_list.unwrap_or_default(), port_list: port_list.unwrap_or_default(), diff --git a/vhdl_lang/src/syntax/concurrent_statement.rs b/vhdl_lang/src/syntax/concurrent_statement.rs index f236e415..3b759d3d 100644 --- a/vhdl_lang/src/syntax/concurrent_statement.rs +++ b/vhdl_lang/src/syntax/concurrent_statement.rs @@ -17,86 +17,83 @@ 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::Kind::*; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; use crate::syntax::{Kind, TokenAccess}; use crate::TokenId; +use vhdl_lang::syntax::parser::ParsingContext; use vhdl_lang::TokenSpan; /// LRM 11.2 Block statement pub fn parse_block_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let start_tok = stream.expect_kind(Block)?; - let token = stream.peek_expect()?; + let start_tok = ctx.stream.expect_kind(Block)?; + let token = ctx.stream.peek_expect()?; let guard_condition = { match token.kind { LeftPar => { - stream.skip(); - let expr = parse_expression(stream)?; - stream.pop_if_kind(RightPar); + ctx.stream.skip(); + let expr = parse_expression(ctx)?; + ctx.stream.pop_if_kind(RightPar); Some(expr) } _ => None, } }; - stream.pop_if_kind(Is); - let header = parse_block_header(stream, diagnostics)?; - let decl = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(Begin)?; - let statements = parse_labeled_concurrent_statements(stream, diagnostics)?; - stream.expect_kind(End)?; - stream.expect_kind(Block)?; - let end_ident = stream.pop_optional_ident(); - let end_tok = stream.expect_kind(SemiColon)?; + ctx.stream.pop_if_kind(Is); + let header = parse_block_header(ctx)?; + let decl = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(Begin)?; + let statements = parse_labeled_concurrent_statements(ctx)?; + ctx.stream.expect_kind(End)?; + ctx.stream.expect_kind(Block)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_tok = ctx.stream.expect_kind(SemiColon)?; Ok(BlockStatement { guard_condition, header, decl, statements, - end_label_pos: check_label_identifier_mismatch(label, end_ident, diagnostics), + end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident), span: TokenSpan::new(start_tok, end_tok), }) } -fn parse_block_header( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { +fn parse_block_header(ctx: &mut ParsingContext<'_>) -> ParseResult { let mut generic_clause = None; let mut generic_map = None; let mut port_clause = None; let mut port_map = None; loop { - let token_id = stream.get_current_token_id(); - let token = stream.peek_expect()?; + let token_id = ctx.stream.get_current_token_id(); + let token = ctx.stream.peek_expect()?; match token.kind { Generic => { - stream.skip(); - if let Some(map_token) = stream.pop_if_kind(Map) { + ctx.stream.skip(); + if let Some(map_token) = ctx.stream.pop_if_kind(Map) { if port_clause.is_some() || port_map.is_some() { - diagnostics.push(Diagnostic::syntax_error( - stream.get_token(map_token), + ctx.diagnostics.push(Diagnostic::syntax_error( + ctx.stream.get_token(map_token), "Generic map must come before port clause and port map", )); } else if generic_clause.is_none() { - diagnostics.push(Diagnostic::syntax_error( - stream.get_token(map_token), + ctx.diagnostics.push(Diagnostic::syntax_error( + ctx.stream.get_token(map_token), "Generic map declared without preceding generic clause", )); } else if generic_map.is_some() { - diagnostics.push(Diagnostic::syntax_error( - stream.get_token(map_token), + ctx.diagnostics.push(Diagnostic::syntax_error( + ctx.stream.get_token(map_token), "Duplicate generic map", )); } - let (list, closing_paren) = parse_association_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + let (list, closing_paren) = parse_association_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; if generic_map.is_none() { generic_map = Some(MapAspect { start: token_id, @@ -106,37 +103,37 @@ fn parse_block_header( } } else { if generic_map.is_some() { - diagnostics.push(Diagnostic::syntax_error( + ctx.diagnostics.push(Diagnostic::syntax_error( token, "Generic clause must come before generic map", )); } else if generic_clause.is_some() { - diagnostics + ctx.diagnostics .push(Diagnostic::syntax_error(token, "Duplicate generic clause")); } - let parsed_generic_list = parse_generic_interface_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + let parsed_generic_list = parse_generic_interface_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; if generic_clause.is_none() { generic_clause = Some(parsed_generic_list); } } } Port => { - stream.skip(); - if let Some(map_token) = stream.pop_if_kind(Map) { + ctx.stream.skip(); + if let Some(map_token) = ctx.stream.pop_if_kind(Map) { if port_clause.is_none() { - diagnostics.push(Diagnostic::syntax_error( - stream.get_token(map_token), + ctx.diagnostics.push(Diagnostic::syntax_error( + ctx.stream.get_token(map_token), "Port map declared without preceeding port clause", )); } else if port_map.is_some() { - diagnostics.push(Diagnostic::syntax_error( - stream.get_token(map_token), + ctx.diagnostics.push(Diagnostic::syntax_error( + ctx.stream.get_token(map_token), "Duplicate port map", )); } - let (list, closing_paren) = parse_association_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + let (list, closing_paren) = parse_association_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; if port_map.is_none() { port_map = Some(MapAspect { start: token_id, @@ -146,15 +143,16 @@ fn parse_block_header( } } else { if port_map.is_some() { - diagnostics.push(Diagnostic::syntax_error( + ctx.diagnostics.push(Diagnostic::syntax_error( token, "Port clause declared after port map", )); } else if port_clause.is_some() { - diagnostics.push(Diagnostic::syntax_error(token, "Duplicate port clause")); + ctx.diagnostics + .push(Diagnostic::syntax_error(token, "Duplicate port clause")); } - let parsed_port_list = parse_port_interface_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + let parsed_port_list = parse_port_interface_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; if port_clause.is_none() { port_clause = Some(parsed_port_list); } @@ -174,22 +172,21 @@ fn parse_block_header( /// LRM 11.3 Process statement pub fn parse_process_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, postponed: Option, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let process_token = stream.expect_kind(Process)?; - let sensitivity_list = if stream.skip_if_kind(LeftPar) { - peek_token!(stream, token, + let process_token = ctx.stream.expect_kind(Process)?; + let sensitivity_list = if ctx.stream.skip_if_kind(LeftPar) { + peek_token!(ctx.stream, token, All => { - stream.skip(); - stream.expect_kind(RightPar)?; + ctx.stream.skip(); + ctx.stream.expect_kind(RightPar)?; Some(SensitivityList::All) }, RightPar => { - stream.skip(); - diagnostics.push( + ctx.stream.skip(); + ctx.diagnostics.push( Diagnostic::syntax_error(token, "Processes with sensitivity lists must contain at least one element.") ); Some(SensitivityList::Names(Vec::new())) @@ -197,14 +194,14 @@ pub fn parse_process_statement( Identifier => { let mut names = Vec::with_capacity(1); loop { - names.push(parse_name(stream)?); - peek_token!(stream, token, + names.push(parse_name(ctx)?); + peek_token!(ctx.stream, token, RightPar => { - stream.skip(); + ctx.stream.skip(); break Some(SensitivityList::Names(names)); }, Comma => { - stream.skip(); + ctx.stream.skip(); }, Identifier => { } @@ -216,29 +213,29 @@ pub fn parse_process_statement( None }; - stream.pop_if_kind(Is); - let decl = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(Begin)?; - let statements = parse_labeled_sequential_statements(stream, diagnostics)?; - stream.expect_kind(End)?; + ctx.stream.pop_if_kind(Is); + let decl = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(Begin)?; + let statements = parse_labeled_sequential_statements(ctx)?; + ctx.stream.expect_kind(End)?; - if let Some(token) = stream.pop_if_kind(Postponed) { + if let Some(token) = ctx.stream.pop_if_kind(Postponed) { if postponed.is_none() { - diagnostics.push(Diagnostic::syntax_error( - stream.get_token(token), + ctx.diagnostics.push(Diagnostic::syntax_error( + ctx.stream.get_token(token), "'postponed' at the end of non-postponed process.", )); } } - stream.expect_kind(Process)?; - let end_ident = stream.pop_optional_ident(); - let end_tok = stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(Process)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_tok = ctx.stream.expect_kind(SemiColon)?; Ok(ProcessStatement { postponed: postponed.is_some(), sensitivity_list, decl, statements, - end_label_pos: check_label_identifier_mismatch(label, end_ident, diagnostics), + end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident), span: TokenSpan::new(postponed.unwrap_or(process_token), end_tok), }) } @@ -271,32 +268,32 @@ fn to_procedure_call( /// Assume target and <= is parsed already fn parse_assignment_known_target( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, target: WithPos, ) -> ParseResult { // @TODO postponed let postponed = false; // @TODO guarded let guarded = false; - let delay_mechanism = parse_delay_mechanism(stream)?; + let delay_mechanism = parse_delay_mechanism(ctx)?; Ok(ConcurrentStatement::Assignment( ConcurrentSignalAssignment { postponed, guarded, target, delay_mechanism, - rhs: parse_signal_assignment_right_hand(stream)?, + rhs: parse_signal_assignment_right_hand(ctx)?, }, )) } fn parse_assignment_or_procedure_call( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, target: WithPos, ) -> ParseResult { - expect_token!(stream, token, + expect_token!(ctx.stream, token, LTE => { - parse_assignment_known_target(stream, target) + parse_assignment_known_target(ctx, target) }, SemiColon => { Ok(ConcurrentStatement::ProcedureCall(to_procedure_call(target, false)?)) @@ -304,18 +301,18 @@ fn parse_assignment_or_procedure_call( } fn parse_selected_signal_assignment( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, postponed: bool, ) -> ParseResult { - stream.expect_kind(With)?; - let expression = parse_expression(stream)?; - stream.expect_kind(Select)?; - let target = parse_target(stream)?; - stream.expect_kind(LTE)?; + ctx.stream.expect_kind(With)?; + let expression = parse_expression(ctx)?; + ctx.stream.expect_kind(Select)?; + let target = parse_target(ctx)?; + ctx.stream.expect_kind(LTE)?; // @TODO guarded let guarded = false; - let delay_mechanism = parse_delay_mechanism(stream)?; - let rhs = AssignmentRightHand::Selected(parse_selection(stream, expression, parse_waveform)?); + let delay_mechanism = parse_delay_mechanism(ctx)?; + let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?); Ok(ConcurrentSignalAssignment { postponed, guarded, @@ -326,23 +323,22 @@ fn parse_selected_signal_assignment( } pub fn parse_concurrent_assert_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, postponed: bool, ) -> ParseResult { Ok(ConcurrentAssertStatement { postponed, - statement: parse_assert_statement(stream)?, + statement: parse_assert_statement(ctx)?, }) } pub fn parse_map_aspect( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, aspect_kind: Kind, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult> { - if let Some(aspect) = stream.pop_if_kind(aspect_kind) { - stream.expect_kind(Map)?; - let (list, closing_paren) = parse_association_list(stream, diagnostics)?; + if let Some(aspect) = ctx.stream.pop_if_kind(aspect_kind) { + ctx.stream.expect_kind(Map)?; + let (list, closing_paren) = parse_association_list(ctx)?; Ok(Some(MapAspect { start: aspect, list, @@ -354,41 +350,37 @@ pub fn parse_map_aspect( } pub fn parse_generic_and_port_map( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult<(Option, Option)> { - let generic_map = parse_map_aspect(stream, Generic, diagnostics)?; - let port_map = parse_map_aspect(stream, Port, diagnostics)?; + let generic_map = parse_map_aspect(ctx, Generic)?; + let port_map = parse_map_aspect(ctx, Port)?; Ok((generic_map, port_map)) } pub fn parse_instantiation_statement( + ctx: &mut ParsingContext<'_>, start_tok: TokenId, - stream: &TokenStream, unit: InstantiatedUnit, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let (generic_map, port_map) = parse_generic_and_port_map(stream, diagnostics)?; + let (generic_map, port_map) = parse_generic_and_port_map(ctx)?; - let end_tok = stream.expect_kind(SemiColon)?; + let end_tok = ctx.stream.expect_kind(SemiColon)?; - let inst = InstantiationStatement { + Ok(InstantiationStatement { unit, generic_map, port_map, span: TokenSpan::new(start_tok, end_tok), - }; - Ok(inst) + }) } fn parse_optional_declarative_part( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult>> { - if is_declarative_part(stream, true)? { - let decls = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(Begin)?; + if is_declarative_part(ctx, true)? { + let decls = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(Begin)?; Ok(Some(decls)) } else { Ok(None) @@ -396,29 +388,28 @@ fn parse_optional_declarative_part( } fn parse_generate_body( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, alternative_label: Option>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let decl = parse_optional_declarative_part(stream, diagnostics)?; - let statements = parse_labeled_concurrent_statements(stream, diagnostics)?; + let decl = parse_optional_declarative_part(ctx)?; + let statements = parse_labeled_concurrent_statements(ctx)?; let mut end_label_pos = None; // Potential inner end [ alternative_label ]; - if stream.next_kinds_are(&[End, SemiColon]) { + if ctx.stream.next_kinds_are(&[End, SemiColon]) { // Inner end no label - stream.skip(); - stream.skip(); - } else if stream.next_kinds_are(&[End, Identifier]) { - stream.skip(); + ctx.stream.skip(); + ctx.stream.skip(); + } else if ctx.stream.next_kinds_are(&[End, Identifier]) { + ctx.stream.skip(); // Inner with identifier - let end_ident = stream.expect_ident()?; + let end_ident = ctx.stream.expect_ident()?; end_label_pos = check_label_identifier_mismatch( + ctx, alternative_label.as_ref().map(|label| &label.tree), Some(end_ident), - diagnostics, ); - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; } let body = GenerateBody { @@ -433,49 +424,47 @@ fn parse_generate_body( /// 11.8 Generate statements fn parse_for_generate_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let start_tok = stream.expect_kind(For)?; - let index_name = WithDecl::new(stream.expect_ident()?); - stream.expect_kind(In)?; - let discrete_range = parse_discrete_range(stream)?; - stream.expect_kind(Generate)?; - let body = parse_generate_body(stream, None, diagnostics)?; - stream.expect_kind(End)?; - stream.expect_kind(Generate)?; - let end_ident = stream.pop_optional_ident(); - let end_tok = stream.expect_kind(SemiColon)?; + let start_tok = ctx.stream.expect_kind(For)?; + let index_name = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.expect_kind(In)?; + let discrete_range = parse_discrete_range(ctx)?; + ctx.stream.expect_kind(Generate)?; + let body = parse_generate_body(ctx, None)?; + ctx.stream.expect_kind(End)?; + ctx.stream.expect_kind(Generate)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_tok = ctx.stream.expect_kind(SemiColon)?; Ok(ForGenerateStatement { index_name, discrete_range, body, - end_label_pos: check_label_identifier_mismatch(label, end_ident, diagnostics), + end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident), span: TokenSpan::new(start_tok, end_tok), }) } /// 11.8 Generate statements fn parse_if_generate_statement( - stream: &TokenStream, + ctx: &mut ParsingContext, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let mut conditionals = Vec::new(); let else_branch; - let start_tok = stream.expect_kind(If)?; + let start_tok = ctx.stream.expect_kind(If)?; loop { - let mut condition = parse_expression(stream)?; + let mut condition = parse_expression(ctx)?; let mut alternative_label = None; - if stream.skip_if_kind(Colon) { + if ctx.stream.skip_if_kind(Colon) { alternative_label = Some(WithDecl::new(expression_to_ident(condition)?)); - condition = parse_expression(stream)?; + condition = parse_expression(ctx)?; } - stream.expect_kind(Generate)?; - let body = parse_generate_body(stream, alternative_label, diagnostics)?; + ctx.stream.expect_kind(Generate)?; + let body = parse_generate_body(ctx, alternative_label)?; let conditional = Conditional { condition, @@ -485,7 +474,7 @@ fn parse_if_generate_statement( conditionals.push(conditional); expect_token!( - stream, end_token, + ctx.stream, end_token, End => { else_branch = None; break; @@ -495,64 +484,63 @@ fn parse_if_generate_statement( }, Else => { let alternative_label = expect_token!( - stream, + ctx.stream, token, Generate => { None }, Identifier => { - stream.expect_kind(Colon)?; - stream.expect_kind(Generate)?; + ctx.stream.expect_kind(Colon)?; + ctx.stream.expect_kind(Generate)?; Some(WithDecl::new(token.to_identifier_value()?)) } ); - let body = parse_generate_body(stream, alternative_label, diagnostics)?; - stream.expect_kind(End)?; + let body = parse_generate_body(ctx, alternative_label)?; + ctx.stream.expect_kind(End)?; else_branch = Some(body); break; } ); } - stream.expect_kind(Generate)?; - let end_ident = stream.pop_optional_ident(); - let end_tok = stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(Generate)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_tok = ctx.stream.expect_kind(SemiColon)?; Ok(IfGenerateStatement { conds: Conditionals { conditionals, else_item: else_branch, }, - end_label_pos: check_label_identifier_mismatch(label, end_ident, diagnostics), + end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident), span: TokenSpan::new(start_tok, end_tok), }) } /// 11.8 Generate statements fn parse_case_generate_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let start_tok = stream.expect_kind(Case)?; - let expression = parse_expression(stream)?; - stream.expect_kind(Generate)?; - stream.expect_kind(When)?; + let start_tok = ctx.stream.expect_kind(Case)?; + let expression = parse_expression(ctx)?; + ctx.stream.expect_kind(Generate)?; + ctx.stream.expect_kind(When)?; let mut alternatives = Vec::with_capacity(2); loop { let alternative_label = { - if stream.next_kinds_are(&[Identifier, Colon]) { - let ident = stream.expect_ident()?; - stream.expect_kind(Colon)?; + if ctx.stream.next_kinds_are(&[Identifier, Colon]) { + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(Colon)?; Some(WithDecl::new(ident)) } else { None } }; - let choices = parse_choices(stream)?; - stream.expect_kind(RightArrow)?; - let body = parse_generate_body(stream, alternative_label, diagnostics)?; + let choices = parse_choices(ctx)?; + ctx.stream.expect_kind(RightArrow)?; + let body = parse_generate_body(ctx, alternative_label)?; alternatives.push(Alternative { choices, @@ -560,109 +548,108 @@ fn parse_case_generate_statement( }); expect_token!( - stream, end_token, + ctx.stream, end_token, End => break, When => continue ); } - stream.expect_kind(Generate)?; - let end_ident = stream.pop_optional_ident(); - let end_tok = stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(Generate)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_tok = ctx.stream.expect_kind(SemiColon)?; Ok(CaseGenerateStatement { sels: Selection { expression, alternatives, }, - end_label_pos: check_label_identifier_mismatch(label, end_ident, diagnostics), + end_label_pos: check_label_identifier_mismatch(ctx, label, end_ident), span: TokenSpan::new(start_tok, end_tok), }) } pub fn parse_concurrent_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let token = stream.peek_expect()?; - let start_tok = stream.get_current_token_id(); + let token = ctx.stream.peek_expect()?; + let start_tok = ctx.stream.get_current_token_id(); let statement = { try_init_token_kind!( token, Block => { - ConcurrentStatement::Block(parse_block_statement(stream, label, diagnostics)?) + ConcurrentStatement::Block(parse_block_statement(ctx, label)?) }, Process => { - ConcurrentStatement::Process(parse_process_statement(stream, label, None, diagnostics)?) + ConcurrentStatement::Process(parse_process_statement(ctx, label, None)?) }, Component => { - stream.skip(); - let unit = InstantiatedUnit::Component(parse_selected_name(stream)?); - ConcurrentStatement::Instance(parse_instantiation_statement(start_tok, stream, unit, diagnostics)?) + ctx.stream.skip(); + let unit = InstantiatedUnit::Component(parse_selected_name(ctx)?); + ConcurrentStatement::Instance(parse_instantiation_statement(ctx, start_tok, unit)?) }, Configuration => { - stream.skip(); - let unit = InstantiatedUnit::Configuration(parse_selected_name(stream)?); - ConcurrentStatement::Instance(parse_instantiation_statement(start_tok, stream, unit, diagnostics)?) + ctx.stream.skip(); + let unit = InstantiatedUnit::Configuration(parse_selected_name(ctx)?); + ConcurrentStatement::Instance(parse_instantiation_statement(ctx, start_tok, unit)?) }, Entity => { - stream.skip(); - let name = parse_selected_name(stream)?; + ctx.stream.skip(); + let name = parse_selected_name(ctx)?; let arch = { - if stream.skip_if_kind(LeftPar) { - let ident = stream.expect_ident()?; - stream.expect_kind(RightPar)?; + if ctx.stream.skip_if_kind(LeftPar) { + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(RightPar)?; Some(ident) } else { None } }; let unit = InstantiatedUnit::Entity(name, arch.map(WithRef::new)); - ConcurrentStatement::Instance(parse_instantiation_statement(start_tok, stream, unit, diagnostics)?) + ConcurrentStatement::Instance(parse_instantiation_statement(ctx, start_tok, unit)?) }, - For => ConcurrentStatement::ForGenerate(parse_for_generate_statement(stream, label, diagnostics)?), - If => ConcurrentStatement::IfGenerate(parse_if_generate_statement(stream, label, diagnostics)?), - Case => ConcurrentStatement::CaseGenerate(parse_case_generate_statement(stream, label, diagnostics)?), - Assert => ConcurrentStatement::Assert(parse_concurrent_assert_statement(stream, false)?), + For => ConcurrentStatement::ForGenerate(parse_for_generate_statement(ctx, label)?), + If => ConcurrentStatement::IfGenerate(parse_if_generate_statement(ctx, label)?), + Case => ConcurrentStatement::CaseGenerate(parse_case_generate_statement(ctx, label)?), + Assert => ConcurrentStatement::Assert(parse_concurrent_assert_statement(ctx, false)?), Postponed => { - let tok = stream.get_current_token_id(); - stream.skip(); - let token = stream.peek_expect()?; + let tok = ctx.stream.get_current_token_id(); + ctx.stream.skip(); + let token = ctx.stream.peek_expect()?; match token.kind { - Process => ConcurrentStatement::Process(parse_process_statement(stream, label, Some(tok), diagnostics)?), - Assert => ConcurrentStatement::Assert(parse_concurrent_assert_statement(stream, true)?), - With => ConcurrentStatement::Assignment(parse_selected_signal_assignment(stream, true)?), + Process => ConcurrentStatement::Process(parse_process_statement(ctx, label, Some(tok))?), + Assert => ConcurrentStatement::Assert(parse_concurrent_assert_statement(ctx, true)?), + With => ConcurrentStatement::Assignment(parse_selected_signal_assignment(ctx, true)?), _ => { - let target = parse_name(stream)?.map_into(Target::Name); - stream.expect_kind(SemiColon)?; + let target = parse_name(ctx)?.map_into(Target::Name); + ctx.stream.expect_kind(SemiColon)?; ConcurrentStatement::ProcedureCall(to_procedure_call(target, true)?) } } }, - With => ConcurrentStatement::Assignment(parse_selected_signal_assignment(stream, false)?), + With => ConcurrentStatement::Assignment(parse_selected_signal_assignment(ctx, false)?), Identifier => { - let name = parse_name(stream)?; - let token = stream.peek_expect()?; + let name = parse_name(ctx)?; + let token = ctx.stream.peek_expect()?; match token.kind { Generic|Port => { name.expect_selected()?; let unit = InstantiatedUnit::Component(name); - ConcurrentStatement::Instance(parse_instantiation_statement(start_tok, stream, unit, diagnostics)?) + ConcurrentStatement::Instance(parse_instantiation_statement(ctx, start_tok, unit)?) } _ => { - parse_assignment_or_procedure_call(stream, name.map_into(Target::Name))? + parse_assignment_or_procedure_call(ctx, name.map_into(Target::Name))? } } }, LtLt => { - let name = parse_name(stream)?; - stream.expect_kind(LTE)?; - parse_assignment_known_target(stream, name.map_into(Target::Name))? + let name = parse_name(ctx)?; + ctx.stream.expect_kind(LTE)?; + parse_assignment_known_target(ctx, name.map_into(Target::Name))? }, LeftPar => { - let target = parse_aggregate(stream)?.map_into(Target::Aggregate); - parse_assignment_or_procedure_call(stream, target)? + let target = parse_aggregate(ctx)?.map_into(Target::Aggregate); + parse_assignment_or_procedure_call(ctx, target)? } ) }; @@ -670,26 +657,25 @@ pub fn parse_concurrent_statement( } pub fn parse_labeled_concurrent_statements( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { let mut statements = Vec::new(); loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { End | Elsif | Else | When => { break Ok(statements); } - _ => match parse_labeled_concurrent_statement(stream, diagnostics) { + _ => match parse_labeled_concurrent_statement(ctx) { Ok(stmt) => { statements.push(stmt); } Err(diagnostic) => { - diagnostics.push(diagnostic); - stream.skip_until(|kind| { + ctx.diagnostics.push(diagnostic); + ctx.stream.skip_until(|kind| { matches!(kind, SemiColon | End | Process | Block | Assert) })?; - stream.pop_if_kind(SemiColon); + ctx.stream.pop_if_kind(SemiColon); } }, } @@ -697,18 +683,17 @@ pub fn parse_labeled_concurrent_statements( } pub fn parse_labeled_concurrent_statement( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start = stream.peek_expect()?; - if stream.next_kind_is(Identifier) { - let name = parse_name(stream)?; - if stream.skip_if_kind(Colon) { + let start = ctx.stream.peek_expect()?; + if ctx.stream.next_kind_is(Identifier) { + let name = parse_name(ctx)?; + if ctx.stream.skip_if_kind(Colon) { let label = Some(to_simple_name(name)?); - let start = stream.peek_expect()?; - let statement = parse_concurrent_statement(stream, label.as_ref(), diagnostics)?; - let end = stream.last().unwrap(); + let start = ctx.stream.peek_expect()?; + let statement = parse_concurrent_statement(ctx, label.as_ref())?; + let end = ctx.stream.last().unwrap(); Ok(LabeledConcurrentStatement { label: WithDecl::new(label), @@ -716,8 +701,8 @@ pub fn parse_labeled_concurrent_statement( }) } else { let target = name.map_into(Target::Name); - let statement = parse_assignment_or_procedure_call(stream, target)?; - let end = stream.last().unwrap(); + let statement = parse_assignment_or_procedure_call(ctx, target)?; + let end = ctx.stream.last().unwrap(); Ok(LabeledConcurrentStatement { label: WithDecl::new(None), @@ -725,8 +710,8 @@ pub fn parse_labeled_concurrent_statement( }) } } else { - let statement = parse_concurrent_statement(stream, None, diagnostics)?; - let end = stream.last().unwrap(); + let statement = parse_concurrent_statement(ctx, None)?; + let end = ctx.stream.last().unwrap(); Ok(LabeledConcurrentStatement { label: WithDecl::new(None), diff --git a/vhdl_lang/src/syntax/configuration.rs b/vhdl_lang/src/syntax/configuration.rs index eee2fd46..6124bdcd 100644 --- a/vhdl_lang/src/syntax/configuration.rs +++ b/vhdl_lang/src/syntax/configuration.rs @@ -9,23 +9,24 @@ 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::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; use crate::ast::*; use crate::data::*; +use vhdl_lang::syntax::parser::ParsingContext; /// LRM 7.3.2.2 -fn parse_entity_aspect(stream: &TokenStream) -> ParseResult { +fn parse_entity_aspect(ctx: &mut ParsingContext<'_>) -> ParseResult { let entity_aspect = expect_token!( - stream, + ctx.stream, token, Open => EntityAspect::Open, - Configuration => EntityAspect::Configuration(parse_selected_name(stream)?), + Configuration => EntityAspect::Configuration(parse_selected_name(ctx)?), Entity => { - let entity_name = parse_selected_name(stream)?; + let entity_name = parse_selected_name(ctx)?; let arch_name = { - if stream.skip_if_kind(LeftPar) { - let ident = stream.expect_ident()?; - stream.expect_kind(RightPar)?; + if ctx.stream.skip_if_kind(LeftPar) { + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(RightPar)?; Some(ident) } else { None @@ -38,13 +39,12 @@ fn parse_entity_aspect(stream: &TokenStream) -> ParseResult { } fn parse_binding_indication_known_entity_aspect( + ctx: &mut ParsingContext<'_>, entity_aspect: Option, - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let (generic_map, port_map) = parse_generic_and_port_map(stream, diagnostics)?; + let (generic_map, port_map) = parse_generic_and_port_map(ctx)?; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; Ok(BindingIndication { entity_aspect, generic_map, @@ -53,39 +53,35 @@ fn parse_binding_indication_known_entity_aspect( } /// LRM 7.3.2 -fn parse_binding_indication( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let entity_aspect = if stream.skip_if_kind(Use) { - Some(parse_entity_aspect(stream)?) +fn parse_binding_indication(ctx: &mut ParsingContext<'_>) -> ParseResult { + let entity_aspect = if ctx.stream.skip_if_kind(Use) { + Some(parse_entity_aspect(ctx)?) } else { None }; - parse_binding_indication_known_entity_aspect(entity_aspect, stream, diagnostics) + parse_binding_indication_known_entity_aspect(ctx, entity_aspect) } fn parse_component_configuration_known_spec( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, spec: ComponentSpecification, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let (bind_ind, vunit_bind_inds) = peek_token!( - stream, + ctx.stream, token, End => (None, Vec::new()), For => (None, Vec::new()), Use => { - stream.skip(); - if stream.peek_kind() == Some(Vunit) { - let vunit_bind_inds = parse_vunit_binding_indication_list_known_keyword(stream)?; + ctx.stream.skip(); + if ctx.stream.peek_kind() == Some(Vunit) { + let vunit_bind_inds = parse_vunit_binding_indication_list_known_keyword(ctx)?; (None, vunit_bind_inds) } else { - let aspect = parse_entity_aspect(stream)?; - let bind_ind = parse_binding_indication_known_entity_aspect(Some(aspect), stream, diagnostics)?; + let aspect = parse_entity_aspect(ctx)?; + let bind_ind = parse_binding_indication_known_entity_aspect(ctx, Some(aspect))?; - if stream.skip_if_kind(Use) { - (Some(bind_ind), parse_vunit_binding_indication_list_known_keyword(stream)?) + if ctx.stream.skip_if_kind(Use) { + (Some(bind_ind), parse_vunit_binding_indication_list_known_keyword(ctx)?) } else { (Some(bind_ind), Vec::new()) } @@ -94,18 +90,18 @@ fn parse_component_configuration_known_spec( ); let block_config = expect_token!( - stream, + ctx.stream, token, End => None, For => { - let block_config = parse_block_configuration_known_keyword(stream, diagnostics)?; - stream.expect_kind(End)?; + let block_config = parse_block_configuration_known_keyword(ctx)?; + ctx.stream.expect_kind(End)?; Some(block_config) } ); - stream.expect_kind(For)?; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(For)?; + ctx.stream.expect_kind(SemiColon)?; Ok(ComponentConfiguration { spec, bind_ind, @@ -120,14 +116,14 @@ enum ComponentSpecificationOrName { } fn parse_component_specification_or_name( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { peek_token!( - stream, token, + ctx.stream, token, All => { - stream.skip(); - stream.expect_kind(Colon)?; - let component_name = parse_selected_name(stream)?; + ctx.stream.skip(); + ctx.stream.expect_kind(Colon)?; + let component_name = parse_selected_name(ctx)?; Ok(ComponentSpecificationOrName::ComponentSpec(ComponentSpecification { instantiation_list: InstantiationList::All, component_name, @@ -135,40 +131,40 @@ fn parse_component_specification_or_name( }, Others => { - stream.skip(); - stream.expect_kind(Colon)?; - let component_name = parse_selected_name(stream)?; + ctx.stream.skip(); + ctx.stream.expect_kind(Colon)?; + let component_name = parse_selected_name(ctx)?; Ok(ComponentSpecificationOrName::ComponentSpec(ComponentSpecification { instantiation_list: InstantiationList::Others, component_name, })) }, Identifier => { - let name = parse_name(stream)?; - let sep_token = stream.peek_expect()?; + let name = parse_name(ctx)?; + let sep_token = ctx.stream.peek_expect()?; match sep_token.kind { Colon => { - stream.skip(); + ctx.stream.skip(); let ident = to_simple_name(name)?; - let component_name = parse_selected_name(stream)?; + let component_name = parse_selected_name(ctx)?; Ok(ComponentSpecificationOrName::ComponentSpec(ComponentSpecification { instantiation_list: InstantiationList::Labels(vec![ident]), component_name, })) } Comma => { - stream.skip(); + ctx.stream.skip(); let mut idents = vec![to_simple_name(name)?]; loop { - idents.push(stream.expect_ident()?); + idents.push(ctx.stream.expect_ident()?); expect_token!( - stream, + ctx.stream, next_token, Comma => {}, Colon => break ); } - let component_name = parse_selected_name(stream)?; + let component_name = parse_selected_name(ctx)?; Ok(ComponentSpecificationOrName::ComponentSpec(ComponentSpecification { instantiation_list: InstantiationList::Labels(idents), component_name, @@ -181,25 +177,23 @@ fn parse_component_specification_or_name( } fn parse_configuration_item_known_keyword( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - match parse_component_specification_or_name(stream)? { + match parse_component_specification_or_name(ctx)? { ComponentSpecificationOrName::ComponentSpec(component_spec) => { Ok(ConfigurationItem::Component( - parse_component_configuration_known_spec(stream, component_spec, diagnostics)?, + parse_component_configuration_known_spec(ctx, component_spec)?, )) } ComponentSpecificationOrName::Name(name) => Ok(ConfigurationItem::Block( - parse_block_configuration_known_name(stream, name, diagnostics)?, + parse_block_configuration_known_name(ctx, name)?, )), } } fn parse_block_configuration_known_name( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, name: WithPos, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let block_spec = name; // @TODO use clauses @@ -208,18 +202,18 @@ fn parse_block_configuration_known_name( loop { expect_token!( - stream, + ctx.stream, token, End => { break; }, For => { - items.push(parse_configuration_item_known_keyword(stream, diagnostics)?); + items.push(parse_configuration_item_known_keyword(ctx)?); } ); } - stream.expect_kind(For)?; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(For)?; + ctx.stream.expect_kind(SemiColon)?; Ok(BlockConfiguration { block_spec, use_clauses, @@ -228,31 +222,30 @@ fn parse_block_configuration_known_name( } fn parse_block_configuration_known_keyword( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let name = parse_name(stream)?; - parse_block_configuration_known_name(stream, name, diagnostics) + let name = parse_name(ctx)?; + parse_block_configuration_known_name(ctx, name) } fn parse_vunit_binding_indication_list_known_keyword( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { let mut indications = Vec::new(); loop { - stream.expect_kind(Vunit)?; + ctx.stream.expect_kind(Vunit)?; let mut vunit_list = Vec::new(); let vunit_bind_ind = loop { - vunit_list.push(parse_name(stream)?); + vunit_list.push(parse_name(ctx)?); peek_token!( - stream, token, + ctx.stream, token, Comma => { - stream.skip(); + ctx.stream.skip(); }, SemiColon => { - stream.skip(); + ctx.stream.skip(); break VUnitBindingIndication { vunit_list }; } ); @@ -260,7 +253,7 @@ fn parse_vunit_binding_indication_list_known_keyword( indications.push(vunit_bind_ind); - if !stream.skip_if_kind(Use) { + if !ctx.stream.skip_if_kind(Use) { break; } } @@ -269,46 +262,42 @@ fn parse_vunit_binding_indication_list_known_keyword( /// LRM 3.4 Configuration declaration pub fn parse_configuration_declaration( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start_token = stream.expect_kind(Configuration)?; - let ident = WithDecl::new(stream.expect_ident()?); - stream.expect_kind(Of)?; - let entity_name = parse_selected_name(stream)?; - stream.expect_kind(Is)?; + let start_token = ctx.stream.expect_kind(Configuration)?; + let ident = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.expect_kind(Of)?; + let entity_name = parse_selected_name(ctx)?; + ctx.stream.expect_kind(Is)?; let mut decl = Vec::new(); let vunit_bind_inds = loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { Use => { - if stream.nth_kind_is(1, Vunit) { - stream.skip(); - break parse_vunit_binding_indication_list_known_keyword(stream)?; + if ctx.stream.nth_kind_is(1, Vunit) { + ctx.stream.skip(); + break parse_vunit_binding_indication_list_known_keyword(ctx)?; } - decl.push(ConfigurationDeclarativeItem::Use(parse_use_clause( - stream, - diagnostics, - )?)); + decl.push(ConfigurationDeclarativeItem::Use(parse_use_clause(ctx)?)); } _ => break Vec::new(), } }; - stream.expect_kind(For)?; - let block_config = parse_block_configuration_known_keyword(stream, diagnostics)?; + ctx.stream.expect_kind(For)?; + let block_config = parse_block_configuration_known_keyword(ctx)?; - stream.expect_kind(End)?; - stream.pop_if_kind(Configuration); - let end_ident = stream.pop_optional_ident(); - let end_token = stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(End)?; + ctx.stream.pop_if_kind(Configuration); + let end_ident = ctx.stream.pop_optional_ident(); + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(ConfigurationDeclaration { span: TokenSpan::new(start_token, end_token), context_clause: ContextClause::default(), - end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident.tree, end_ident), ident, entity_name, decl, @@ -319,18 +308,17 @@ pub fn parse_configuration_declaration( /// LRM 7.3 Configuration Specification pub fn parse_configuration_specification( - stream: &TokenStream, - diagnsotics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start_token = stream.expect_kind(For)?; - match parse_component_specification_or_name(stream)? { + let start_token = ctx.stream.expect_kind(For)?; + match parse_component_specification_or_name(ctx)? { ComponentSpecificationOrName::ComponentSpec(spec) => { - let bind_ind = parse_binding_indication(stream, diagnsotics)?; - if stream.skip_if_kind(Use) { - let vunit_bind_inds = parse_vunit_binding_indication_list_known_keyword(stream)?; - stream.expect_kind(End)?; - stream.expect_kind(For)?; - let end_token = stream.expect_kind(SemiColon)?; + let bind_ind = parse_binding_indication(ctx)?; + if ctx.stream.skip_if_kind(Use) { + let vunit_bind_inds = parse_vunit_binding_indication_list_known_keyword(ctx)?; + ctx.stream.expect_kind(End)?; + ctx.stream.expect_kind(For)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(ConfigurationSpecification { span: TokenSpan::new(start_token, end_token), spec, @@ -338,11 +326,11 @@ pub fn parse_configuration_specification( vunit_bind_inds, }) } else { - if stream.skip_if_kind(End) { - stream.expect_kind(For)?; - stream.expect_kind(SemiColon)?; + if ctx.stream.skip_if_kind(End) { + ctx.stream.expect_kind(For)?; + ctx.stream.expect_kind(SemiColon)?; } - let end_token = stream.get_last_token_id(); + let end_token = ctx.stream.get_last_token_id(); Ok(ConfigurationSpecification { span: TokenSpan::new(start_token, end_token), spec, diff --git a/vhdl_lang/src/syntax/context.rs b/vhdl_lang/src/syntax/context.rs index 20a44597..49855c10 100644 --- a/vhdl_lang/src/syntax/context.rs +++ b/vhdl_lang/src/syntax/context.rs @@ -7,19 +7,22 @@ use super::common::check_end_identifier_mismatch; use super::common::ParseResult; use super::names::parse_name; -use super::tokens::{Kind::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; use crate::ast::*; -use crate::data::*; +use crate::syntax::parser::ParsingContext; use crate::syntax::separated_list::{parse_ident_list, parse_name_list}; +#[derive(PartialEq, Debug)] +pub enum DeclarationOrReference { + Declaration(ContextDeclaration), + Reference(ContextReference), +} + /// LRM 13. Design units and their analysis -pub fn parse_library_clause( - stream: &TokenStream, - diagnsotics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let library_token = stream.expect_kind(Library)?; - let name_list = parse_ident_list(stream, diagnsotics)?; - let semi_token = stream.expect_kind(SemiColon)?; +pub fn parse_library_clause(ctx: &mut ParsingContext<'_>) -> ParseResult { + let library_token = ctx.stream.expect_kind(Library)?; + let name_list = parse_ident_list(ctx)?; + let semi_token = ctx.stream.expect_kind(SemiColon)?; Ok(LibraryClause { span: TokenSpan::new(library_token, semi_token), name_list, @@ -27,34 +30,22 @@ pub fn parse_library_clause( } /// LRM 12.4. Use clauses -pub fn parse_use_clause( - stream: &TokenStream, - diagnsotics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let use_token = stream.expect_kind(Use)?; +pub fn parse_use_clause(ctx: &mut ParsingContext<'_>) -> ParseResult { + let use_token = ctx.stream.expect_kind(Use)?; - let name_list = parse_name_list(stream, diagnsotics)?; - let semi_token = stream.expect_kind(SemiColon)?; + let name_list = parse_name_list(ctx)?; + let semi_token = ctx.stream.expect_kind(SemiColon)?; Ok(UseClause { span: TokenSpan::new(use_token, semi_token), name_list, }) } -#[derive(PartialEq, Debug)] -pub enum DeclarationOrReference { - Declaration(ContextDeclaration), - Reference(ContextReference), -} - -pub fn parse_context_reference( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let context_token = stream.expect_kind(Context)?; +pub fn parse_context_reference(ctx: &mut ParsingContext<'_>) -> ParseResult { + let context_token = ctx.stream.expect_kind(Context)?; - let name_list = parse_name_list(stream, diagnostics)?; - let semi_token = stream.expect_kind(SemiColon)?; + let name_list = parse_name_list(ctx)?; + let semi_token = ctx.stream.expect_kind(SemiColon)?; Ok(ContextReference { span: TokenSpan::new(context_token, semi_token), name_list, @@ -62,37 +53,34 @@ pub fn parse_context_reference( } /// LRM 13.4 Context clauses -pub fn parse_context( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let context_token = stream.expect_kind(Context)?; - let name = parse_name(stream)?; - if stream.skip_if_kind(Is) { +pub fn parse_context(ctx: &mut ParsingContext<'_>) -> ParseResult { + let context_token = ctx.stream.expect_kind(Context)?; + let name = parse_name(ctx)?; + if ctx.stream.skip_if_kind(Is) { let mut items = Vec::with_capacity(16); let end_ident; loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; try_init_token_kind!( token, - Library => items.push(ContextItem::Library(parse_library_clause(stream, diagnostics)?)), - Use => items.push(ContextItem::Use(parse_use_clause(stream, diagnostics)?)), - Context => items.push(ContextItem::Context(parse_context_reference(stream, diagnostics)?)), + Library => items.push(ContextItem::Library(parse_library_clause(ctx)?)), + Use => items.push(ContextItem::Use(parse_use_clause(ctx)?)), + Context => items.push(ContextItem::Context(parse_context_reference(ctx)?)), End => { - stream.skip(); - stream.pop_if_kind(Context); - end_ident = stream.pop_optional_ident(); - stream.expect_kind(SemiColon)?; + ctx.stream.skip(); + ctx.stream.pop_if_kind(Context); + end_ident = ctx.stream.pop_optional_ident(); + ctx.stream.expect_kind(SemiColon)?; break; } ) } let ident = WithDecl::new(to_simple_name(name)?); - let end_token = stream.get_last_token_id(); + let end_token = ctx.stream.get_last_token_id(); Ok(DeclarationOrReference::Declaration(ContextDeclaration { span: TokenSpan::new(context_token, end_token), - end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident.tree, end_ident), ident, items, })) @@ -100,12 +88,12 @@ pub fn parse_context( // Context reference let mut items = vec![name]; let mut tokens = Vec::new(); - while let Some(comma) = stream.pop_if_kind(Comma) { - items.push(parse_name(stream)?); + while let Some(comma) = ctx.stream.pop_if_kind(Comma) { + items.push(parse_name(ctx)?); tokens.push(comma); } let name_list = SeparatedList { items, tokens }; - let semi_token = stream.expect_kind(SemiColon)?; + let semi_token = ctx.stream.expect_kind(SemiColon)?; Ok(DeclarationOrReference::Reference(ContextReference { span: TokenSpan::new(context_token, semi_token), name_list, diff --git a/vhdl_lang/src/syntax/declarative_part.rs b/vhdl_lang/src/syntax/declarative_part.rs index c759a214..73e9a141 100644 --- a/vhdl_lang/src/syntax/declarative_part.rs +++ b/vhdl_lang/src/syntax/declarative_part.rs @@ -16,20 +16,19 @@ use super::subprogram::parse_subprogram; use super::tokens::{Kind::*, *}; use super::type_declaration::parse_type_declaration; use crate::ast::{ContextClause, Declaration, PackageInstantiation}; -use crate::data::DiagnosticHandler; use crate::syntax::concurrent_statement::parse_map_aspect; +use vhdl_lang::syntax::parser::ParsingContext; pub fn parse_package_instantiation( - stream: &TokenStream, - diagnsotics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start_token = stream.expect_kind(Package)?; - let ident = stream.expect_ident()?; - stream.expect_kind(Is)?; - stream.expect_kind(New)?; - let package_name = parse_selected_name(stream)?; - let generic_map = parse_map_aspect(stream, Generic, diagnsotics)?; - let end_token = stream.expect_kind(SemiColon)?; + let start_token = ctx.stream.expect_kind(Package)?; + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(Is)?; + ctx.stream.expect_kind(New)?; + let package_name = parse_selected_name(ctx)?; + let generic_map = parse_map_aspect(ctx, Generic)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(PackageInstantiation { span: TokenSpan::new(start_token, end_token), @@ -40,8 +39,8 @@ pub fn parse_package_instantiation( }) } -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()) +pub fn is_declarative_part(ctx: &mut ParsingContext, begin_is_end: bool) -> ParseResult { + Ok(check_declarative_part(ctx.stream.peek_expect()?, !begin_is_end, begin_is_end).is_ok()) } fn check_declarative_part(token: &Token, may_end: bool, may_begin: bool) -> ParseResult<()> { @@ -61,10 +60,7 @@ fn check_declarative_part(token: &Token, may_end: bool, may_begin: bool) -> Pars } } -pub fn parse_declarative_part( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult> { +pub fn parse_declarative_part(ctx: &mut ParsingContext<'_>) -> ParseResult> { let mut declarations: Vec = Vec::new(); fn is_recover_token(kind: Kind) -> bool { @@ -91,21 +87,18 @@ pub fn parse_declarative_part( ) } - while let Some(token) = stream.peek() { + while let Some(token) = ctx.stream.peek() { match token.kind { Begin | End => break, Type | Subtype | Component | Impure | Pure | Function | Procedure | Package | For => { let decl = match token.kind { - Type | Subtype => { - parse_type_declaration(stream, diagnostics).map(Declaration::Type)? + Type | Subtype => parse_type_declaration(ctx).map(Declaration::Type)?, + Component => parse_component_declaration(ctx).map(Declaration::Component)?, + Impure | Pure | Function | Procedure => parse_subprogram(ctx)?, + Package => parse_package_instantiation(ctx).map(Declaration::Package)?, + For => { + parse_configuration_specification(ctx).map(Declaration::Configuration)? } - Component => parse_component_declaration(stream, diagnostics) - .map(Declaration::Component)?, - Impure | Pure | Function | Procedure => parse_subprogram(stream, diagnostics)?, - Package => parse_package_instantiation(stream, diagnostics) - .map(Declaration::Package)?, - For => parse_configuration_specification(stream, diagnostics) - .map(Declaration::Configuration)?, _ => unreachable!(), }; declarations.push(decl); @@ -113,18 +106,18 @@ pub fn parse_declarative_part( File | Shared | Constant | Signal | Variable | Attribute => { let decls: ParseResult> = match token.kind { - File => parse_file_declaration(stream) + File => parse_file_declaration(ctx) .map(|decls| decls.into_iter().map(Declaration::File).collect()), - Shared | Constant | Signal | Variable => parse_object_declaration(stream) + Shared | Constant | Signal | Variable => parse_object_declaration(ctx) .map(|decls| decls.into_iter().map(Declaration::Object).collect()), - Attribute => parse_attribute(stream) + Attribute => parse_attribute(ctx) .map(|decls| decls.into_iter().map(Declaration::Attribute).collect()), _ => unreachable!(), }; - match decls.or_recover_until(stream, diagnostics, is_recover_token) { + match decls.or_recover_until(ctx, is_recover_token) { Ok(ref mut decls) => declarations.append(decls), Err(err) => { - diagnostics.push(err); + ctx.diagnostics.push(err); continue; } } @@ -132,25 +125,25 @@ pub fn parse_declarative_part( Use | Alias => { let decl: ParseResult = match token.kind { - Use => parse_use_clause(stream, diagnostics).map(Declaration::Use), - Alias => parse_alias_declaration(stream).map(Declaration::Alias), + Use => parse_use_clause(ctx).map(Declaration::Use), + Alias => parse_alias_declaration(ctx).map(Declaration::Alias), _ => unreachable!(), }; - match decl.or_recover_until(stream, diagnostics, is_recover_token) { + match decl.or_recover_until(ctx, is_recover_token) { Ok(decl) => declarations.push(decl), Err(err) => { - diagnostics.push(err); + ctx.diagnostics.push(err); continue; } } } _ => { - diagnostics.push(token.kinds_error(&[ + ctx.diagnostics.push(token.kinds_error(&[ Type, Subtype, Component, Impure, Pure, Function, Procedure, Package, For, File, Shared, Constant, Signal, Variable, Attribute, Use, Alias, ])); - stream.skip_until(is_recover_token)?; + ctx.stream.skip_until(is_recover_token)?; continue; } } diff --git a/vhdl_lang/src/syntax/design_unit.rs b/vhdl_lang/src/syntax/design_unit.rs index ad29b150..1e7751bb 100644 --- a/vhdl_lang/src/syntax/design_unit.rs +++ b/vhdl_lang/src/syntax/design_unit.rs @@ -4,7 +4,8 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::tokens::{HasTokenSpan, Kind::*, TokenSpan, TokenStream}; +use super::tokens::{HasTokenSpan, Kind::*, TokenSpan}; +use vhdl_lang::syntax::parser::ParsingContext; use super::common::check_end_identifier_mismatch; use super::common::ParseResult; @@ -22,33 +23,30 @@ 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, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let start_token = stream.expect_kind(Entity)?; +pub fn parse_entity_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.expect_kind(Entity)?; - let ident = WithDecl::new(stream.expect_ident()?); - stream.expect_kind(Is)?; + let ident = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.expect_kind(Is)?; - let generic_clause = parse_optional_generic_list(stream, diagnostics)?; - let port_clause = parse_optional_port_list(stream, diagnostics)?; + let generic_clause = parse_optional_generic_list(ctx)?; + let port_clause = parse_optional_port_list(ctx)?; - let decl = parse_declarative_part(stream, diagnostics)?; + let decl = parse_declarative_part(ctx)?; - let statements = if stream.skip_if_kind(Begin) { - parse_labeled_concurrent_statements(stream, diagnostics)? + let statements = if ctx.stream.skip_if_kind(Begin) { + parse_labeled_concurrent_statements(ctx)? } else { Vec::new() }; - stream.pop_if_kind(End); - stream.pop_if_kind(Entity); - let end_ident = stream.pop_optional_ident(); - let end_token = stream.expect_kind(SemiColon)?; + ctx.stream.pop_if_kind(End); + ctx.stream.pop_if_kind(Entity); + let end_ident = ctx.stream.pop_optional_ident(); + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(EntityDeclaration { span: TokenSpan::new(start_token, end_token), context_clause: ContextClause::default(), - end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident.tree, end_ident), ident, generic_clause, port_clause, @@ -58,30 +56,27 @@ pub fn parse_entity_declaration( } /// LRM 3.3.1 -pub fn parse_architecture_body( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let start_token = stream.expect_kind(Architecture)?; - let ident = WithDecl::new(stream.expect_ident()?); - stream.expect_kind(Of)?; - let entity_name = stream.expect_ident()?; - stream.expect_kind(Is)?; - - let decl = parse_declarative_part(stream, diagnostics)?; - let begin_token = stream.expect_kind(Begin)?; - - let statements = parse_labeled_concurrent_statements(stream, diagnostics)?; - stream.expect_kind(End)?; - stream.pop_if_kind(Architecture); - - let end_ident = stream.pop_optional_ident(); - let end_token = stream.expect_kind(SemiColon)?; +pub fn parse_architecture_body(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.expect_kind(Architecture)?; + let ident = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.expect_kind(Of)?; + let entity_name = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(Is)?; + + let decl = parse_declarative_part(ctx)?; + let begin_token = ctx.stream.expect_kind(Begin)?; + + let statements = parse_labeled_concurrent_statements(ctx)?; + ctx.stream.expect_kind(End)?; + ctx.stream.pop_if_kind(Architecture); + + let end_ident = ctx.stream.pop_optional_ident(); + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(ArchitectureBody { span: TokenSpan::new(start_token, end_token), context_clause: ContextClause::default(), - end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident.tree, end_ident), begin_token, ident, entity_name: entity_name.into_ref(), @@ -91,32 +86,29 @@ pub fn parse_architecture_body( } /// LRM 4.7 Package declarations -pub fn parse_package_declaration( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let start_token = stream.expect_kind(Package)?; - let ident = WithDecl::new(stream.expect_ident()?); - - stream.expect_kind(Is)?; +pub fn parse_package_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.expect_kind(Package)?; + let ident = WithDecl::new(ctx.stream.expect_ident()?); + + ctx.stream.expect_kind(Is)?; let generic_clause = { - if stream.skip_if_kind(Generic) { - let decl = parse_generic_interface_list(stream, diagnostics)?; - stream.expect_kind(SemiColon)?; + if ctx.stream.skip_if_kind(Generic) { + let decl = parse_generic_interface_list(ctx)?; + ctx.stream.expect_kind(SemiColon)?; Some(decl) } else { None } }; - let decl = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(End)?; - stream.pop_if_kind(Package); - let end_ident = stream.pop_optional_ident(); - let end_token = stream.expect_kind(SemiColon)?; + let decl = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(End)?; + ctx.stream.pop_if_kind(Package); + let end_ident = ctx.stream.pop_optional_ident(); + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(PackageDeclaration { span: TokenSpan::new(start_token, end_token), context_clause: ContextClause::default(), - end_ident_pos: check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident.tree, end_ident), ident, generic_clause, decl, @@ -124,28 +116,25 @@ pub fn parse_package_declaration( } /// LRM 4.8 Package bodies -pub fn parse_package_body( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let start_token = stream.expect_kind(Package)?; - stream.expect_kind(Body)?; - let ident = stream.expect_ident()?; - - stream.expect_kind(Is)?; - let decl = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(End)?; - if stream.skip_if_kind(Package) { - stream.expect_kind(Body)?; +pub fn parse_package_body(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.expect_kind(Package)?; + ctx.stream.expect_kind(Body)?; + let ident = ctx.stream.expect_ident()?; + + ctx.stream.expect_kind(Is)?; + let decl = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(End)?; + if ctx.stream.skip_if_kind(Package) { + ctx.stream.expect_kind(Body)?; } - let end_ident = stream.pop_optional_ident(); - let end_token = stream.expect_kind(SemiColon)?; + let end_ident = ctx.stream.pop_optional_ident(); + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(PackageBody { span: TokenSpan::new(start_token, end_token), context_clause: ContextClause::default(), decl, - end_ident_pos: check_end_identifier_mismatch(&ident, end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, &ident, end_ident), ident: ident.into(), }) } @@ -164,107 +153,104 @@ fn context_item_message(context_item: &ContextItem, message: impl AsRef) -> format!("{} {}", prefix, message.as_ref()) } -pub fn parse_design_file( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { +pub fn parse_design_file(ctx: &mut ParsingContext<'_>) -> ParseResult { let mut context_clause = vec![]; let mut design_units = vec![]; - while let Some(token) = stream.peek() { + while let Some(token) = ctx.stream.peek() { try_init_token_kind!( token, Library => { - match parse_library_clause(stream, diagnostics) { + match parse_library_clause(ctx) { Ok(library) => { context_clause.push(ContextItem::Library(library)); }, - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), } }, Use => { - match parse_use_clause(stream, diagnostics) { + match parse_use_clause(ctx) { Ok(use_clause) => { context_clause.push(ContextItem::Use(use_clause)); }, - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), } }, - Context => match parse_context(stream, diagnostics) { + Context => match parse_context(ctx) { Ok(DeclarationOrReference::Declaration(context_decl)) => { if !context_clause.is_empty() { let mut diagnostic = Diagnostic::syntax_error(&context_decl.ident, "Context declaration may not be preceeded by a context clause"); for context_item in context_clause.iter() { - diagnostic.add_related(context_item.get_pos(stream), context_item_message(context_item, "may not come before context declaration")); + diagnostic.add_related(context_item.get_pos(ctx.stream), context_item_message(context_item, "may not come before context declaration")); } - diagnostics.push(diagnostic); + ctx.diagnostics.push(diagnostic); context_clause.clear(); } - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); design_units.push((tokens, AnyDesignUnit::Primary(AnyPrimaryUnit::Context(context_decl)))); } Ok(DeclarationOrReference::Reference(context_ref)) => { context_clause.push(ContextItem::Context(context_ref)); } - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), }, - Entity => match parse_entity_declaration(stream, diagnostics) { + Entity => match parse_entity_declaration(ctx) { Ok(mut entity) => { - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); entity.context_clause = take_context_clause(&mut context_clause); design_units.push((tokens, AnyDesignUnit::Primary(AnyPrimaryUnit::Entity(entity)))); } - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), }, - Architecture => match parse_architecture_body(stream, diagnostics) { + Architecture => match parse_architecture_body(ctx) { Ok(mut architecture) => { - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); architecture.context_clause = take_context_clause(&mut context_clause); design_units.push((tokens, AnyDesignUnit::Secondary(AnySecondaryUnit::Architecture(architecture)))); } - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), }, - Configuration => match parse_configuration_declaration(stream, diagnostics) { + Configuration => match parse_configuration_declaration(ctx) { Ok(mut configuration) => { - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); configuration.context_clause = take_context_clause(&mut context_clause); design_units.push((tokens, AnyDesignUnit::Primary(AnyPrimaryUnit::Configuration(configuration)))); } - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), }, Package => { - if stream.next_kinds_are(&[Package, Body]) { - match parse_package_body(stream, diagnostics) { + if ctx.stream.next_kinds_are(&[Package, Body]) { + match parse_package_body(ctx) { Ok(mut package_body) => { - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); package_body.context_clause = take_context_clause(&mut context_clause); design_units.push((tokens, AnyDesignUnit::Secondary(AnySecondaryUnit::PackageBody(package_body)))); } - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), }; - } else if stream.next_kinds_are(&[Package, Identifier, Is, New]) { - match parse_package_instantiation(stream, diagnostics) { + } else if ctx.stream.next_kinds_are(&[Package, Identifier, Is, New]) { + match parse_package_instantiation(ctx) { Ok(mut inst) => { - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); inst.context_clause = take_context_clause(&mut context_clause); design_units.push((tokens, AnyDesignUnit::Primary(AnyPrimaryUnit::PackageInstance(inst)))); }, - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), } } else { - match parse_package_declaration(stream, diagnostics) { + match parse_package_declaration(ctx) { Ok(mut package) => { - let tokens = stream.slice_tokens(); + let tokens = ctx.stream.slice_tokens(); package.context_clause = take_context_clause(&mut context_clause); design_units.push((tokens, AnyDesignUnit::Primary(AnyPrimaryUnit::Package(package)))); } - Err(diagnostic) => diagnostics.push(diagnostic), + Err(diagnostic) => ctx.diagnostics.push(diagnostic), }; } } @@ -272,8 +258,8 @@ pub fn parse_design_file( } for context_item in context_clause { - diagnostics.add( - context_item.get_pos(stream), + ctx.diagnostics.add( + context_item.get_pos(ctx.stream), context_item_message(&context_item, "not associated with any design unit"), ErrorCode::UnassociatedContext, ); @@ -294,8 +280,7 @@ mod tests { fn parse_str(code: &str) -> (Code, DesignFile, Vec) { let code = Code::new(code); - let mut diagnostics = vec![]; - let design_file = code.with_stream(|stream| parse_design_file(stream, &mut diagnostics)); + let (design_file, diagnostics) = code.with_stream_diagnostics(parse_design_file); (code, design_file, diagnostics) } diff --git a/vhdl_lang/src/syntax/expression.rs b/vhdl_lang/src/syntax/expression.rs index 432b4804..9157b921 100644 --- a/vhdl_lang/src/syntax/expression.rs +++ b/vhdl_lang/src/syntax/expression.rs @@ -7,11 +7,12 @@ 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::{Kind, Kind::*}; use crate::ast; use crate::ast::{Literal, *}; use crate::data::{Diagnostic, WithPos}; use crate::syntax::TokenAccess; +use vhdl_lang::syntax::parser::ParsingContext; fn name_to_expression(name: WithPos) -> WithPos { WithPos { @@ -143,14 +144,14 @@ fn kind_to_binary_op(kind: Kind) -> Option<(Operator, usize)> { } pub fn parse_aggregate_initial_choices( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, choices: Vec>, ) -> ParseResult>> { let mut choices = choices; let mut result = Vec::new(); loop { expect_token!( - stream, + ctx.stream, token, RightPar => { if choices.len() == 1 { @@ -166,7 +167,7 @@ pub fn parse_aggregate_initial_choices( if choices.len() == 1 { if let Some(WithPos{item: Choice::Expression(expr), pos}) = choices.pop() { result.push(ElementAssociation::Positional(WithPos::new(expr, pos))); - choices = parse_choices(stream)?; + choices = parse_choices(ctx)?; continue; } } @@ -174,17 +175,17 @@ pub fn parse_aggregate_initial_choices( return Err(token.kinds_error(&[RightArrow])); }, RightArrow => { - let rhs = parse_expression(stream)?; + let rhs = parse_expression(ctx)?; result.push(ElementAssociation::Named(choices, rhs)); expect_token!( - stream, + ctx.stream, token, RightPar => { return Ok(WithPos::from(result, token.pos.clone())) }, Comma => { - choices = parse_choices(stream)?; + choices = parse_choices(ctx)?; } ) } @@ -192,21 +193,23 @@ pub fn parse_aggregate_initial_choices( } } -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(), stream.get_pos(token).clone())); +pub fn parse_aggregate( + ctx: &mut ParsingContext<'_>, +) -> ParseResult>> { + ctx.stream.expect_kind(LeftPar)?; + if let Some(token) = ctx.stream.pop_if_kind(RightPar) { + return Ok(WithPos::from(Vec::new(), ctx.stream.get_pos(token).clone())); }; - let choices = parse_choices(stream)?; - parse_aggregate_initial_choices(stream, choices) + let choices = parse_choices(ctx)?; + parse_aggregate_initial_choices(ctx, choices) } fn parse_half_range( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, left_expr: WithPos, direction: Direction, ) -> ParseResult> { - let right_expr = parse_expression(stream)?; + let right_expr = parse_expression(ctx)?; let pos = left_expr.pos.combine(&right_expr.pos); let range = DiscreteRange::Range(ast::Range::Range(RangeConstraint { @@ -218,29 +221,32 @@ fn parse_half_range( Ok(WithPos::new(range, pos)) } -fn parse_choice(stream: &TokenStream) -> ParseResult> { - if let Some(token) = stream.pop_if_kind(Others) { - return Ok(WithPos::new(Choice::Others, stream.get_pos(token).clone())); +fn parse_choice(ctx: &mut ParsingContext<'_>) -> ParseResult> { + if let Some(token) = ctx.stream.pop_if_kind(Others) { + return Ok(WithPos::new( + Choice::Others, + ctx.stream.get_pos(token).clone(), + )); } - let left_expr = parse_expression(stream)?; + let left_expr = parse_expression(ctx)?; - if stream.skip_if_kind(To) { - let range = parse_half_range(stream, left_expr, Direction::Ascending)?; + if ctx.stream.skip_if_kind(To) { + let range = parse_half_range(ctx, left_expr, Direction::Ascending)?; Ok(range.map_into(Choice::DiscreteRange)) - } else if stream.skip_if_kind(Downto) { - let range = parse_half_range(stream, left_expr, Direction::Descending)?; + } else if ctx.stream.skip_if_kind(Downto) { + let range = parse_half_range(ctx, left_expr, Direction::Descending)?; Ok(range.map_into(Choice::DiscreteRange)) } else { Ok(left_expr.map_into(Choice::Expression)) } } -pub fn parse_choices(stream: &TokenStream) -> ParseResult>> { +pub fn parse_choices(ctx: &mut ParsingContext<'_>) -> ParseResult>> { let mut choices = Vec::new(); loop { - choices.push(parse_choice(stream)?); + choices.push(parse_choice(ctx)?); - if !stream.skip_if_kind(Bar) { + if !ctx.stream.skip_if_kind(Bar) { break; } } @@ -248,12 +254,12 @@ pub fn parse_choices(stream: &TokenStream) -> ParseResult>> } /// LRM 9.3.7 Allocators -fn parse_allocator(stream: &TokenStream) -> ParseResult> { - stream.expect_kind(New)?; - let type_mark = parse_type_mark(stream)?; +fn parse_allocator(ctx: &mut ParsingContext<'_>) -> ParseResult> { + ctx.stream.expect_kind(New)?; + let type_mark = parse_type_mark(ctx)?; - if stream.skip_if_kind(Tick) { - let expr = parse_expression(stream)?; + if ctx.stream.skip_if_kind(Tick) { + let expr = parse_expression(ctx)?; let pos = type_mark.pos.clone().combine_into(&expr); Ok(WithPos { item: Allocator::Qualified(QualifiedExpression { type_mark, expr }), @@ -263,7 +269,7 @@ fn parse_allocator(stream: &TokenStream) -> ParseResult> { let mut pos = type_mark.pos.clone(); let constraint = { - if let Some(constraint) = parse_subtype_constraint(stream)? { + if let Some(constraint) = parse_subtype_constraint(ctx)? { pos = pos.combine(&constraint.pos); Some(constraint) } else { @@ -319,8 +325,8 @@ fn name_to_selected_name(name: Name) -> Option { } } -fn parse_expression_or_aggregate(stream: &TokenStream) -> ParseResult> { - let mut choices = parse_choices(stream)?; +fn parse_expression_or_aggregate(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let mut choices = parse_choices(ctx)?; if choices.len() == 1 && matches!( @@ -340,19 +346,19 @@ fn parse_expression_or_aggregate(stream: &TokenStream) -> ParseResult { Ok(parse_aggregate_initial_choices( - stream, + ctx, vec![WithPos::new(Choice::Expression(expr), pos)], )?.map_into(Expression::Aggregate)) }, // Was expression with parenthesis RightPar => { - stream.skip(); + ctx.stream.skip(); // Lexical position between parenthesis let expr = WithPos { item: expr, @@ -363,7 +369,7 @@ fn parse_expression_or_aggregate(stream: &TokenStream) -> ParseResult ParseResult ParseResult> { - let token = stream.peek_expect()?; +fn parse_primary(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let token = ctx.stream.peek_expect()?; match token.kind { Identifier | LtLt => { - let name = parse_name(stream)?; - if stream.skip_if_kind(Tick) { - let lpar = stream.expect_kind(LeftPar)?; + let name = parse_name(ctx)?; + if ctx.stream.skip_if_kind(Tick) { + let lpar = ctx.stream.expect_kind(LeftPar)?; let expr = - parse_expression_or_aggregate(stream)?.combine_pos_with(stream.get_pos(lpar)); + parse_expression_or_aggregate(ctx)?.combine_pos_with(ctx.stream.get_pos(lpar)); let pos = name.pos.combine(&expr); Ok(WithPos { item: Expression::Qualified(Box::new(QualifiedExpression { @@ -393,38 +399,37 @@ fn parse_primary(stream: &TokenStream) -> ParseResult> { } } BitString => { - stream.skip(); + ctx.stream.skip(); Ok(token .to_bit_string()? .map_into(|bs| Expression::Literal(Literal::BitString(bs)))) } Character => { - stream.skip(); + ctx.stream.skip(); Ok(token .to_character_value()? .map_into(|chr| Expression::Literal(Literal::Character(chr)))) } StringLiteral => { - if stream.next_kinds_are(&[StringLiteral, LeftPar]) { + if ctx.stream.next_kinds_are(&[StringLiteral, LeftPar]) { // Probably an function call via operator symbol "foo"() - parse_name(stream) - .map(|name| name.map_into(|name| Expression::Name(Box::new(name)))) + parse_name(ctx).map(|name| name.map_into(|name| Expression::Name(Box::new(name)))) } else { - stream.skip(); + ctx.stream.skip(); Ok(token .to_string_value()? .map_into(|string| Expression::Literal(Literal::String(string)))) } } Null => { - stream.skip(); + ctx.stream.skip(); Ok(WithPos { item: Expression::Literal(Literal::Null), pos: token.pos.clone(), }) } New => { - let alloc = parse_allocator(stream)?; + let alloc = parse_allocator(ctx)?; let new_pos = token.pos.combine(&alloc); Ok(WithPos { @@ -433,11 +438,11 @@ fn parse_primary(stream: &TokenStream) -> ParseResult> { }) } AbstractLiteral => { - stream.skip(); + ctx.stream.skip(); let value = token.to_abstract_literal()?; // Physical unit - if let Some(unit_token) = stream.pop_if_kind(Identifier) { - let unit = stream.get_token(unit_token).to_identifier_value()?; + if let Some(unit_token) = ctx.stream.pop_if_kind(Identifier) { + let unit = ctx.stream.get_token(unit_token).to_identifier_value()?; let pos = value.pos.combine_into(&unit); let physical = PhysicalLiteral { value: value.item, @@ -453,16 +458,16 @@ fn parse_primary(stream: &TokenStream) -> ParseResult> { } LeftPar => { - stream.skip(); - parse_expression_or_aggregate(stream).map(|expr| expr.combine_pos_with(&token)) + ctx.stream.skip(); + parse_expression_or_aggregate(ctx).map(|expr| expr.combine_pos_with(&token)) } kind => { // Prefix unary operation if let Some((unary_op, op_precedence)) = kind_to_prefix_unary_op(kind) { - stream.skip(); + ctx.stream.skip(); - let expr = parse_expr(stream, op_precedence)?; + let expr = parse_expr(ctx, op_precedence)?; let pos = token.pos.combine(&expr); Ok(WithPos { @@ -474,7 +479,7 @@ fn parse_primary(stream: &TokenStream) -> ParseResult> { }) } else { Err(Diagnostic::syntax_error( - stream.pos_before(token), + ctx.stream.pos_before(token), "Expected {expression}", )) } @@ -482,9 +487,12 @@ fn parse_primary(stream: &TokenStream) -> ParseResult> { } } -fn parse_expr(stream: &TokenStream, min_precedence: usize) -> ParseResult> { - let mut lhs = parse_primary(stream)?; - while let Some(token) = stream.peek() { +fn parse_expr( + ctx: &mut ParsingContext<'_>, + min_precedence: usize, +) -> ParseResult> { + let mut lhs = parse_primary(ctx)?; + while let Some(token) = ctx.stream.peek() { if token.kind == RightPar { return Ok(lhs); }; @@ -492,8 +500,8 @@ fn parse_expr(stream: &TokenStream, min_precedence: usize) -> ParseResult min_precedence { - stream.skip(); - let rhs = parse_expr(stream, op_precedence)?; + ctx.stream.skip(); + let rhs = parse_expr(ctx, op_precedence)?; let pos = lhs.pos.combine(&rhs); lhs = WithPos { item: Expression::Binary( @@ -527,10 +535,10 @@ fn parse_expr(stream: &TokenStream, min_precedence: usize) -> ParseResult ParseResult> { - let state = stream.state(); - parse_expr(stream, 0).map_err(|err| { - stream.set_state(state); +pub fn parse_expression(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let state = ctx.stream.state(); + parse_expr(ctx, 0).map_err(|err| { + ctx.stream.set_state(state); err }) } diff --git a/vhdl_lang/src/syntax/interface_declaration.rs b/vhdl_lang/src/syntax/interface_declaration.rs index 069af6f1..7d0da628 100644 --- a/vhdl_lang/src/syntax/interface_declaration.rs +++ b/vhdl_lang/src/syntax/interface_declaration.rs @@ -14,9 +14,10 @@ use super::tokens::{Kind::*, *}; use crate::ast::*; use crate::data::*; use vhdl_lang::data::error_codes::ErrorCode; +use vhdl_lang::syntax::parser::ParsingContext; -fn parse_optional_mode(stream: &TokenStream) -> ParseResult>> { - let token = stream.peek_expect()?; +fn parse_optional_mode(ctx: &mut ParsingContext<'_>) -> ParseResult>> { + let token = ctx.stream.peek_expect()?; let mode = match token.kind { In => Mode::In, Out => Mode::Out, @@ -25,7 +26,7 @@ fn parse_optional_mode(stream: &TokenStream) -> ParseResult Linkage => Mode::Linkage, _ => return Ok(None), }; - stream.skip(); + ctx.stream.skip(); Ok(Some(WithPos::new(mode, token.pos.clone()))) } @@ -38,10 +39,10 @@ fn unexpected_object_class_kind(list_type: InterfaceType, token: &Token) -> Diag } fn parse_optional_object_class( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, list_type: InterfaceType, ) -> ParseResult>> { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; let class = match token.kind { Constant => ObjectClass::Constant, @@ -50,19 +51,19 @@ fn parse_optional_object_class( Identifier => return Ok(None), _ => return Err(unexpected_object_class_kind(list_type, token)), }; - stream.skip(); + ctx.stream.skip(); Ok(Some(WithPos::new(class, token.pos.clone()))) } fn parse_interface_file_declaration( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { - stream.expect_kind(File)?; - let idents = parse_identifier_list(stream)?; - stream.expect_kind(Colon)?; - let subtype = parse_subtype_indication(stream)?; + ctx.stream.expect_kind(File)?; + let idents = parse_identifier_list(ctx)?; + ctx.stream.expect_kind(Colon)?; + let subtype = parse_subtype_indication(ctx)?; - if stream.next_kind_is(Open) { + if ctx.stream.next_kind_is(Open) { if let Some(ident) = idents.first() { return Err(Diagnostic::syntax_error( ident, @@ -70,7 +71,7 @@ fn parse_interface_file_declaration( )); } } - if stream.next_kind_is(Is) { + if ctx.stream.next_kind_is(Is) { if let Some(ident) = idents.first() { return Err(Diagnostic::syntax_error( ident, @@ -91,17 +92,17 @@ fn parse_interface_file_declaration( } fn parse_interface_object_declaration( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, list_type: InterfaceType, ) -> ParseResult> { - let explicit_object_class = parse_optional_object_class(stream, list_type)?; + let explicit_object_class = parse_optional_object_class(ctx, list_type)?; let object_class_pos = explicit_object_class.as_ref().map(|class| &class.pos); - let idents = parse_identifier_list(stream)?; + let idents = parse_identifier_list(ctx)?; - stream.expect_kind(Colon)?; + ctx.stream.expect_kind(Colon)?; - let mode_with_pos = parse_optional_mode(stream)?; + let mode_with_pos = parse_optional_mode(ctx)?; let mode = mode_with_pos .as_ref() .map(|mode| mode.item) @@ -120,8 +121,8 @@ fn parse_interface_object_declaration( (InterfaceType::Parameter, None, _) => ObjectClass::Variable, }; - let subtype = parse_subtype_indication(stream)?; - let expr = parse_optional_assignment(stream)?; + let subtype = parse_subtype_indication(ctx)?; + let expr = parse_optional_assignment(ctx)?; // @TODO maybe move this to a semantic check? for ident in idents.iter() { @@ -165,14 +166,16 @@ fn parse_interface_object_declaration( .collect()) } -fn parse_subprogram_default(stream: &TokenStream) -> ParseResult> { - if stream.skip_if_kind(Is) { +fn parse_subprogram_default( + ctx: &mut ParsingContext<'_>, +) -> ParseResult> { + if ctx.stream.skip_if_kind(Is) { let default = { peek_token!( - stream, token, - Identifier => SubprogramDefault::Name(parse_selected_name(stream)?), + ctx.stream, token, + Identifier => SubprogramDefault::Name(parse_selected_name(ctx)?), BOX => { - stream.skip(); + ctx.stream.skip(); SubprogramDefault::Box } ) @@ -185,33 +188,32 @@ fn parse_subprogram_default(stream: &TokenStream) -> ParseResult, ) -> ParseResult { - stream.expect_kind(Package)?; - let ident = stream.expect_ident()?; - stream.expect_kind(Is)?; - stream.expect_kind(New)?; - let package_name = parse_selected_name(stream)?; - stream.expect_kind(Generic)?; - stream.expect_kind(Map)?; + ctx.stream.expect_kind(Package)?; + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(Is)?; + ctx.stream.expect_kind(New)?; + let package_name = parse_selected_name(ctx)?; + ctx.stream.expect_kind(Generic)?; + ctx.stream.expect_kind(Map)?; let generic_map = { - let left_par = stream.expect_kind(LeftPar)?; - let map_token = stream.peek_expect()?; + let left_par = ctx.stream.expect_kind(LeftPar)?; + let map_token = ctx.stream.peek_expect()?; match map_token.kind { BOX => { - stream.skip(); - stream.expect_kind(RightPar)?; + ctx.stream.skip(); + ctx.stream.expect_kind(RightPar)?; InterfacePackageGenericMapAspect::Box } Default => { - stream.skip(); - stream.expect_kind(RightPar)?; + ctx.stream.skip(); + ctx.stream.expect_kind(RightPar)?; InterfacePackageGenericMapAspect::Default } _ => { - let (list, _) = parse_association_list_no_leftpar(stream, left_par, diagnsotics)?; + let (list, _) = parse_association_list_no_leftpar(ctx, left_par)?; InterfacePackageGenericMapAspect::Map(list) } } @@ -225,41 +227,40 @@ fn parse_interface_package( } fn parse_interface_declaration( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext, list_type: InterfaceType, ) -> ParseResult> { peek_token!( - stream, token, + ctx.stream, token, Signal | Constant | Variable | Identifier => { - parse_interface_object_declaration(stream, list_type) + parse_interface_object_declaration(ctx, list_type) }, - File => parse_interface_file_declaration(stream), + File => parse_interface_file_declaration(ctx), Type => { - stream.skip(); - let ident = stream.expect_ident()?; + ctx.stream.skip(); + let ident = ctx.stream.expect_ident()?; Ok(vec![InterfaceDeclaration::Type(WithDecl::new(ident))]) }, Function | Procedure | Impure | Pure => { - let spec = parse_subprogram_specification(stream, diagnostics)?; - let default = parse_subprogram_default(stream)?; + let spec = parse_subprogram_specification(ctx)?; + let default = parse_subprogram_default(ctx)?; Ok(vec![InterfaceDeclaration::Subprogram(spec, default)]) }, Package => { - Ok(vec![InterfaceDeclaration::Package (parse_interface_package(stream, diagnostics)?)]) + Ok(vec![InterfaceDeclaration::Package (parse_interface_package(ctx)?)]) } ) } /// 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(ctx: &mut ParsingContext<'_>) -> ParseResult<()> { peek_token!( - stream, token, + ctx.stream, token, SemiColon => { - stream.skip(); - if stream.next_kind_is(RightPar) { + ctx.stream.skip(); + if ctx.stream.next_kind_is(RightPar) { return Err(Diagnostic::syntax_error(&token.pos, format!("Last interface element may not end with {}", kinds_str(&[SemiColon])))); @@ -282,70 +283,69 @@ fn is_sync_kind(list_type: InterfaceType, kind: Kind) -> bool { } fn parse_interface_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, list_type: InterfaceType, ) -> ParseResult> { let mut interface_list = Vec::new(); - let left_par = stream.expect_kind(LeftPar)?; + let left_par = ctx.stream.expect_kind(LeftPar)?; 'outer: loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { RightPar => { if interface_list.is_empty() { - diagnostics.add( - stream.get_pos(left_par).combine(token), + ctx.diagnostics.add( + ctx.stream.get_pos(left_par).combine(token), "Interface list must not be empty", ErrorCode::SyntaxError, ); } - stream.skip(); + ctx.stream.skip(); break; } _ => { - let state = stream.state(); + let state = ctx.stream.state(); - match parse_interface_declaration(stream, diagnostics, list_type) { + match parse_interface_declaration(ctx, list_type) { Ok(ref mut decl_list) => { interface_list.append(decl_list); } Err(err) => { - diagnostics.push(err); - stream.set_state(state); - if let Some(token) = stream.peek() { + ctx.diagnostics.push(err); + ctx.stream.set_state(state); + if let Some(token) = ctx.stream.peek() { if is_sync_kind(list_type, token.kind) { - stream.skip(); + ctx.stream.skip(); } } // Recover - while let Some(token) = stream.peek() { + while let Some(token) = ctx.stream.peek() { match token.kind { SemiColon => { - stream.skip(); + ctx.stream.skip(); continue 'outer; } kind if is_sync_kind(list_type, kind) => { continue 'outer; } RightPar => { - stream.skip(); + ctx.stream.skip(); break 'outer; } _ => { - stream.skip(); + ctx.stream.skip(); } } } } } - if let Err(err) = parse_semicolon_separator(stream) { - diagnostics.push(err); + if let Err(err) = parse_semicolon_separator(ctx) { + ctx.diagnostics.push(err); // Ignore comma when recovering from errors - stream.pop_if_kind(Comma); + ctx.stream.pop_if_kind(Comma); } } } @@ -355,61 +355,52 @@ fn parse_interface_list( } pub fn parse_generic_interface_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { - parse_interface_list(stream, diagnostics, InterfaceType::Generic) + parse_interface_list(ctx, InterfaceType::Generic) } pub fn parse_port_interface_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { - parse_interface_list(stream, diagnostics, InterfaceType::Port) + parse_interface_list(ctx, InterfaceType::Port) } pub fn parse_parameter_interface_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { - parse_interface_list(stream, diagnostics, InterfaceType::Parameter) + parse_interface_list(ctx, InterfaceType::Parameter) } #[cfg(test)] fn parse_one_interface_declaration( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, list_type: InterfaceType, ) -> ParseResult { - let mut diagnostics = Vec::new(); - let result = parse_interface_declaration(stream, &mut diagnostics, list_type).map(|decls| { + parse_interface_declaration(ctx, list_type).map(|decls| { assert_eq!(decls.len(), 1); decls[0].clone() - }); - assert_eq!(diagnostics, vec![]); - result + }) } #[cfg(test)] -pub fn parse_parameter(stream: &TokenStream) -> ParseResult { - parse_one_interface_declaration(stream, InterfaceType::Parameter) +pub fn parse_parameter(ctx: &mut ParsingContext) -> ParseResult { + parse_one_interface_declaration(ctx, InterfaceType::Parameter) } #[cfg(test)] -pub fn parse_port(stream: &TokenStream) -> ParseResult { - parse_one_interface_declaration(stream, InterfaceType::Port) +pub fn parse_port(ctx: &mut ParsingContext) -> ParseResult { + parse_one_interface_declaration(ctx, InterfaceType::Port) } #[cfg(test)] -pub fn parse_generic(stream: &TokenStream) -> ParseResult { - parse_one_interface_declaration(stream, InterfaceType::Generic) +pub fn parse_generic(ctx: &mut ParsingContext) -> ParseResult { + parse_one_interface_declaration(ctx, InterfaceType::Generic) } #[cfg(test)] -pub fn parse_parameter_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult> { - parse_interface_list(stream, diagnostics, InterfaceType::Parameter) +pub fn parse_parameter_list(ctx: &mut ParsingContext) -> ParseResult> { + parse_interface_list(ctx, InterfaceType::Parameter) } #[cfg(test)] diff --git a/vhdl_lang/src/syntax/names.rs b/vhdl_lang/src/syntax/names.rs index 6cc2bac9..d2f4385f 100644 --- a/vhdl_lang/src/syntax/names.rs +++ b/vhdl_lang/src/syntax/names.rs @@ -9,17 +9,18 @@ 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::*, TokenAccess, TokenStream}; +use super::tokens::{Kind::*, TokenAccess}; use crate::ast; use crate::ast::{Literal, *}; use crate::data::error_codes::ErrorCode; -use crate::data::{Diagnostic, DiagnosticHandler, WithPos}; +use crate::data::{Diagnostic, WithPos}; use crate::syntax::separated_list::parse_list_with_separator_or_recover; use crate::syntax::TokenId; +use vhdl_lang::syntax::parser::ParsingContext; -pub fn parse_designator(stream: &TokenStream) -> ParseResult> { +pub fn parse_designator(ctx: &mut ParsingContext<'_>) -> ParseResult> { Ok(expect_token!( - stream, + ctx.stream, token, Identifier => token.to_identifier_value()?.map_into(Designator::Identifier), StringLiteral => token.to_operator_symbol()?.map_into(Designator::OperatorSymbol), @@ -27,19 +28,17 @@ pub fn parse_designator(stream: &TokenStream) -> ParseResult )) } -pub fn parse_selected_name(stream: &TokenStream) -> ParseResult> { - let mut name = parse_designator(stream)? - .into_ref() - .map_into(Name::Designator); +pub fn parse_selected_name(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let mut name = parse_designator(ctx)?.into_ref().map_into(Name::Designator); loop { - if !stream.skip_if_kind(Dot) { + if !ctx.stream.skip_if_kind(Dot) { break; } - if let Some(tok) = stream.pop_if_kind(All) { - let pos = stream.get_pos(tok).combine(&name.pos); + if let Some(tok) = ctx.stream.pop_if_kind(All) { + let pos = ctx.stream.get_pos(tok).combine(&name.pos); name = WithPos::from(Name::SelectedAll(Box::new(name)), pos); } else { - let suffix = parse_designator(stream)?.into_ref(); + let suffix = parse_designator(ctx)?.into_ref(); let pos = suffix.pos.combine(&name.pos); name = WithPos::from(Name::Selected(Box::new(name), suffix), pos); } @@ -47,21 +46,21 @@ pub fn parse_selected_name(stream: &TokenStream) -> ParseResult> { Ok(name) } -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(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let name = parse_selected_name(ctx)?; + parse_type_mark_starting_with_name(ctx, name) } pub fn parse_type_mark_starting_with_name( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, name: WithPos, ) -> ParseResult> { - let state = stream.state(); + let state = ctx.stream.state(); // Check if it is a type mark with a subtype or element attribute: // Example: signal sig0 : sig1'subtype; - if stream.pop_if_kind(Tick).is_some() { - if let Ok(attr) = stream.expect_attribute_designator() { + if ctx.stream.pop_if_kind(Tick).is_some() { + if let Ok(attr) = ctx.stream.expect_attribute_designator() { if let AttributeDesignator::Type(typattr) = attr.item { return Ok(WithPos { pos: attr.pos.combine_into(&name.pos), @@ -73,7 +72,7 @@ pub fn parse_type_mark_starting_with_name( } } - stream.set_state(state); + ctx.stream.set_state(state); }; Ok(WithPos { @@ -106,11 +105,11 @@ 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(ctx: &mut ParsingContext<'_>) -> ParseResult> { let mut idents = Vec::new(); loop { - idents.push(stream.expect_ident()?); - if !stream.skip_if_kind(Comma) { + idents.push(ctx.stream.expect_ident()?); + if !ctx.stream.skip_if_kind(Comma) { break; } } @@ -165,23 +164,23 @@ fn assoc_to_expression(assoc: AssociationElement) -> ParseResult ParseResult> { - if let Some(token) = stream.pop_if_kind(Open) { +fn parse_actual_part(ctx: &mut ParsingContext<'_>) -> ParseResult> { + if let Some(token) = ctx.stream.pop_if_kind(Open) { Ok(WithPos::from( ActualPart::Open, - stream.get_pos(token).clone(), + ctx.stream.get_pos(token).clone(), )) } else { - Ok(parse_expression(stream)?.map_into(ActualPart::Expression)) + Ok(parse_expression(ctx)?.map_into(ActualPart::Expression)) } } -pub fn parse_association_element(stream: &TokenStream) -> ParseResult { - let actual = parse_actual_part(stream)?; - if stream.skip_if_kind(RightArrow) { +pub fn parse_association_element(ctx: &mut ParsingContext<'_>) -> ParseResult { + let actual = parse_actual_part(ctx)?; + if ctx.stream.skip_if_kind(RightArrow) { Ok(AssociationElement { formal: Some(actual_part_to_name(actual)?), - actual: parse_actual_part(stream)?, + actual: parse_actual_part(ctx)?, }) } else { Ok(AssociationElement { @@ -192,39 +191,36 @@ pub fn parse_association_element(stream: &TokenStream) -> ParseResult, ) -> ParseResult<(SeparatedList, TokenId)> { - let left_par = stream.expect_kind(LeftPar)?; - parse_association_list_no_leftpar(stream, left_par, diagnsotics) + let left_par = ctx.stream.expect_kind(LeftPar)?; + parse_association_list_no_leftpar(ctx, left_par) } pub fn parse_association_list_no_leftpar( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, left_par: TokenId, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult<(SeparatedList, TokenId)> { - if let Some(right_par) = stream.pop_if_kind(RightPar) { - diagnostics.add( - stream.get_span(left_par, right_par), + if let Some(right_par) = ctx.stream.pop_if_kind(RightPar) { + ctx.diagnostics.add( + ctx.stream.get_span(left_par, right_par), "Association list cannot be empty", ErrorCode::SyntaxError, ); return Ok((SeparatedList::default(), right_par)); } let list = parse_list_with_separator_or_recover( - stream, + ctx, Comma, - diagnostics, parse_association_element, Some(RightPar), )?; - let right_par = stream.expect_kind(RightPar)?; + let right_par = ctx.stream.expect_kind(RightPar)?; Ok((list, right_par)) } fn parse_function_call( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, prefix: WithPos, first: AssociationElement, ) -> ParseResult> { @@ -232,9 +228,9 @@ fn parse_function_call( association_elements.push(first); loop { - association_elements.push(parse_association_element(stream)?); + association_elements.push(parse_association_element(ctx)?); expect_token!( - stream, + ctx.stream, token, Comma => {}, RightPar => { @@ -251,17 +247,17 @@ fn parse_function_call( } fn parse_attribute_name( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, name: WithPos, signature: Option>, ) -> ParseResult> { - let attr = stream.expect_attribute_designator()?; + let attr = ctx.stream.expect_attribute_designator()?; let (expression, pos) = { - if stream.skip_if_kind(LeftPar) { - let ret = Some(parse_expression(stream)?); - let rpar_token = stream.expect_kind(RightPar)?; - (ret, stream.get_pos(rpar_token).combine(&name)) + if ctx.stream.skip_if_kind(LeftPar) { + let ret = Some(parse_expression(ctx)?); + let rpar_token = ctx.stream.expect_kind(RightPar)?; + (ret, ctx.stream.get_pos(rpar_token).combine(&name)) } else { (None, attr.pos.combine(&name)) } @@ -283,10 +279,10 @@ enum DesignatorOrAll { All, } -fn parse_suffix(stream: &TokenStream) -> ParseResult> { +fn parse_suffix(ctx: &mut ParsingContext<'_>) -> ParseResult> { let name = { expect_token!( - stream, + ctx.stream, token, Identifier => token.to_identifier_value()?.map_into(|ident| DesignatorOrAll::Designator(Designator::Identifier(ident))), Character => token.to_character_value()?.map_into(|byte| DesignatorOrAll::Designator(Designator::Character(byte))), @@ -300,50 +296,50 @@ fn parse_suffix(stream: &TokenStream) -> ParseResult> { /// LRM 8.7 External names /// Inside of << >> -fn parse_inner_external_name(stream: &TokenStream) -> ParseResult { - let token = stream.peek_expect()?; +fn parse_inner_external_name(ctx: &mut ParsingContext<'_>) -> ParseResult { + let token = ctx.stream.peek_expect()?; let class = try_init_token_kind!( token, Signal => ExternalObjectClass::Signal, Constant => ExternalObjectClass::Constant, Variable => ExternalObjectClass::Variable); - stream.skip(); + ctx.stream.skip(); let path = peek_token!( - stream, token, + ctx.stream, token, CommAt => { - stream.skip(); - let path_name = parse_name(stream)?; + ctx.stream.skip(); + let path_name = parse_name(ctx)?; let path_pos = path_name.pos.clone().combine_into(&token); WithPos::from(ExternalPath::Package(path_name), path_pos) }, Dot => { - stream.skip(); - let path_name = parse_name(stream)?; + ctx.stream.skip(); + let path_name = parse_name(ctx)?; let path_pos = path_name.pos.clone().combine_into(&token); WithPos::from(ExternalPath::Absolute(path_name), path_pos) }, Circ => { - stream.skip(); - stream.expect_kind(Dot)?; + ctx.stream.skip(); + ctx.stream.expect_kind(Dot)?; let mut up_levels = 1; - while stream.skip_if_kind(Circ) { - stream.expect_kind(Dot)?; + while ctx.stream.skip_if_kind(Circ) { + ctx.stream.expect_kind(Dot)?; up_levels += 1; } - let path_name = parse_name(stream)?; + let path_name = parse_name(ctx)?; let path_pos = path_name.pos.clone().combine_into(&token); WithPos::from(ExternalPath::Relative(path_name, up_levels), path_pos) }, Identifier => { - let path_name = parse_name(stream)?; + let path_name = parse_name(ctx)?; let path_pos = path_name.pos.clone(); WithPos::from(ExternalPath::Relative(path_name, 0), path_pos) } ); - stream.expect_kind(Colon)?; - let subtype = parse_subtype_indication(stream)?; + ctx.stream.expect_kind(Colon)?; + let subtype = parse_subtype_indication(ctx)?; Ok(ExternalName { class, @@ -353,14 +349,14 @@ fn parse_inner_external_name(stream: &TokenStream) -> ParseResult } /// LRM 8. Names -fn _parse_name(stream: &TokenStream) -> ParseResult> { +fn _parse_name(ctx: &mut ParsingContext<'_>) -> 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)?)); - let end_token = stream.expect_kind(GtGt)?; - WithPos::from(external_name, stream.get_span(token, end_token)) + if let Some(token) = ctx.stream.pop_if_kind(LtLt) { + let external_name = Name::External(Box::new(parse_inner_external_name(ctx)?)); + let end_token = ctx.stream.expect_kind(GtGt)?; + WithPos::from(external_name, ctx.stream.get_span(token, end_token)) } else { - let suffix = parse_suffix(stream)?; + let suffix = parse_suffix(ctx)?; match suffix.item { DesignatorOrAll::Designator(designator) => { WithPos::from(Name::Designator(designator.into_ref()), suffix.pos) @@ -375,11 +371,11 @@ fn _parse_name(stream: &TokenStream) -> ParseResult> { } }; - while let Some(token) = stream.peek() { + while let Some(token) = ctx.stream.peek() { match token.kind { Dot => { - stream.skip(); - let suffix = parse_suffix(stream)?; + ctx.stream.skip(); + let suffix = parse_suffix(ctx)?; let pos = name.pos.combine(&suffix.pos); match suffix.item { @@ -401,40 +397,40 @@ fn _parse_name(stream: &TokenStream) -> ParseResult> { } } LeftSquare => { - let state = stream.state(); - let signature = Some(parse_signature(stream)?); - if !stream.skip_if_kind(Tick) { + let state = ctx.stream.state(); + let signature = Some(parse_signature(ctx)?); + if !ctx.stream.skip_if_kind(Tick) { // Alias may have prefix[signature] without tick - stream.set_state(state); + ctx.stream.set_state(state); break; } - name = parse_attribute_name(stream, name, signature)?; + name = parse_attribute_name(ctx, name, signature)?; } Tick => { - if stream.nth_kind_is(1, LeftPar) { + if ctx.stream.nth_kind_is(1, LeftPar) { break; } - stream.skip(); + ctx.stream.skip(); let signature = None; - name = parse_attribute_name(stream, name, signature)?; + name = parse_attribute_name(ctx, name, signature)?; } LeftPar => { - stream.skip(); - if let Some(right_par) = stream.pop_if_kind(RightPar) { + ctx.stream.skip(); + if let Some(right_par) = ctx.stream.pop_if_kind(RightPar) { return Err(Diagnostic::syntax_error( - token.pos.combine(stream.get_pos(right_par)), + token.pos.combine(ctx.stream.get_pos(right_par)), "Association list cannot be empty", )); } - let assoc = parse_association_element(stream)?; + let assoc = parse_association_element(ctx)?; expect_token!( - stream, + ctx.stream, sep_token, Comma => { - name = parse_function_call(stream, name, assoc)?; + name = parse_function_call(ctx, name, assoc)?; }, To | Downto => { - let right_expr = parse_expression(stream)?; + let right_expr = parse_expression(ctx)?; let direction = { if sep_token.kind == To { Direction::Ascending @@ -442,8 +438,8 @@ fn _parse_name(stream: &TokenStream) -> ParseResult> { Direction::Descending } }; - let rpar_token = stream.expect_kind(RightPar)?; - let pos = stream.get_pos(rpar_token).combine(&name); + let rpar_token = ctx.stream.expect_kind(RightPar)?; + let pos = ctx.stream.get_pos(rpar_token).combine(&name); let discrete_range = DiscreteRange::Range(ast::Range::Range(RangeConstraint { left_expr: Box::new(assoc_to_expression(assoc)?), @@ -504,10 +500,10 @@ pub fn into_range(assoc: AssociationElement) -> Result ParseResult> { - let state = stream.state(); - _parse_name(stream).map_err(|err| { - stream.set_state(state); +pub fn parse_name(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let state = ctx.stream.state(); + _parse_name(ctx).map_err(|err| { + ctx.stream.set_state(state); err }) } @@ -912,9 +908,9 @@ mod tests { fn test_name_signature_no_attribute_name() { // Alias declarations may use name[signature] let code = Code::new("prefix[return natural]"); - let name = code.with_partial_stream(|stream| { - let result = parse_name(stream); - stream.expect_kind(LeftSquare)?; + let name = code.with_partial_stream(|ctx| { + let result = parse_name(ctx); + ctx.stream.expect_kind(LeftSquare)?; result }); let prefix = WithPos { @@ -927,10 +923,10 @@ mod tests { #[test] fn test_qualified_expression_is_not_name() { let code = Code::new("prefix'("); - let name = code.with_stream(|stream| { - let result = parse_name(stream); - stream.expect_kind(Tick)?; - stream.expect_kind(LeftPar)?; + let name = code.with_stream(|ctx| { + let result = parse_name(ctx); + ctx.stream.expect_kind(Tick)?; + ctx.stream.expect_kind(LeftPar)?; result }); let prefix = WithPos { @@ -1219,7 +1215,7 @@ mod tests { let code = Code::new("foo()"); let res = code.parse(parse_name); assert_eq!( - res, + res.0, Err(Diagnostic::syntax_error( code.s1("()"), "Association list cannot be empty" diff --git a/vhdl_lang/src/syntax/object_declaration.rs b/vhdl_lang/src/syntax/object_declaration.rs index 3ecdab96..41d50d72 100644 --- a/vhdl_lang/src/syntax/object_declaration.rs +++ b/vhdl_lang/src/syntax/object_declaration.rs @@ -8,15 +8,18 @@ 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::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; /// LRM 6.4.2 Object Declarations use crate::ast::*; use crate::data::WithPos; use crate::Diagnostic; +use vhdl_lang::syntax::parser::ParsingContext; -pub fn parse_optional_assignment(stream: &TokenStream) -> ParseResult>> { - if stream.pop_if_kind(ColonEq).is_some() { - let expr = parse_expression(stream)?; +pub fn parse_optional_assignment( + ctx: &mut ParsingContext<'_>, +) -> ParseResult>> { + if ctx.stream.pop_if_kind(ColonEq).is_some() { + let expr = parse_expression(ctx)?; Ok(Some(expr)) } else { Ok(None) @@ -24,31 +27,31 @@ pub fn parse_optional_assignment(stream: &TokenStream) -> ParseResult, class: ObjectClass, ) -> ParseResult> { - let start_token = stream.get_current_token_id(); + let start_token = ctx.stream.get_current_token_id(); match class { ObjectClass::Signal => { - stream.expect_kind(Signal)?; + ctx.stream.expect_kind(Signal)?; } ObjectClass::Constant => { - stream.expect_kind(Constant)?; + ctx.stream.expect_kind(Constant)?; } ObjectClass::Variable => { - stream.expect_kind(Variable)?; + ctx.stream.expect_kind(Variable)?; } ObjectClass::SharedVariable => { - stream.expect_kind(Shared)?; - stream.expect_kind(Variable)?; + ctx.stream.expect_kind(Shared)?; + ctx.stream.expect_kind(Variable)?; } } - let idents = parse_identifier_list(stream)?; - stream.expect_kind(Colon)?; - let subtype = parse_subtype_indication(stream)?; - let opt_expression = parse_optional_assignment(stream)?; - let end_token = stream.expect_kind(SemiColon)?; + let idents = parse_identifier_list(ctx)?; + ctx.stream.expect_kind(Colon)?; + let subtype = parse_subtype_indication(ctx)?; + let opt_expression = parse_optional_assignment(ctx)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(idents .into_iter() @@ -62,42 +65,44 @@ fn parse_object_declaration_kind( .collect()) } -pub fn parse_object_declaration(stream: &TokenStream) -> ParseResult> { - let token = stream.peek_expect()?; +pub fn parse_object_declaration( + ctx: &mut ParsingContext<'_>, +) -> ParseResult> { + let token = ctx.stream.peek_expect()?; let result = try_init_token_kind!( token, - Constant => parse_object_declaration_kind(stream, ObjectClass::Constant)?, - Signal => parse_object_declaration_kind(stream, ObjectClass::Signal)?, - Variable => parse_object_declaration_kind(stream, ObjectClass::Variable)?, + Constant => parse_object_declaration_kind(ctx, ObjectClass::Constant)?, + Signal => parse_object_declaration_kind(ctx, ObjectClass::Signal)?, + Variable => parse_object_declaration_kind(ctx, ObjectClass::Variable)?, Shared => { - parse_object_declaration_kind(stream, ObjectClass::SharedVariable)? + parse_object_declaration_kind(ctx, ObjectClass::SharedVariable)? } ); Ok(result) } -pub fn parse_file_declaration(stream: &TokenStream) -> ParseResult> { - let start_token = stream.expect_kind(File)?; - let idents = parse_identifier_list(stream)?; - stream.expect_kind(Colon)?; - let subtype = parse_subtype_indication(stream)?; +pub fn parse_file_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let start_token = ctx.stream.expect_kind(File)?; + let idents = parse_identifier_list(ctx)?; + ctx.stream.expect_kind(Colon)?; + let subtype = parse_subtype_indication(ctx)?; let open_info = { - if stream.skip_if_kind(Open) { - Some(parse_expression(stream)?) + if ctx.stream.skip_if_kind(Open) { + Some(parse_expression(ctx)?) } else { None } }; let file_name = { - if stream.skip_if_kind(Is) { - Some(parse_expression(stream)?) + if ctx.stream.skip_if_kind(Is) { + Some(parse_expression(ctx)?) } else { None } }; - let end_token = stream.expect_kind(SemiColon)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; // If the `file_open_information` is present, `file_name` is mandatory // LRM 6.4.2.5 diff --git a/vhdl_lang/src/syntax/parser.rs b/vhdl_lang/src/syntax/parser.rs index e683846f..7a234d9f 100644 --- a/vhdl_lang/src/syntax/parser.rs +++ b/vhdl_lang/src/syntax/parser.rs @@ -4,11 +4,11 @@ // // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com -use super::design_unit::parse_design_file; use super::tokens::{Symbols, TokenStream, Tokenizer}; use crate::ast::DesignFile; use crate::data::*; use crate::standard::VHDLStandard; +use crate::syntax::design_unit::parse_design_file; use std::io; use std::sync::Arc; @@ -16,6 +16,11 @@ pub struct VHDLParser { pub symbols: Arc, } +pub(crate) struct ParsingContext<'a> { + pub stream: &'a TokenStream<'a>, + pub diagnostics: &'a mut dyn DiagnosticHandler, +} + pub type ParserResult = Result<(Source, DesignFile), io::Error>; impl VHDLParser { @@ -38,7 +43,12 @@ impl VHDLParser { let tokenizer = Tokenizer::new(&self.symbols, source, ContentReader::new(&contents)); let stream = TokenStream::new(tokenizer, diagnostics); - match parse_design_file(&stream, diagnostics) { + let mut ctx = ParsingContext { + stream: &stream, + diagnostics, + }; + + match parse_design_file(&mut ctx) { Ok(design_file) => design_file, Err(diagnostic) => { diagnostics.push(diagnostic); diff --git a/vhdl_lang/src/syntax/range.rs b/vhdl_lang/src/syntax/range.rs index e07967da..cfcf0b1a 100644 --- a/vhdl_lang/src/syntax/range.rs +++ b/vhdl_lang/src/syntax/range.rs @@ -8,14 +8,15 @@ 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::Kind::*; use crate::ast; use crate::ast::*; use crate::data::{Diagnostic, WithPos}; +use vhdl_lang::syntax::parser::ParsingContext; -pub fn parse_direction(stream: &TokenStream) -> ParseResult { +pub fn parse_direction(ctx: &mut ParsingContext) -> ParseResult { Ok(expect_token!( - stream, token, + ctx.stream, token, To => Direction::Ascending, Downto => Direction::Descending )) @@ -26,13 +27,13 @@ enum NameOrRange { Range(WithPos), } -fn parse_name_or_range(stream: &TokenStream) -> ParseResult { - let expr = parse_expression(stream)?; +fn parse_name_or_range(ctx: &mut ParsingContext<'_>) -> ParseResult { + let expr = parse_expression(ctx)?; - match stream.peek_kind() { + match ctx.stream.peek_kind() { Some(To) | Some(Downto) => { - let direction = parse_direction(stream)?; - let right_expr = parse_expression(stream)?; + let direction = parse_direction(ctx)?; + let right_expr = parse_expression(ctx)?; let pos = expr.pos.combine(&right_expr.pos); let range = ast::Range::Range(RangeConstraint { @@ -72,38 +73,38 @@ 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> { - match parse_name_or_range(stream)? { +pub fn parse_range(ctx: &mut ParsingContext<'_>) -> ParseResult> { + match parse_name_or_range(ctx)? { NameOrRange::Range(range) => Ok(range), NameOrRange::Name(name) => Err(Diagnostic::syntax_error(&name, "Expected range")), } } -pub fn parse_discrete_range(stream: &TokenStream) -> ParseResult { - match parse_name_or_range(stream) { +pub fn parse_discrete_range(ctx: &mut ParsingContext<'_>) -> ParseResult { + match parse_name_or_range(ctx) { Ok(NameOrRange::Range(range)) => Ok(DiscreteRange::Range(range.item)), Ok(NameOrRange::Name(name)) => { let type_mark = name_to_type_mark(name)?; - let range = parse_optional(stream, Range, parse_range)?.map(|range| range.item); + let range = parse_optional(ctx, Range, parse_range)?.map(|range| range.item); Ok(DiscreteRange::Discrete(type_mark, range)) } Err(diagnostic) => Err(diagnostic.when("parsing discrete_range")), } } -pub fn parse_array_index_constraint(stream: &TokenStream) -> ParseResult { - match parse_name_or_range(stream) { +pub fn parse_array_index_constraint(ctx: &mut ParsingContext<'_>) -> ParseResult { + match parse_name_or_range(ctx) { Ok(NameOrRange::Range(range)) => Ok(ArrayIndex::Discrete(DiscreteRange::Range(range.item))), Ok(NameOrRange::Name(name)) => { let type_mark = name_to_type_mark(name)?; - if stream.skip_if_kind(Range) { - if stream.skip_if_kind(BOX) { + if ctx.stream.skip_if_kind(Range) { + if ctx.stream.skip_if_kind(BOX) { Ok(ArrayIndex::IndexSubtypeDefintion(type_mark)) } else { Ok(ArrayIndex::Discrete(DiscreteRange::Discrete( type_mark, - Some(parse_range(stream)?.item), + Some(parse_range(ctx)?.item), ))) } } else { diff --git a/vhdl_lang/src/syntax/separated_list.rs b/vhdl_lang/src/syntax/separated_list.rs index a53ac659..5671100b 100644 --- a/vhdl_lang/src/syntax/separated_list.rs +++ b/vhdl_lang/src/syntax/separated_list.rs @@ -5,27 +5,24 @@ // Copyright (c) 2023, Olof Kraigher olof.kraigher@gmail.com use crate::ast::{IdentList, NameList, SeparatedList, WithRef}; -use crate::data::{DiagnosticHandler, DiagnosticResult}; +use crate::data::DiagnosticResult; use crate::syntax::common::ParseResult; use crate::syntax::names::parse_name; use crate::syntax::Kind::Comma; -use crate::syntax::{kind_str, Kind, TokenAccess, TokenStream}; +use crate::syntax::{kind_str, Kind, TokenAccess}; use crate::Diagnostic; +use vhdl_lang::syntax::parser::ParsingContext; /// Skip extraneous tokens of kind `separator`. /// When there are any extra tokens of that kind, mark all the positions of these tokens as erroneous -fn skip_extraneous_tokens( - stream: &TokenStream, - separator: Kind, - diagnostics: &mut dyn DiagnosticHandler, -) { - if let Some(separator_tok) = stream.pop_if_kind(separator) { - let start_pos = stream.get_pos(separator_tok); +fn skip_extraneous_tokens(ctx: &mut ParsingContext<'_>, separator: Kind) { + if let Some(separator_tok) = ctx.stream.pop_if_kind(separator) { + let start_pos = ctx.stream.get_pos(separator_tok); let mut end_pos = start_pos; - while let Some(separator_tok) = stream.pop_if_kind(separator) { - end_pos = stream.get_pos(separator_tok) + while let Some(separator_tok) = ctx.stream.pop_if_kind(separator) { + end_pos = ctx.stream.get_pos(separator_tok) } - diagnostics.push(Diagnostic::syntax_error( + ctx.diagnostics.push(Diagnostic::syntax_error( start_pos.combine(end_pos), format!("Extraneous '{}'", kind_str(separator)), )); @@ -37,46 +34,45 @@ fn skip_extraneous_tokens( /// where `element` is an AST element and `separator` is a token of some `ast::Kind`. /// The returned list retains information of the whereabouts of the separator tokens. pub fn parse_list_with_separator( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, separator: Kind, - diagnostics: &mut dyn DiagnosticHandler, parse_fn: F, ) -> DiagnosticResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&mut ParsingContext<'_>) -> ParseResult, { - parse_list_with_separator_or_recover(stream, separator, diagnostics, parse_fn, None) + parse_list_with_separator_or_recover(ctx, separator, parse_fn, None) } /// Same as `parse_list_with_separator`. /// However, when supplied with a `recover_token` will skip until either the separator /// or the recover token is found. pub fn parse_list_with_separator_or_recover( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, separator: Kind, - diagnostics: &mut dyn DiagnosticHandler, parse_fn: F, recover_token: Option, ) -> DiagnosticResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&mut ParsingContext<'_>) -> ParseResult, { let mut items = vec![]; let mut tokens = vec![]; loop { - match parse_fn(stream) { + match parse_fn(ctx) { Ok(item) => items.push(item), Err(err) => { if let Some(tok) = recover_token { - stream.skip_until(|kind| kind == separator || kind == tok)?; - diagnostics.push(err); + ctx.stream + .skip_until(|kind| kind == separator || kind == tok)?; + ctx.diagnostics.push(err); } else { return Err(err); } } } - if let Some(separator_tok) = stream.pop_if_kind(separator) { - skip_extraneous_tokens(stream, separator, diagnostics); + if let Some(separator_tok) = ctx.stream.pop_if_kind(separator) { + skip_extraneous_tokens(ctx, separator); tokens.push(separator_tok); } else { break; @@ -85,19 +81,13 @@ where Ok(SeparatedList { items, tokens }) } -pub fn parse_name_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> DiagnosticResult { - parse_list_with_separator(stream, Comma, diagnostics, parse_name) +pub fn parse_name_list(ctx: &mut ParsingContext<'_>) -> DiagnosticResult { + parse_list_with_separator(ctx, Comma, parse_name) } -pub fn parse_ident_list( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> DiagnosticResult { - parse_list_with_separator(stream, Comma, diagnostics, |stream| { - stream.expect_ident().map(WithRef::new) +pub fn parse_ident_list(ctx: &mut ParsingContext<'_>) -> DiagnosticResult { + parse_list_with_separator(ctx, Comma, |ctx| { + ctx.stream.expect_ident().map(WithRef::new) }) } @@ -212,15 +202,14 @@ mod test { #[test] fn parse_recoverable_list() { let code = Code::new("a => b,c => d, e =>)"); - let (res, diag) = code.with_stream_diagnostics(|stream, diag| { + let (res, diag) = code.with_stream_diagnostics(|ctx| { let res = parse_list_with_separator_or_recover( - stream, + ctx, Kind::Comma, - diag, parse_association_element, Some(RightPar), ); - stream.skip(); + ctx.stream.skip(); res }); assert_eq!( @@ -245,9 +234,9 @@ mod test { #[test] fn parse_list_with_erroneous_elements() { let code = Code::new("1,c,d"); - let mut diag: Vec = vec![]; let diag = code - .parse(|stream| parse_ident_list(stream, &mut diag)) + .parse(parse_ident_list) + .0 .expect_err("Should not parse OK"); assert_eq!( diag, diff --git a/vhdl_lang/src/syntax/sequential_statement.rs b/vhdl_lang/src/syntax/sequential_statement.rs index d8d46dd1..971dd706 100644 --- a/vhdl_lang/src/syntax/sequential_statement.rs +++ b/vhdl_lang/src/syntax/sequential_statement.rs @@ -10,29 +10,30 @@ 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::Kind::*; use super::waveform::{parse_delay_mechanism, parse_waveform}; use crate::ast::*; use crate::data::*; use crate::syntax::common::check_label_identifier_mismatch; +use vhdl_lang::syntax::parser::ParsingContext; /// LRM 10.2 Wait statement -fn parse_wait_statement(stream: &TokenStream) -> ParseResult { - stream.expect_kind(Wait)?; +fn parse_wait_statement(ctx: &mut ParsingContext<'_>) -> ParseResult { + ctx.stream.expect_kind(Wait)?; let mut sensitivity_clause = vec![]; - if stream.skip_if_kind(On) { + if ctx.stream.skip_if_kind(On) { loop { - sensitivity_clause.push(parse_name(stream)?); - if !stream.skip_if_kind(Comma) { + sensitivity_clause.push(parse_name(ctx)?); + if !ctx.stream.skip_if_kind(Comma) { break; } } } - let condition_clause = parse_optional(stream, Until, parse_expression)?; - let timeout_clause = parse_optional(stream, For, parse_expression)?; + let condition_clause = parse_optional(ctx, Until, parse_expression)?; + let timeout_clause = parse_optional(ctx, For, parse_expression)?; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; Ok(WaitStatement { sensitivity_clause, condition_clause, @@ -41,13 +42,13 @@ fn parse_wait_statement(stream: &TokenStream) -> ParseResult { } /// LRM 10.3 Assertion statement -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)?; - let severity = parse_optional(stream, Severity, parse_expression)?; +pub fn parse_assert_statement(ctx: &mut ParsingContext<'_>) -> ParseResult { + ctx.stream.expect_kind(Assert)?; + let condition = parse_expression(ctx)?; + let report = parse_optional(ctx, Report, parse_expression)?; + let severity = parse_optional(ctx, Severity, parse_expression)?; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; Ok(AssertStatement { condition, report, @@ -56,31 +57,32 @@ pub fn parse_assert_statement(stream: &TokenStream) -> ParseResult ParseResult { - stream.expect_kind(Report)?; - let report = parse_expression(stream)?; - let severity = parse_optional(stream, Severity, parse_expression)?; +fn parse_report_statement(ctx: &mut ParsingContext<'_>) -> ParseResult { + ctx.stream.expect_kind(Report)?; + let report = parse_expression(ctx)?; + let severity = parse_optional(ctx, Severity, parse_expression)?; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; Ok(ReportStatement { report, severity }) } pub fn parse_labeled_sequential_statements( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { let mut statements = Vec::new(); loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { End | Else | Elsif | When => { break Ok(statements); } - _ => match parse_sequential_statement(stream, diagnostics) { + _ => match parse_sequential_statement(ctx) { Ok(stmt) => statements.push(stmt), Err(diag) => { - diagnostics.push(diag); - let _ = stream.skip_until(|kind| matches!(kind, End | Else | Elsif | When)); + ctx.diagnostics.push(diag); + let _ = ctx + .stream + .skip_until(|kind| matches!(kind, End | Else | Elsif | When)); } }, } @@ -89,17 +91,16 @@ pub fn parse_labeled_sequential_statements( /// LRM 10.8 If statement fn parse_if_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - stream.expect_kind(If)?; + ctx.stream.expect_kind(If)?; let mut conditionals = Vec::new(); let mut else_branch = None; loop { - let condition = parse_expression(stream)?; - stream.expect_kind(Then)?; - let statements = parse_labeled_sequential_statements(stream, diagnostics)?; + let condition = parse_expression(ctx)?; + ctx.stream.expect_kind(Then)?; + let statements = parse_labeled_sequential_statements(ctx)?; let conditional = Conditional { condition, @@ -107,7 +108,7 @@ fn parse_if_statement( }; expect_token!( - stream, + ctx.stream, end_token, Elsif => { conditionals.push(conditional); @@ -116,20 +117,20 @@ fn parse_if_statement( Else => { conditionals.push(conditional); - let statements = parse_labeled_sequential_statements(stream, diagnostics)?; + let statements = parse_labeled_sequential_statements(ctx)?; expect_token!( - stream, + ctx.stream, end_token, End => { - stream.expect_kind(If)?; + ctx.stream.expect_kind(If)?; else_branch = Some(statements); break; } ); }, End => { - stream.expect_kind(If)?; + ctx.stream.expect_kind(If)?; conditionals.push(conditional); break; } @@ -137,8 +138,8 @@ fn parse_if_statement( } let end_label_pos = - check_label_identifier_mismatch(label, stream.pop_optional_ident(), diagnostics); - stream.expect_kind(SemiColon)?; + check_label_identifier_mismatch(ctx, label, ctx.stream.pop_optional_ident()); + ctx.stream.expect_kind(SemiColon)?; Ok(IfStatement { conds: Conditionals { conditionals, @@ -150,41 +151,40 @@ fn parse_if_statement( /// LRM 10.9 Case statement fn parse_case_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - stream.expect_kind(Case)?; - let is_matching = stream.pop_if_kind(Que).is_some(); - let expression = parse_expression(stream)?; - stream.expect_kind(Is)?; - stream.expect_kind(When)?; + ctx.stream.expect_kind(Case)?; + let is_matching = ctx.stream.pop_if_kind(Que).is_some(); + let expression = parse_expression(ctx)?; + ctx.stream.expect_kind(Is)?; + ctx.stream.expect_kind(When)?; let mut alternatives = Vec::new(); loop { - let choices = parse_choices(stream)?; - stream.expect_kind(RightArrow)?; - let statements = parse_labeled_sequential_statements(stream, diagnostics)?; + let choices = parse_choices(ctx)?; + ctx.stream.expect_kind(RightArrow)?; + let statements = parse_labeled_sequential_statements(ctx)?; let alternative = Alternative { choices, item: statements, }; expect_token!( - stream, + ctx.stream, end_token, When => { alternatives.push(alternative); continue; }, End => { - stream.expect_kind(Case)?; + ctx.stream.expect_kind(Case)?; if is_matching { - stream.expect_kind(Que)?; + ctx.stream.expect_kind(Que)?; } - let end_label_pos = check_label_identifier_mismatch(label, stream.pop_optional_ident(), diagnostics); + let end_label_pos = check_label_identifier_mismatch(ctx, label, ctx.stream.pop_optional_ident()); alternatives.push(alternative); - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; return Ok(CaseStatement { is_matching, expression, @@ -198,38 +198,37 @@ fn parse_case_statement( /// LRM 10.10 Loop statement fn parse_loop_statement( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let iteration_scheme = { expect_token!( - stream, token, + ctx.stream, token, Loop => None, While => { - let expression = parse_expression(stream)?; - stream.expect_kind(Loop)?; + let expression = parse_expression(ctx)?; + ctx.stream.expect_kind(Loop)?; Some(IterationScheme::While(expression)) }, For => { - let ident = stream.expect_ident()?; - stream.expect_kind(In)?; - let discrete_range = parse_discrete_range(stream)?; - stream.expect_kind(Loop)?; + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(In)?; + let discrete_range = parse_discrete_range(ctx)?; + ctx.stream.expect_kind(Loop)?; Some(IterationScheme::For(ident.into(), discrete_range)) } ) }; - let statements = parse_labeled_sequential_statements(stream, diagnostics)?; + let statements = parse_labeled_sequential_statements(ctx)?; expect_token!( - stream, + ctx.stream, end_token, End => { - stream.expect_kind(Loop)?; - let end_label_pos = check_label_identifier_mismatch(label, stream.pop_optional_ident(), diagnostics); - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(Loop)?; + let end_label_pos = check_label_identifier_mismatch(ctx, label, ctx.stream.pop_optional_ident()); + ctx.stream.expect_kind(SemiColon)?; Ok(LoopStatement { iteration_scheme, statements, @@ -240,11 +239,11 @@ fn parse_loop_statement( } /// LRM 10.11 Next statement -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)?; - stream.expect_kind(SemiColon)?; +fn parse_next_statement(ctx: &mut ParsingContext<'_>) -> ParseResult { + ctx.stream.expect_kind(Next)?; + let loop_label = ctx.stream.pop_optional_ident(); + let condition = parse_optional(ctx, When, parse_expression)?; + ctx.stream.expect_kind(SemiColon)?; Ok(NextStatement { loop_label: loop_label.map(WithRef::new), condition, @@ -252,11 +251,11 @@ fn parse_next_statement(stream: &TokenStream) -> ParseResult { } /// LRM 10.12 Exit statement -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)?; - stream.expect_kind(SemiColon)?; +fn parse_exit_statement(ctx: &mut ParsingContext<'_>) -> ParseResult { + ctx.stream.expect_kind(Exit)?; + let loop_label = ctx.stream.pop_optional_ident(); + let condition = parse_optional(ctx, When, parse_expression)?; + ctx.stream.expect_kind(SemiColon)?; Ok(ExitStatement { loop_label: loop_label.map(WithRef::new), condition, @@ -264,47 +263,47 @@ fn parse_exit_statement(stream: &TokenStream) -> ParseResult { } /// LRM 10.13 Return statement -fn parse_return_statement(stream: &TokenStream) -> ParseResult { - stream.expect_kind(Return)?; +fn parse_return_statement(ctx: &mut ParsingContext<'_>) -> ParseResult { + ctx.stream.expect_kind(Return)?; let expression = { - if stream.peek_kind() == Some(SemiColon) { + if ctx.stream.peek_kind() == Some(SemiColon) { None } else { - Some(parse_expression(stream)?) + Some(parse_expression(ctx)?) } }; - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; Ok(ReturnStatement { expression }) } /// LRM 10.5 Signal assignment statement pub fn parse_signal_assignment_right_hand( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult> { - parse_assignment_right_hand(stream, parse_waveform) + parse_assignment_right_hand(ctx, parse_waveform) } /// LRM 10.6 Variable assignment statement fn parse_variable_assignment_right_hand( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult>> { - parse_assignment_right_hand(stream, parse_expression) + parse_assignment_right_hand(ctx, parse_expression) } fn parse_assignment_right_hand( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, parse_item: F, ) -> ParseResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&mut ParsingContext<'_>) -> ParseResult, { - let item = parse_item(stream)?; + let item = parse_item(ctx)?; expect_token!( - stream, + ctx.stream, token, When => { - Ok(AssignmentRightHand::Conditional(parse_conditonals(stream, item, parse_item)?)) + Ok(AssignmentRightHand::Conditional(parse_conditonals(ctx, item, parse_item)?)) }, SemiColon => { @@ -314,14 +313,14 @@ where } fn parse_conditonals( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, initial_item: T, parse_item: F, ) -> ParseResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&mut ParsingContext<'_>) -> ParseResult, { - let condition = parse_expression(stream)?; + let condition = parse_expression(ctx)?; let cond_expr = Conditional { condition, item: initial_item, @@ -332,22 +331,22 @@ where loop { expect_token!( - stream, + ctx.stream, token, SemiColon => { break; }, Else => { - let item = parse_item(stream)?; + let item = parse_item(ctx)?; expect_token!( - stream, + ctx.stream, token, SemiColon => { else_item = Some(item); break; }, When => { - let condition = parse_expression(stream)?; + let condition = parse_expression(ctx)?; let conditional = Conditional { condition, item @@ -366,23 +365,23 @@ where } pub fn parse_selection( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, expression: WithPos, parse_item: F, ) -> ParseResult> where - F: Fn(&TokenStream) -> ParseResult, + F: Fn(&mut ParsingContext<'_>) -> ParseResult, { let mut alternatives = Vec::with_capacity(2); loop { - let item = parse_item(stream)?; - stream.expect_kind(When)?; - let choices = parse_choices(stream)?; + let item = parse_item(ctx)?; + ctx.stream.expect_kind(When)?; + let choices = parse_choices(ctx)?; alternatives.push(Alternative { choices, item }); expect_token!( - stream, + ctx.stream, token, Comma => {}, SemiColon => break @@ -395,15 +394,15 @@ where }) } -fn parse_optional_force_mode(stream: &TokenStream) -> ParseResult> { - let token = stream.peek_expect()?; +fn parse_optional_force_mode(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let token = ctx.stream.peek_expect()?; let optional_force_mode = match token.kind { In => { - stream.skip(); + ctx.stream.skip(); Some(ForceMode::In) } Out => { - stream.skip(); + ctx.stream.skip(); Some(ForceMode::Out) } _ => None, @@ -413,33 +412,33 @@ fn parse_optional_force_mode(stream: &TokenStream) -> ParseResult, target: WithPos, ) -> ParseResult { Ok(expect_token!( - stream, + ctx.stream, token, ColonEq => { SequentialStatement::VariableAssignment(VariableAssignment { target, - rhs: parse_variable_assignment_right_hand(stream)? + rhs: parse_variable_assignment_right_hand(ctx)? }) }, LTE => { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { Force => { - stream.skip(); + ctx.stream.skip(); SequentialStatement::SignalForceAssignment(SignalForceAssignment { target, - force_mode: parse_optional_force_mode(stream)?, - rhs: parse_variable_assignment_right_hand(stream)? + force_mode: parse_optional_force_mode(ctx)?, + rhs: parse_variable_assignment_right_hand(ctx)? }) }, Release => { - stream.skip(); - let force_mode = parse_optional_force_mode(stream)?; - stream.expect_kind(SemiColon)?; + ctx.stream.skip(); + let force_mode = parse_optional_force_mode(ctx)?; + ctx.stream.expect_kind(SemiColon)?; SequentialStatement::SignalReleaseAssignment(SignalReleaseAssignment { target, @@ -447,11 +446,11 @@ fn parse_assignment_or_procedure_call( }) } _ => { - let delay_mechanism = parse_delay_mechanism(stream)?; + let delay_mechanism = parse_delay_mechanism(ctx)?; SequentialStatement::SignalAssignment(SignalAssignment { target, delay_mechanism, - rhs: parse_signal_assignment_right_hand(stream)? + rhs: parse_signal_assignment_right_hand(ctx)? }) } } @@ -476,40 +475,40 @@ fn parse_assignment_or_procedure_call( )) } -pub fn parse_target(stream: &TokenStream) -> ParseResult> { - if stream.next_kind_is(LeftPar) { - Ok(parse_aggregate(stream)?.map_into(Target::Aggregate)) +pub fn parse_target(ctx: &mut ParsingContext<'_>) -> ParseResult> { + if ctx.stream.next_kind_is(LeftPar) { + Ok(parse_aggregate(ctx)?.map_into(Target::Aggregate)) } else { - Ok(parse_name(stream)?.map_into(Target::Name)) + Ok(parse_name(ctx)?.map_into(Target::Name)) } } -fn parse_selected_assignment(stream: &TokenStream) -> ParseResult { - let expression = parse_expression(stream)?; - stream.expect_kind(Select)?; - let target = parse_target(stream)?; +fn parse_selected_assignment(ctx: &mut ParsingContext<'_>) -> ParseResult { + let expression = parse_expression(ctx)?; + ctx.stream.expect_kind(Select)?; + let target = parse_target(ctx)?; expect_token!( - stream, + ctx.stream, token, ColonEq => { - let rhs = AssignmentRightHand::Selected(parse_selection(stream, expression, parse_expression)?); + let rhs = AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?); Ok(SequentialStatement::VariableAssignment(VariableAssignment { target, rhs })) }, LTE => { - if stream.skip_if_kind(Force) { + if ctx.stream.skip_if_kind(Force) { Ok(SequentialStatement::SignalForceAssignment(SignalForceAssignment { target, - force_mode: parse_optional_force_mode(stream)?, - rhs: AssignmentRightHand::Selected(parse_selection(stream, expression, parse_expression)?) + force_mode: parse_optional_force_mode(ctx)?, + rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_expression)?) })) } else { Ok(SequentialStatement::SignalAssignment(SignalAssignment { target, - delay_mechanism: parse_delay_mechanism(stream)?, - rhs: AssignmentRightHand::Selected(parse_selection(stream, expression, parse_waveform)?) + delay_mechanism: parse_delay_mechanism(ctx)?, + rhs: AssignmentRightHand::Selected(parse_selection(ctx, expression, parse_waveform)?) })) } } @@ -517,37 +516,36 @@ fn parse_selected_assignment(stream: &TokenStream) -> ParseResult, label: Option<&Ident>, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; let statement = { try_init_token_kind!( token, - Wait => SequentialStatement::Wait(parse_wait_statement(stream)?), - Assert => SequentialStatement::Assert(parse_assert_statement(stream)?), - Report => SequentialStatement::Report(parse_report_statement(stream)?), - If => SequentialStatement::If(parse_if_statement(stream, label, diagnostics)?), - Case => SequentialStatement::Case(parse_case_statement(stream, label, diagnostics)?), + Wait => SequentialStatement::Wait(parse_wait_statement(ctx)?), + Assert => SequentialStatement::Assert(parse_assert_statement(ctx)?), + Report => SequentialStatement::Report(parse_report_statement(ctx)?), + If => SequentialStatement::If(parse_if_statement(ctx, label)?), + Case => SequentialStatement::Case(parse_case_statement(ctx, label)?), For | Loop | While => { - SequentialStatement::Loop(parse_loop_statement(stream, label, diagnostics)?) + SequentialStatement::Loop(parse_loop_statement(ctx, label)?) }, - Next => SequentialStatement::Next(parse_next_statement(stream)?), - Exit => SequentialStatement::Exit(parse_exit_statement(stream)?), - Return => SequentialStatement::Return(parse_return_statement(stream)?), + Next => SequentialStatement::Next(parse_next_statement(ctx)?), + Exit => SequentialStatement::Exit(parse_exit_statement(ctx)?), + Return => SequentialStatement::Return(parse_return_statement(ctx)?), Null => { - stream.skip(); - stream.expect_kind(SemiColon)?; + ctx.stream.skip(); + ctx.stream.expect_kind(SemiColon)?; SequentialStatement::Null }, With => { - stream.skip(); - parse_selected_assignment(stream)? + ctx.stream.skip(); + parse_selected_assignment(ctx)? }, Identifier|LeftPar|LtLt => { - let target = parse_target(stream)?; - parse_assignment_or_procedure_call(stream, target)? + let target = parse_target(ctx)?; + parse_assignment_or_procedure_call(ctx, target)? } ) }; @@ -555,35 +553,33 @@ fn parse_unlabeled_sequential_statement( } pub fn parse_sequential_statement( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start = stream.peek_expect()?; + let start = ctx.stream.peek_expect()?; - if stream.next_kind_is(Identifier) { - let name = parse_name(stream)?; - if stream.skip_if_kind(Colon) { + if ctx.stream.next_kind_is(Identifier) { + let name = parse_name(ctx)?; + if ctx.stream.skip_if_kind(Colon) { let label = Some(to_simple_name(name)?); - let start = stream.peek_expect()?; - let statement = - parse_unlabeled_sequential_statement(stream, label.as_ref(), diagnostics)?; - let end = stream.last().unwrap(); + let start = ctx.stream.peek_expect()?; + let statement = parse_unlabeled_sequential_statement(ctx, label.as_ref())?; + let end = ctx.stream.last().unwrap(); Ok(LabeledSequentialStatement { label: WithDecl::new(label), statement: WithPos::new(statement, start.pos.combine(&end.pos)), }) } else { let target = name.map_into(Target::Name); - let statement = parse_assignment_or_procedure_call(stream, target)?; - let end = stream.last().unwrap(); + let statement = parse_assignment_or_procedure_call(ctx, target)?; + let end = ctx.stream.last().unwrap(); Ok(LabeledSequentialStatement { label: WithDecl::new(None), statement: WithPos::new(statement, start.pos.combine(&end.pos)), }) } } else { - let statement = parse_unlabeled_sequential_statement(stream, None, diagnostics)?; - let end = stream.last().unwrap(); + let statement = parse_unlabeled_sequential_statement(ctx, None)?; + let end = ctx.stream.last().unwrap(); Ok(LabeledSequentialStatement { label: WithDecl::new(None), statement: WithPos::new(statement, start.pos.combine(&end.pos)), diff --git a/vhdl_lang/src/syntax/subprogram.rs b/vhdl_lang/src/syntax/subprogram.rs index 4bba9486..ca7c67e8 100644 --- a/vhdl_lang/src/syntax/subprogram.rs +++ b/vhdl_lang/src/syntax/subprogram.rs @@ -9,55 +9,56 @@ 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::*, TokenAccess, TokenId, TokenSpan, TokenStream}; +use super::tokens::{kinds_error, Kind::*, TokenAccess, TokenId, TokenSpan}; use crate::ast::*; use crate::data::*; use crate::syntax::concurrent_statement::parse_map_aspect; use crate::syntax::interface_declaration::parse_generic_interface_list; use crate::syntax::names::parse_name; +use vhdl_lang::syntax::parser::ParsingContext; -pub fn parse_signature(stream: &TokenStream) -> ParseResult> { - let left_square = stream.expect_kind(LeftSquare)?; - let start_pos = stream.get_pos(left_square); +pub fn parse_signature(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let left_square = ctx.stream.expect_kind(LeftSquare)?; + let start_pos = ctx.stream.get_pos(left_square); let mut type_marks = Vec::new(); let mut return_mark = None; let pos = peek_token!( - stream, token, + ctx.stream, token, Return => { - stream.skip(); - return_mark = Some(parse_type_mark(stream)?); - let right_square = stream.expect_kind(RightSquare)?; - start_pos.combine(stream.get_pos(right_square)) + ctx.stream.skip(); + return_mark = Some(parse_type_mark(ctx)?); + let right_square = ctx.stream.expect_kind(RightSquare)?; + start_pos.combine(ctx.stream.get_pos(right_square)) }, RightSquare => { - stream.skip(); + ctx.stream.skip(); start_pos.combine(&token.pos) }, Identifier => { loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; match token.kind { Identifier => { - type_marks.push(parse_type_mark(stream)?); + type_marks.push(parse_type_mark(ctx)?); expect_token!( - stream, + ctx.stream, sep_token, Comma => {}, RightSquare => { break start_pos.combine(&sep_token.pos); }, Return => { - return_mark = Some(parse_type_mark(stream)?); - let right_square = stream.expect_kind(RightSquare)?; - break start_pos.combine(stream.get_pos(right_square)); + return_mark = Some(parse_type_mark(ctx)?); + let right_square = ctx.stream.expect_kind(RightSquare)?; + break start_pos.combine(ctx.stream.get_pos(right_square)); } ) } _ => { - stream.skip(); - return Err(kinds_error(stream.pos_before(token), &[Identifier])) + ctx.stream.skip(); + return Err(kinds_error(ctx.stream.pos_before(token), &[Identifier])) } }; } @@ -72,9 +73,9 @@ pub fn parse_signature(stream: &TokenStream) -> ParseResult> Ok(WithPos::new(signature, pos)) } -fn parse_designator(stream: &TokenStream) -> ParseResult> { +fn parse_designator(ctx: &mut ParsingContext<'_>) -> ParseResult> { Ok(expect_token!( - stream, + ctx.stream, token, Identifier => token.to_identifier_value()?.map_into(SubprogramDesignator::Identifier), StringLiteral => token.to_operator_symbol()?.map_into(SubprogramDesignator::OperatorSymbol) @@ -86,14 +87,13 @@ fn parse_designator(stream: &TokenStream) -> ParseResult, ) -> ParseResult> { - let Some(generic) = stream.pop_if_kind(Generic) else { + let Some(generic) = ctx.stream.pop_if_kind(Generic) else { return Ok(None); }; - let generic_list = parse_generic_interface_list(stream, diagnostics)?; - let map_aspect = parse_map_aspect(stream, Generic, diagnostics)?; + let generic_list = parse_generic_interface_list(ctx)?; + let map_aspect = parse_map_aspect(ctx, Generic)?; Ok(Some(SubprogramHeader { generic_tok: generic, @@ -103,11 +103,10 @@ pub fn parse_optional_subprogram_header( } pub fn parse_subprogram_instantiation( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start_token = stream.get_current_token_id(); - let tok = stream.peek_expect()?; + let start_token = ctx.stream.get_current_token_id(); + let tok = ctx.stream.peek_expect()?; let kind = match tok.kind { Procedure => SubprogramKind::Procedure, Function => SubprogramKind::Function, @@ -118,18 +117,18 @@ pub fn parse_subprogram_instantiation( )) } }; - stream.skip(); - let ident = WithDecl::new(stream.expect_ident()?); - stream.expect_kind(Is)?; - stream.expect_kind(New)?; - let subprogram_name = parse_name(stream)?; - let signature = if stream.next_kind_is(LeftSquare) { - Some(parse_signature(stream)?) + ctx.stream.skip(); + let ident = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.expect_kind(Is)?; + ctx.stream.expect_kind(New)?; + let subprogram_name = parse_name(ctx)?; + let signature = if ctx.stream.next_kind_is(LeftSquare) { + Some(parse_signature(ctx)?) } else { None }; - let generic_map = parse_map_aspect(stream, Generic, diagnostics)?; - let end_token = stream.expect_kind(SemiColon)?; + let generic_map = parse_map_aspect(ctx, Generic)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(SubprogramInstantiation { span: TokenSpan::new(start_token, end_token), kind, @@ -141,46 +140,42 @@ pub fn parse_subprogram_instantiation( } pub fn parse_subprogram_specification( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { let (is_function, is_pure) = { expect_token!( - stream, + ctx.stream, token, Procedure => (false, false), Function => (true, true), Impure => { - stream.expect_kind(Function)?; + ctx.stream.expect_kind(Function)?; (true, false) }, Pure => { - stream.expect_kind(Function)?; + ctx.stream.expect_kind(Function)?; (true, true) } ) }; - let designator = parse_designator(stream)?; + let designator = parse_designator(ctx)?; - let header = parse_optional_subprogram_header(stream, diagnostics)?; + let header = parse_optional_subprogram_header(ctx)?; let (parameter_list, param_tok) = { - if let Some(parameter) = stream.pop_if_kind(Parameter) { - ( - parse_parameter_interface_list(stream, diagnostics)?, - Some(parameter), - ) - } else if stream.peek_kind() == Some(LeftPar) { - (parse_parameter_interface_list(stream, diagnostics)?, None) + if let Some(parameter) = ctx.stream.pop_if_kind(Parameter) { + (parse_parameter_interface_list(ctx)?, Some(parameter)) + } else if ctx.stream.peek_kind() == Some(LeftPar) { + (parse_parameter_interface_list(ctx)?, None) } else { (Vec::new(), None) } }; if is_function { - stream.expect_kind(Return)?; - let return_type = parse_type_mark(stream)?; + ctx.stream.expect_kind(Return)?; + let return_type = parse_type_mark(ctx)?; Ok(SubprogramSpecification::Function(FunctionSpecification { pure: is_pure, param_tok, @@ -200,12 +195,11 @@ pub fn parse_subprogram_specification( } pub fn parse_subprogram_declaration( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - let start_token = stream.get_current_token_id(); - let specification = parse_subprogram_specification(stream, diagnostics)?; - let end_token = stream.expect_kind(SemiColon)?; + let start_token = ctx.stream.get_current_token_id(); + let specification = parse_subprogram_specification(ctx)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(SubprogramDeclaration { span: TokenSpan::new(start_token, end_token), @@ -215,10 +209,9 @@ pub fn parse_subprogram_declaration( /// LRM 4.3 Subprogram bodies pub fn parse_subprogram_body( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, specification_start_token: TokenId, specification: SubprogramSpecification, - diagnostics: &mut dyn DiagnosticHandler, ) -> ParseResult { let end_kind = { match specification { @@ -226,26 +219,26 @@ pub fn parse_subprogram_body( SubprogramSpecification::Function(..) => Function, } }; - let declarations = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(Begin)?; + let declarations = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(Begin)?; - let statements = parse_labeled_sequential_statements(stream, diagnostics)?; + let statements = parse_labeled_sequential_statements(ctx)?; expect_token!( - stream, + ctx.stream, end_token, End => { - stream.pop_if_kind(end_kind); + ctx.stream.pop_if_kind(end_kind); - let end_ident = if matches!(stream.peek_kind(), Some(Identifier | StringLiteral)) { - Some(parse_designator(stream)?) + let end_ident = if matches!(ctx.stream.peek_kind(), Some(Identifier | StringLiteral)) { + Some(parse_designator(ctx)?) } else { None }; - let end_token = stream.expect_kind(SemiColon)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(SubprogramBody { span: TokenSpan::new(specification_start_token, end_token), - end_ident_pos: check_end_identifier_mismatch(specification.subpgm_designator(), end_ident, diagnostics), + end_ident_pos: check_end_identifier_mismatch(ctx, specification.subpgm_designator(), end_ident), specification, declarations, statements, @@ -254,28 +247,25 @@ pub fn parse_subprogram_body( ) } -pub fn parse_subprogram( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - if stream.next_kinds_are(&[Procedure, Identifier, Is, New]) - || stream.next_kinds_are(&[Function, Identifier, Is, New]) +pub fn parse_subprogram(ctx: &mut ParsingContext<'_>) -> ParseResult { + if ctx.stream.next_kinds_are(&[Procedure, Identifier, Is, New]) + || ctx.stream.next_kinds_are(&[Function, Identifier, Is, New]) { return Ok(Declaration::SubprogramInstantiation( - parse_subprogram_instantiation(stream, diagnostics)?, + parse_subprogram_instantiation(ctx)?, )); } - let start_token = stream.get_current_token_id(); - let specification = parse_subprogram_specification(stream, diagnostics)?; + let start_token = ctx.stream.get_current_token_id(); + let specification = parse_subprogram_specification(ctx)?; expect_token!( - stream, + ctx.stream, token, Is => { - Ok(Declaration::SubprogramBody(parse_subprogram_body(stream, start_token, specification, diagnostics)?)) + Ok(Declaration::SubprogramBody(parse_subprogram_body(ctx, start_token, specification)?)) }, SemiColon => { Ok(Declaration::SubprogramDeclaration(SubprogramDeclaration{ - span: TokenSpan::new(start_token, stream.get_last_token_id()), + span: TokenSpan::new(start_token, ctx.stream.get_last_token_id()), specification, })) } diff --git a/vhdl_lang/src/syntax/subtype_indication.rs b/vhdl_lang/src/syntax/subtype_indication.rs index 813f3a09..b57a7168 100644 --- a/vhdl_lang/src/syntax/subtype_indication.rs +++ b/vhdl_lang/src/syntax/subtype_indication.rs @@ -7,20 +7,21 @@ 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::*, TokenAccess, TokenStream}; +use super::tokens::{kinds_error, Kind::*, TokenAccess}; /// LRM 6.3 Subtype declarations use crate::ast::*; use crate::data::WithPos; use crate::syntax::TokenId; +use vhdl_lang::syntax::parser::ParsingContext; -fn parse_record_element_constraint(stream: &TokenStream) -> ParseResult { - let ident = stream.expect_ident()?; - let constraint = Box::new(parse_composite_constraint(stream)?); +fn parse_record_element_constraint(ctx: &mut ParsingContext<'_>) -> ParseResult { + let ident = ctx.stream.expect_ident()?; + let constraint = Box::new(parse_composite_constraint(ctx)?); Ok(ElementConstraint { ident, constraint }) } fn parse_array_constraint( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, leftpar: TokenId, // Open is None initial: Option, @@ -29,17 +30,17 @@ fn parse_array_constraint( let mut end_pos = loop { expect_token!( - stream, sep_token, + ctx.stream, sep_token, RightPar => break sep_token.pos.clone(), Comma => {} ); - discrete_ranges.push(parse_discrete_range(stream)?); + discrete_ranges.push(parse_discrete_range(ctx)?); }; // Array element constraint let element_constraint = { - if let Some(elemement_constraint) = parse_subtype_constraint(stream)? { + if let Some(elemement_constraint) = parse_subtype_constraint(ctx)? { end_pos = elemement_constraint.pos.clone(); Some(Box::new(elemement_constraint)) } else { @@ -47,7 +48,7 @@ fn parse_array_constraint( } }; - let leftpar_pos = stream.get_pos(leftpar).clone(); + let leftpar_pos = ctx.stream.get_pos(leftpar).clone(); Ok(WithPos::from( SubtypeConstraint::Array(discrete_ranges, element_constraint), @@ -55,50 +56,54 @@ fn parse_array_constraint( )) } -fn parse_composite_constraint(stream: &TokenStream) -> ParseResult> { +fn parse_composite_constraint( + ctx: &mut ParsingContext<'_>, +) -> ParseResult> { // There is no finite lookahead that can differentiate // between array and record element constraint - let leftpar = stream.expect_kind(LeftPar)?; - let state = stream.state(); + let leftpar = ctx.stream.expect_kind(LeftPar)?; + let state = ctx.stream.state(); let mut initial = { - if stream.skip_if_kind(Open) { + if ctx.stream.skip_if_kind(Open) { // Array constraint open Ok(None) } else { - parse_discrete_range(stream).map(Some) + parse_discrete_range(ctx).map(Some) } }; - if let Some(token) = stream.peek() { + if let Some(token) = ctx.stream.peek() { match token.kind { RightPar | Comma => {} _ => { - initial = Err(kinds_error(stream.pos_before(token), &[RightPar, Comma]) - .when("parsing index constraint")); + initial = Err( + kinds_error(ctx.stream.pos_before(token), &[RightPar, Comma]) + .when("parsing index constraint"), + ); } } } if let Ok(initial) = initial { // Array constraint - parse_array_constraint(stream, leftpar, initial) + parse_array_constraint(ctx, leftpar, initial) } else { // Record constraint - stream.set_state(state); - let mut constraints = vec![parse_record_element_constraint(stream)?]; + ctx.stream.set_state(state); + let mut constraints = vec![parse_record_element_constraint(ctx)?]; let rightpar_pos = loop { expect_token!( - stream, + ctx.stream, sep_token, RightPar => break sep_token.pos.clone(), Comma => {} ); - constraints.push(parse_record_element_constraint(stream)?); + constraints.push(parse_record_element_constraint(ctx)?); }; - let leftpar_pos = stream.get_pos(leftpar).clone(); + let leftpar_pos = ctx.stream.get_pos(leftpar).clone(); Ok(WithPos::from( SubtypeConstraint::Record(constraints), @@ -108,19 +113,19 @@ fn parse_composite_constraint(stream: &TokenStream) -> ParseResult, ) -> ParseResult>> { - if let Some(token) = stream.peek() { + if let Some(token) = ctx.stream.peek() { let constraint = match token.kind { Range => { - stream.skip(); + ctx.stream.skip(); Some( - parse_range(stream)? + parse_range(ctx)? .map_into(SubtypeConstraint::Range) .combine_pos_with(&token), ) } - LeftPar => Some(parse_composite_constraint(stream)?), + LeftPar => Some(parse_composite_constraint(ctx)?), _ => None, }; Ok(constraint) @@ -130,17 +135,17 @@ pub fn parse_subtype_constraint( } pub fn parse_element_resolution_indication( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult { - stream.expect_kind(LeftPar)?; + ctx.stream.expect_kind(LeftPar)?; - let first_ident = stream.expect_ident()?; + let first_ident = ctx.stream.expect_ident()?; Ok(peek_token!( - stream, token, + ctx.stream, token, Dot | RightPar => { let selected_name = first_ident.map_into(|sym| Name::Designator(Designator::Identifier(sym).into_ref())); - stream.expect_kind(RightPar)?; + ctx.stream.expect_kind(RightPar)?; ResolutionIndication::ArrayElement(selected_name) }, Identifier | LeftPar => { @@ -152,15 +157,15 @@ pub fn parse_element_resolution_indication( if element_resolutions.is_empty() { first_ident.clone() } else { - stream.expect_ident()? + ctx.stream.expect_ident()? } }; let resolution = { - if stream.peek_kind() == Some(LeftPar) { - parse_element_resolution_indication(stream)? + if ctx.stream.peek_kind() == Some(LeftPar) { + parse_element_resolution_indication(ctx)? } else { - ResolutionIndication::FunctionName(parse_selected_name(stream)?) + ResolutionIndication::FunctionName(parse_selected_name(ctx)?) } }; @@ -170,7 +175,7 @@ pub fn parse_element_resolution_indication( }); expect_token!( - stream, + ctx.stream, token, RightPar => break, Comma => {} @@ -183,28 +188,28 @@ pub fn parse_element_resolution_indication( )) } -pub fn parse_subtype_indication(stream: &TokenStream) -> ParseResult { +pub fn parse_subtype_indication(ctx: &mut ParsingContext<'_>) -> ParseResult { let (resolution, type_mark) = { - if stream.peek_kind() == Some(LeftPar) { - let resolution = parse_element_resolution_indication(stream)?; - let type_mark = parse_type_mark(stream)?; + if ctx.stream.peek_kind() == Some(LeftPar) { + let resolution = parse_element_resolution_indication(ctx)?; + let type_mark = parse_type_mark(ctx)?; (resolution, type_mark) } else { - let selected_name = parse_selected_name(stream)?; - match stream.peek_kind() { + let selected_name = parse_selected_name(ctx)?; + match ctx.stream.peek_kind() { Some(Identifier) => ( ResolutionIndication::FunctionName(selected_name), - parse_type_mark(stream)?, + parse_type_mark(ctx)?, ), _ => ( ResolutionIndication::Unresolved, - parse_type_mark_starting_with_name(stream, selected_name)?, + parse_type_mark_starting_with_name(ctx, selected_name)?, ), } } }; - let constraint = parse_subtype_constraint(stream)?; + let constraint = parse_subtype_constraint(ctx)?; Ok(SubtypeIndication { resolution, diff --git a/vhdl_lang/src/syntax/test.rs b/vhdl_lang/src/syntax/test.rs index 6edfea7b..d6a81372 100644 --- a/vhdl_lang/src/syntax/test.rs +++ b/vhdl_lang/src/syntax/test.rs @@ -37,6 +37,7 @@ use crate::standard::VHDLStandard; use crate::syntax::concurrent_statement::parse_map_aspect; use crate::syntax::context::{parse_context, DeclarationOrReference}; use crate::syntax::names::parse_association_element; +use crate::syntax::parser::ParsingContext; use crate::syntax::subprogram::{parse_optional_subprogram_header, parse_subprogram_instantiation}; use crate::syntax::{kind_str, TokenAccess, TokenId, TokenSpan}; use std::collections::hash_map::DefaultHasher; @@ -335,9 +336,9 @@ impl Code { } /// Helper method to run lower level parsing function at specific substring - pub fn parse(&self, parse_fun: F) -> R + pub fn parse(&self, parse_fun: F) -> (R, Vec) where - F: FnOnce(&TokenStream) -> R, + F: FnOnce(&mut ParsingContext<'_>) -> R, { let contents = self.pos.source.contents(); let source = Source::from_contents( @@ -347,19 +348,24 @@ 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 stream = TokenStream::new(tokenizer, &mut NoDiagnostics); forward(&stream, self.pos.start()); - parse_fun(&mut stream) + let mut diag = Vec::new(); + let mut ctx = ParsingContext { + stream: &stream, + diagnostics: &mut diag, + }; + (parse_fun(&mut ctx), diag) } /// Expect Ok() value - pub fn parse_ok(&self, parse_fun: F) -> R + pub fn parse_ok(&self, parse_fun: F) -> (R, Vec) where - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&mut ParsingContext<'_>) -> ParseResult, { match self.parse(parse_fun) { - Ok(res) => res, - Err(diagnostic) => { + (Ok(res), diag) => (res, diag), + (Err(diagnostic), _) => { panic!("{}", diagnostic.show_default()); } } @@ -367,51 +373,34 @@ impl Code { pub fn with_partial_stream(&self, parse_fun: F) -> R where - F: FnOnce(&TokenStream) -> R, + R: Debug, + F: FnOnce(&mut ParsingContext<'_>) -> 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); - parse_fun(&mut stream) + let (res, diag) = self.with_partial_stream_diagnostics(parse_fun); + check_no_diagnostics(&diag); + res } pub fn with_stream(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&mut ParsingContext<'_>) -> ParseResult, { - let parse_fun_eof = |stream: &TokenStream| { - let result = parse_fun(stream); - match result { - Err(err) => { - println!("{err:#?}"); - println!("{}", err.show_default()); - panic!("Got Err()"); - } - Ok(result) => { - if let Some(token) = stream.peek() { - println!("result = {result:#?}"); - panic!("Expected EOF got {token:?}"); - } - result - } - } - }; - - self.with_partial_stream(parse_fun_eof) + let (res, diag) = self.with_stream_diagnostics(parse_fun); + check_no_diagnostics(&diag); + res } pub fn with_stream_err(&self, parse_fun: F) -> Diagnostic where R: Debug, - F: FnOnce(&TokenStream) -> ParseResult, + F: FnOnce(&mut ParsingContext<'_>) -> ParseResult, { - let parse_fun_eof = |stream: &TokenStream| { - let result = parse_fun(stream); + let parse_fun_eof = |ctx: &mut ParsingContext<'_>| { + let result = parse_fun(ctx); match result { Err(err) => { - if let Some(token) = stream.peek() { + if let Some(token) = ctx.stream.peek() { println!("err = {err:#?}"); panic!("Expected EOF got {token:?}"); } @@ -429,28 +418,51 @@ 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(&mut ParsingContext<'_>) -> R, { - let mut diagnostics = Vec::new(); - let result = - self.with_partial_stream(|stream: &TokenStream| parse_fun(stream, &mut diagnostics)); - (result, diagnostics) + let contents = self.pos.source.contents(); + let reader = ContentReader::new(&contents); + let tokenizer = Tokenizer::new(&self.symbols, &self.pos.source, reader); + let stream = TokenStream::new(tokenizer, &mut NoDiagnostics); + let mut diag = Vec::new(); + let mut ctx = ParsingContext { + stream: &stream, + diagnostics: &mut diag, + }; + let res = parse_fun(&mut ctx); + (res, diag) } pub fn with_stream_diagnostics(&self, parse_fun: F) -> (R, Vec) where R: Debug, - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&mut ParsingContext<'_>) -> ParseResult, { - let mut diagnostics = Vec::new(); - let result = self.with_stream(|stream: &TokenStream| parse_fun(stream, &mut diagnostics)); - (result, diagnostics) + let parse_fun_eof = |ctx: &mut ParsingContext| { + let result = parse_fun(ctx); + match result { + Err(err) => { + println!("{err:#?}"); + println!("{}", err.show_default()); + panic!("Got Err()"); + } + Ok(result) => { + if let Some(token) = ctx.stream.peek() { + println!("result = {result:#?}"); + panic!("Expected EOF got {token:?}"); + } + result + } + } + }; + + self.with_partial_stream_diagnostics(parse_fun_eof) } pub fn with_stream_no_diagnostics(&self, parse_fun: F) -> R where R: Debug, - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&mut ParsingContext<'_>) -> ParseResult, { let (result, diagnostics) = self.with_stream_diagnostics(parse_fun); check_no_diagnostics(&diagnostics); @@ -458,51 +470,49 @@ impl Code { } pub fn declarative_part(&self) -> Vec { - let mut diagnostics = Vec::new(); - let res = self.parse_ok(|stream| parse_declarative_part(stream, &mut diagnostics)); - check_no_diagnostics(&diagnostics); - res + self.parse_ok_no_diagnostics(parse_declarative_part) } /// 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_no_diagnostics(|ctx| ctx.stream.expect_ident()) } pub fn attr_ident(&self) -> WithPos { - self.parse_ok(|stream: &TokenStream| stream.expect_ident()) + self.parse_ok_no_diagnostics(|ctx| ctx.stream.expect_ident()) .map_into(|i| AttributeDesignator::Ident(WithRef::new(i))) } pub fn decl_ident(&self) -> WithDecl { - WithDecl::new(self.parse_ok(|stream: &TokenStream| stream.expect_ident())) + WithDecl::new(self.parse_ok_no_diagnostics(|ctx| ctx.stream.expect_ident())) } pub fn designator(&self) -> WithPos { - self.parse_ok(parse_designator) + self.parse_ok_no_diagnostics(parse_designator) } pub fn decl_designator(&self) -> WithDecl> { - WithDecl::new(self.parse_ok(parse_designator)) + WithDecl::new(self.parse_ok_no_diagnostics(parse_designator)) } pub fn ref_designator(&self) -> WithPos> { - self.parse_ok(parse_designator).map_into(WithRef::new) + self.parse_ok_no_diagnostics(parse_designator) + .map_into(WithRef::new) } pub fn character(&self) -> WithPos { - self.parse_ok(|stream: &TokenStream| { - let id = stream.expect_kind(Kind::Character)?; - stream.get_token(id).to_character_value() + self.parse_ok_no_diagnostics(|ctx: &mut ParsingContext| { + let id = ctx.stream.expect_kind(Kind::Character)?; + ctx.stream.get_token(id).to_character_value() }) } - /// Helper method to create expression from first occurence of substr + /// Helper method to create expression from first occurrence of substr /// Can be used to test all but expression parsing pub fn expr(&self) -> WithPos { - self.parse_ok(parse_expression) + self.parse_ok_no_diagnostics(parse_expression) } pub fn name(&self) -> WithPos { - self.parse_ok(parse_name) + self.parse_ok_no_diagnostics(parse_name) } pub fn name_list(&self) -> SeparatedList> { @@ -514,11 +524,11 @@ impl Code { } pub fn type_mark(&self) -> WithPos { - self.parse_ok(parse_type_mark) + self.parse_ok_no_diagnostics(parse_type_mark) } pub fn signature(&self) -> WithPos { - self.parse_ok(parse_signature) + self.parse_ok_no_diagnostics(parse_signature) } /// Return symbol from symbol table @@ -531,15 +541,17 @@ impl Code { } pub fn object_decl(&self) -> ObjectDeclaration { - self.parse_ok(parse_object_declaration).remove(0) + self.parse_ok_no_diagnostics(parse_object_declaration) + .remove(0) } pub fn file_decl(&self) -> FileDeclaration { - self.parse_ok(parse_file_declaration).remove(0) + self.parse_ok_no_diagnostics(parse_file_declaration) + .remove(0) } pub fn alias_decl(&self) -> AliasDeclaration { - self.parse_ok(parse_alias_declaration) + self.parse_ok_no_diagnostics(parse_alias_declaration) } pub fn component_decl(&self) -> ComponentDeclaration { @@ -551,19 +563,19 @@ impl Code { } pub fn subtype_indication(&self) -> SubtypeIndication { - self.parse_ok(parse_subtype_indication) + self.parse_ok_no_diagnostics(parse_subtype_indication) } pub fn port(&self) -> InterfaceDeclaration { - self.parse_ok(parse_port) + self.parse_ok_no_diagnostics(parse_port) } pub fn generic(&self) -> InterfaceDeclaration { - self.parse_ok(parse_generic) + self.parse_ok_no_diagnostics(parse_generic) } pub fn parameter(&self) -> InterfaceDeclaration { - self.parse_ok(parse_parameter) + self.parse_ok_no_diagnostics(parse_parameter) } pub fn function_call(&self) -> WithPos { @@ -585,11 +597,10 @@ impl Code { pub fn parse_ok_no_diagnostics(&self, parse_fun: F) -> R where - F: FnOnce(&TokenStream, &mut dyn DiagnosticHandler) -> ParseResult, + F: FnOnce(&mut ParsingContext<'_>) -> ParseResult, { - let mut diagnostics = Vec::new(); - let res = self.parse_ok(|stream| parse_fun(stream, &mut diagnostics)); - check_no_diagnostics(&diagnostics); + let (res, diag) = self.parse_ok(|ctx| parse_fun(ctx)); + check_no_diagnostics(&diag); res } @@ -606,37 +617,33 @@ impl Code { } pub fn port_map_aspect(&self) -> MapAspect { - self.parse_ok_no_diagnostics(|stream, diagnsotics| { - parse_map_aspect(stream, Kind::Port, diagnsotics) - }) - .expect("Expecting port map aspect") + self.parse_ok_no_diagnostics(|ctx| parse_map_aspect(ctx, Kind::Port)) + .expect("Expecting port map aspect") } pub fn generic_map_aspect(&self) -> MapAspect { - self.parse_ok_no_diagnostics(|stream, diagnostics| { - parse_map_aspect(stream, Kind::Generic, diagnostics) - }) - .expect("Expecting generic map aspect") + self.parse_ok_no_diagnostics(|ctx| parse_map_aspect(ctx, Kind::Generic)) + .expect("Expecting generic map aspect") } pub fn waveform(&self) -> Waveform { - self.parse_ok(parse_waveform) + self.parse_ok_no_diagnostics(parse_waveform) } pub fn aggregate(&self) -> WithPos> { - self.parse_ok(parse_aggregate) + self.parse_ok_no_diagnostics(parse_aggregate) } pub fn range(&self) -> ast::Range { - self.parse_ok(parse_range).item + self.parse_ok_no_diagnostics(parse_range).item } pub fn discrete_range(&self) -> DiscreteRange { - self.parse_ok(parse_discrete_range) + self.parse_ok_no_diagnostics(parse_discrete_range) } pub fn choices(&self) -> Vec> { - self.parse_ok(parse_choices) + self.parse_ok_no_diagnostics(parse_choices) } pub fn use_clause(&self) -> UseClause { @@ -683,14 +690,14 @@ impl Code { } pub fn attribute_name(&self) -> AttributeName { - match self.parse_ok(parse_name).item { + match self.parse_ok_no_diagnostics(parse_name).item { Name::Attribute(attr) => *attr, name => panic!("Expected attribute got {name:?}"), } } pub fn association_element(&self) -> AssociationElement { - self.parse_ok(parse_association_element) + self.parse_ok_no_diagnostics(parse_association_element) } } diff --git a/vhdl_lang/src/syntax/tokens/tokenstream.rs b/vhdl_lang/src/syntax/tokens/tokenstream.rs index b122576e..c2217fb6 100644 --- a/vhdl_lang/src/syntax/tokens/tokenstream.rs +++ b/vhdl_lang/src/syntax/tokens/tokenstream.rs @@ -5,6 +5,7 @@ // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com use std::cell::Cell; +use vhdl_lang::syntax::parser::ParsingContext; use super::tokenizer::Kind::*; use super::tokenizer::*; @@ -302,12 +303,7 @@ impl<'a> TokenAccess for TokenStream<'a> { } pub trait Recover { - fn or_recover_until( - self, - stream: &TokenStream, - msgs: &mut dyn DiagnosticHandler, - cond: F, - ) -> DiagnosticResult + fn or_recover_until(self, ctx: &mut ParsingContext<'_>, cond: F) -> DiagnosticResult where F: Fn(Kind) -> bool; @@ -315,23 +311,18 @@ pub trait Recover { } impl Recover for DiagnosticResult { - fn or_recover_until( - self, - stream: &TokenStream, - msgs: &mut dyn DiagnosticHandler, - cond: F, - ) -> DiagnosticResult + fn or_recover_until(self, ctx: &mut ParsingContext<'_>, cond: F) -> DiagnosticResult where F: Fn(Kind) -> bool, { match self { Ok(res) => Ok(res), Err(ref original_err) => { - let res = stream.skip_until(cond); + let res = ctx.stream.skip_until(cond); match res { Ok(_) => self, Err(err) => { - msgs.push(original_err.clone()); + ctx.diagnostics.push(original_err.clone()); Err(err) } } diff --git a/vhdl_lang/src/syntax/type_declaration.rs b/vhdl_lang/src/syntax/type_declaration.rs index be713407..79b178ae 100644 --- a/vhdl_lang/src/syntax/type_declaration.rs +++ b/vhdl_lang/src/syntax/type_declaration.rs @@ -11,18 +11,18 @@ 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::*, TokenSpan, TokenStream}; +use super::tokens::{Kind::*, TokenSpan}; use crate::ast::*; use crate::ast::{AbstractLiteral, Range}; -use crate::data::DiagnosticHandler; use crate::named_entity::Reference; use crate::syntax::names::parse_type_mark; +use vhdl_lang::syntax::parser::ParsingContext; /// LRM 5.2.2 Enumeration types -fn parse_enumeration_type_definition(stream: &TokenStream) -> ParseResult { +fn parse_enumeration_type_definition(ctx: &mut ParsingContext<'_>) -> ParseResult { let mut enum_literals = Vec::new(); loop { - expect_token!(stream, + expect_token!(ctx.stream, literal_token, Identifier | Character => { let enum_literal = match literal_token.kind { @@ -32,7 +32,7 @@ fn parse_enumeration_type_definition(stream: &TokenStream) -> ParseResult { break; }, Comma => {} ); @@ -43,13 +43,13 @@ fn parse_enumeration_type_definition(stream: &TokenStream) -> ParseResult ParseResult> { - stream.expect_kind(LeftPar)?; +fn parse_array_index_constraints(ctx: &mut ParsingContext<'_>) -> ParseResult> { + ctx.stream.expect_kind(LeftPar)?; let mut indexes = Vec::new(); loop { - indexes.push(parse_array_index_constraint(stream)?); + indexes.push(parse_array_index_constraint(ctx)?); - expect_token!(stream, token, + expect_token!(ctx.stream, token, RightPar => { return Ok(indexes); }, @@ -59,45 +59,45 @@ fn parse_array_index_constraints(stream: &TokenStream) -> ParseResult ParseResult { - let index_constraints = parse_array_index_constraints(stream)?; - stream.expect_kind(Of)?; - let element_subtype = parse_subtype_indication(stream)?; +fn parse_array_type_definition(ctx: &mut ParsingContext<'_>) -> ParseResult { + let index_constraints = parse_array_index_constraints(ctx)?; + ctx.stream.expect_kind(Of)?; + let element_subtype = parse_subtype_indication(ctx)?; Ok(TypeDefinition::Array(index_constraints, element_subtype)) } /// LRM 5.3.3 Record types fn parse_record_type_definition( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, ) -> ParseResult<(TypeDefinition, Option)> { let mut elem_decls = Vec::new(); loop { - if stream.skip_if_kind(End) { - stream.pop_if_kind(Record); - let end_ident = stream.pop_optional_ident(); + if ctx.stream.skip_if_kind(End) { + ctx.stream.pop_if_kind(Record); + let end_ident = ctx.stream.pop_optional_ident(); return Ok((TypeDefinition::Record(elem_decls), end_ident)); }; - let idents = parse_identifier_list(stream)?; - stream.expect_kind(Colon)?; - let subtype = parse_subtype_indication(stream)?; + let idents = parse_identifier_list(ctx)?; + ctx.stream.expect_kind(Colon)?; + let subtype = parse_subtype_indication(ctx)?; for ident in idents { elem_decls.push(ElementDeclaration { ident: ident.into(), subtype: subtype.clone(), }); } - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; } } -pub fn parse_subtype_declaration(stream: &TokenStream) -> ParseResult { - let start_token = stream.expect_kind(Subtype)?; - let ident = stream.expect_ident()?; - stream.expect_kind(Is)?; - let subtype_indication = parse_subtype_indication(stream)?; - let end_token = stream.expect_kind(SemiColon)?; +pub fn parse_subtype_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.expect_kind(Subtype)?; + let ident = ctx.stream.expect_ident()?; + ctx.stream.expect_kind(Is)?; + let subtype_indication = parse_subtype_indication(ctx)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(TypeDeclaration { span: TokenSpan::new(start_token, end_token), ident: ident.into(), @@ -108,56 +108,55 @@ pub fn parse_subtype_declaration(stream: &TokenStream) -> ParseResult, ) -> ParseResult<(ProtectedTypeDeclaration, Option)> { let mut items = Vec::new(); loop { - let token = stream.peek_expect()?; + let token = ctx.stream.peek_expect()?; try_init_token_kind!( token, Impure | Function | Procedure => items.push(ProtectedTypeDeclarativeItem::Subprogram( - parse_subprogram_declaration(stream, diagnostics)?, + parse_subprogram_declaration(ctx)?, )), End => { - stream.skip(); + ctx.stream.skip(); break; } ); } - stream.expect_kind(Protected)?; - let end_ident = stream.pop_optional_ident(); + ctx.stream.expect_kind(Protected)?; + let end_ident = ctx.stream.pop_optional_ident(); Ok((ProtectedTypeDeclaration { items }, end_ident)) } /// LRM 5.2.4 Physical types fn parse_physical_type_definition( - stream: &TokenStream, + ctx: &mut ParsingContext<'_>, range: Range, ) -> ParseResult<(TypeDefinition, Option)> { - let primary_unit = WithDecl::new(stream.expect_ident()?); - stream.expect_kind(SemiColon)?; + let primary_unit = WithDecl::new(ctx.stream.expect_ident()?); + ctx.stream.expect_kind(SemiColon)?; let mut secondary_units = Vec::new(); loop { peek_token!( - stream, token, + ctx.stream, token, End => { break; }, Identifier => { - stream.skip(); + ctx.stream.skip(); let ident = WithDecl::new(token.to_identifier_value()?); - stream.expect_kind(EQ)?; + ctx.stream.expect_kind(EQ)?; let literal = { - expect_token!(stream, + expect_token!(ctx.stream, value_token, AbstractLiteral => { let value = value_token.to_abstract_literal()?.item; - let unit = stream.expect_ident()?; + let unit = ctx.stream.expect_ident()?; PhysicalLiteral {value, unit: unit.into_ref()} }, Identifier => { @@ -168,14 +167,14 @@ fn parse_physical_type_definition( }; secondary_units.push((ident, literal)); - stream.expect_kind(SemiColon)?; + ctx.stream.expect_kind(SemiColon)?; } ) } - stream.expect_kind(End)?; - stream.expect_kind(Units)?; - let end_ident = stream.pop_optional_ident(); + ctx.stream.expect_kind(End)?; + ctx.stream.expect_kind(Units)?; + let end_ident = ctx.stream.pop_optional_ident(); Ok(( TypeDefinition::Physical(PhysicalTypeDeclaration { @@ -188,30 +187,27 @@ fn parse_physical_type_definition( } /// LRM 6.2 -pub fn parse_type_declaration( - stream: &TokenStream, - diagnostics: &mut dyn DiagnosticHandler, -) -> ParseResult { - let start_token = stream.get_current_token_id(); +pub fn parse_type_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult { + let start_token = ctx.stream.get_current_token_id(); peek_token!( - stream, token, + ctx.stream, token, Subtype => { - return parse_subtype_declaration(stream); + return parse_subtype_declaration(ctx); }, Type => { - stream.skip(); + ctx.stream.skip(); } ); - let ident = WithDecl::new(stream.expect_ident()?); + let ident = WithDecl::new(ctx.stream.expect_ident()?); let mut end_ident_pos = None; expect_token!( - stream, token, + ctx.stream, token, Is => {}, SemiColon => { return Ok(TypeDeclaration { - span: TokenSpan::new(start_token, stream.get_last_token_id()), + span: TokenSpan::new(start_token, ctx.stream.get_last_token_id()), ident, def: TypeDefinition::Incomplete(Reference::undefined()), end_ident_pos @@ -220,61 +216,61 @@ pub fn parse_type_declaration( ); let def = expect_token!( - stream, token, + ctx.stream, token, // Integer Range => { - let constraint = parse_range(stream)?.item; + let constraint = parse_range(ctx)?.item; expect_token!( - stream, token, + ctx.stream, token, SemiColon => { - stream.back(); // The ';' is consumed at the end of the function + ctx.stream.back(); // The ';' is consumed at the end of the function TypeDefinition::Numeric(constraint) }, Units => { - let (def, end_ident) = parse_physical_type_definition(stream, constraint)?; - end_ident_pos = check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics); + let (def, end_ident) = parse_physical_type_definition(ctx, constraint)?; + end_ident_pos = check_end_identifier_mismatch(ctx, &ident.tree, end_ident); def } ) }, Access => { - let subtype_indication = parse_subtype_indication(stream)?; + let subtype_indication = parse_subtype_indication(ctx)?; TypeDefinition::Access(subtype_indication) }, Protected => { - if stream.skip_if_kind(Body) { - let decl = parse_declarative_part(stream, diagnostics)?; - stream.expect_kind(End)?; - stream.expect_kind(Protected)?; - stream.expect_kind(Body)?; - let end_ident = stream.pop_optional_ident(); - end_ident_pos = check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics); + if ctx.stream.skip_if_kind(Body) { + let decl = parse_declarative_part(ctx)?; + ctx.stream.expect_kind(End)?; + ctx.stream.expect_kind(Protected)?; + ctx.stream.expect_kind(Body)?; + let end_ident = ctx.stream.pop_optional_ident(); + end_ident_pos = check_end_identifier_mismatch(ctx, &ident.tree, end_ident); TypeDefinition::ProtectedBody(ProtectedTypeBody {decl}) } else { - let (protected_type_decl, end_ident) = parse_protected_type_declaration(stream, diagnostics)?; - end_ident_pos = check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics); + let (protected_type_decl, end_ident) = parse_protected_type_declaration(ctx)?; + end_ident_pos = check_end_identifier_mismatch(ctx, &ident.tree, end_ident); TypeDefinition::Protected(protected_type_decl) } }, File => { - stream.expect_kind(Of)?; - let type_mark = parse_type_mark(stream)?; + ctx.stream.expect_kind(Of)?; + let type_mark = parse_type_mark(ctx)?; TypeDefinition::File(type_mark) }, - Array => parse_array_type_definition(stream)?, + Array => parse_array_type_definition(ctx)?, Record => { - let (def, end_ident) = parse_record_type_definition(stream)?; - end_ident_pos = check_end_identifier_mismatch(&ident.tree, end_ident, diagnostics); + let (def, end_ident) = parse_record_type_definition(ctx)?; + end_ident_pos = check_end_identifier_mismatch(ctx, &ident.tree, end_ident); def }, // Enumeration - LeftPar => parse_enumeration_type_definition(stream)? + LeftPar => parse_enumeration_type_definition(ctx)? ); - let end_token = stream.expect_kind(SemiColon)?; + let end_token = ctx.stream.expect_kind(SemiColon)?; Ok(TypeDeclaration { span: TokenSpan::new(start_token, end_token), ident, diff --git a/vhdl_lang/src/syntax/waveform.rs b/vhdl_lang/src/syntax/waveform.rs index 4e059ab5..e85ccc89 100644 --- a/vhdl_lang/src/syntax/waveform.rs +++ b/vhdl_lang/src/syntax/waveform.rs @@ -5,27 +5,28 @@ // Copyright (c) 2018, Olof Kraigher olof.kraigher@gmail.com use crate::ast::{DelayMechanism, Waveform, WaveformElement}; +use crate::syntax::parser::ParsingContext; use super::common::{parse_optional, ParseResult}; use super::expression::parse_expression; -use super::tokens::{Kind::*, TokenStream}; +use super::tokens::Kind::*; /// LRM 10.5 Signal assignment statement -pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult> { - let token = stream.peek_expect()?; +pub fn parse_delay_mechanism(ctx: &mut ParsingContext<'_>) -> ParseResult> { + let token = ctx.stream.peek_expect()?; match token.kind { Transport => { - stream.skip(); + ctx.stream.skip(); Ok(Some(DelayMechanism::Transport)) } Inertial => { - stream.skip(); + ctx.stream.skip(); Ok(Some(DelayMechanism::Inertial { reject: None })) } Reject => { - stream.skip(); - let reject = Some(parse_expression(stream)?); - stream.expect_kind(Inertial)?; + ctx.stream.skip(); + let reject = Some(parse_expression(ctx)?); + ctx.stream.expect_kind(Inertial)?; Ok(Some(DelayMechanism::Inertial { reject })) } _ => Ok(None), @@ -33,20 +34,20 @@ pub fn parse_delay_mechanism(stream: &TokenStream) -> ParseResult ParseResult { - if stream.skip_if_kind(Unaffected) { +pub fn parse_waveform(ctx: &mut ParsingContext<'_>) -> ParseResult { + if ctx.stream.skip_if_kind(Unaffected) { return Ok(Waveform::Unaffected); } let mut elems = Vec::new(); loop { - let value = parse_expression(stream)?; - let after = parse_optional(stream, After, parse_expression)?; + let value = parse_expression(ctx)?; + let after = parse_optional(ctx, After, parse_expression)?; elems.push(WaveformElement { value, after }); - if !stream.skip_if_kind(Comma) { + if !ctx.stream.skip_if_kind(Comma) { break; } }