Skip to content

Commit

Permalink
Add parsing context (#286)
Browse files Browse the repository at this point in the history
  • Loading branch information
Schottkyc137 authored Apr 13, 2024
1 parent 1233700 commit 6a892af
Show file tree
Hide file tree
Showing 23 changed files with 1,405 additions and 1,479 deletions.
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 [email protected]

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 [email protected]

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

0 comments on commit 6a892af

Please sign in to comment.