Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions vhdl_lang/src/syntax/alias_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<AliasDeclaration> {
let start_token = stream.expect_kind(Alias)?;
let designator = WithDecl::new(parse_designator(stream)?);
pub fn parse_alias_declaration(ctx: &mut ParsingContext<'_>) -> ParseResult<AliasDeclaration> {
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),
Expand Down
43 changes: 22 additions & 21 deletions vhdl_lang/src/syntax/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<EntityClass> {
Ok(expect_token!(stream, token,
fn parse_entity_class(ctx: &mut ParsingContext<'_>) -> ParseResult<EntityClass> {
Ok(expect_token!(ctx.stream, token,
Entity => EntityClass::Entity,
Architecture => EntityClass::Architecture,
Configuration => EntityClass::Configuration,
Expand All @@ -35,8 +36,8 @@ fn parse_entity_class(stream: &TokenStream) -> ParseResult<EntityClass> {
))
}

pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult<Vec<EntityName>> {
Ok(expect_token!(stream, token,
pub fn parse_entity_name_list(ctx: &mut ParsingContext<'_>) -> ParseResult<Vec<EntityName>> {
Ok(expect_token!(ctx.stream, token,
Identifier | StringLiteral => {
let mut entity_name_list = Vec::new();
let mut token = token;
Expand All @@ -49,8 +50,8 @@ pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult<Vec<EntityNam
};

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
}
Expand All @@ -61,8 +62,8 @@ pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult<Vec<EntityNam
signature,
}));

if stream.skip_if_kind(Comma) {
token = expect_token!(stream, token, Identifier | StringLiteral => token);
if ctx.stream.skip_if_kind(Comma) {
token = expect_token!(ctx.stream, token, Identifier | StringLiteral => token);
} else {
break entity_name_list;
}
Expand All @@ -77,26 +78,26 @@ pub fn parse_entity_name_list(stream: &TokenStream) -> ParseResult<Vec<EntityNam
))
}

pub fn parse_attribute(stream: &TokenStream) -> ParseResult<Vec<Attribute>> {
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<Vec<Attribute>> {
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(),
type_mark,
})]
},
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()
Expand Down
22 changes: 11 additions & 11 deletions vhdl_lang/src/syntax/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<F, R>(
stream: &TokenStream,
ctx: &mut ParsingContext<'_>,
keyword: Kind,
parse_fun: F,
) -> ParseResult<Option<R>>
where
F: FnOnce(&TokenStream) -> ParseResult<R>,
F: FnOnce(&mut ParsingContext) -> ParseResult<R>,
{
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
}
Expand All @@ -32,15 +32,15 @@ where
}

pub fn check_end_identifier_mismatch<T: std::fmt::Display + std::cmp::PartialEq>(
ctx: &mut ParsingContext,
ident: &WithPos<T>,
end_ident: Option<WithPos<T>>,
diagnostics: &mut dyn DiagnosticHandler,
) -> Option<SrcPos> {
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),
));
Expand All @@ -50,23 +50,23 @@ pub fn check_end_identifier_mismatch<T: std::fmt::Display + std::cmp::PartialEq>
}

pub fn check_label_identifier_mismatch(
ctx: &mut ParsingContext,
label: Option<&Ident>,
end_ident: Option<Ident>,
diagnostics: &mut dyn DiagnosticHandler,
) -> Option<SrcPos> {
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",
Expand Down
67 changes: 33 additions & 34 deletions vhdl_lang/src/syntax/component_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Option<Vec<InterfaceDeclaration>>> {
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);
}
Expand All @@ -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<Option<Vec<InterfaceDeclaration>>> {
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",
));
Expand All @@ -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<ComponentDeclaration> {
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(),
Expand Down
Loading