Skip to content

Commit

Permalink
Attribute parsers
Browse files Browse the repository at this point in the history
  • Loading branch information
vaivaswatha committed Oct 23, 2023
1 parent c4ee705 commit dbae825
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 65 deletions.
95 changes: 90 additions & 5 deletions src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@
//!
//! [AttrObj]s can be downcasted to their concrete types using
/// [downcast_rs](https://docs.rs/downcast-rs/1.2.0/downcast_rs/index.html#example-without-generics).
use std::{hash::Hash, ops::Deref};
use std::{fmt::Display, hash::Hash, ops::Deref};

use combine::{easy, parser, ParseResult, Parser, Positioned};
use downcast_rs::{impl_downcast, Downcast};
use intertrait::{cast::CastRef, CastFrom};

Expand All @@ -34,6 +35,8 @@ use crate::{
context::Context,
dialect::{Dialect, DialectName},
error::Result,
input_err,
parsable::{identifier, spaced, to_parse_result, Parsable, ParserFn, StateStream},
printable::{self, Printable},
};

Expand All @@ -59,11 +62,11 @@ pub trait Attribute: Printable + Verify + Downcast + CastFrom + Sync {
/// Register this attribute's [AttrId] in the dialect it belongs to.
/// **Warning**: No check is made as to whether this attr is already registered
/// in `dialect`.
fn register_attr_in_dialect(dialect: &mut Dialect)
fn register_attr_in_dialect(dialect: &mut Dialect, attr_parser: ParserFn<AttrObj>)
where
Self: Sized,
{
dialect.add_attr(Self::get_attr_id_static());
dialect.add_attr(Self::get_attr_id_static(), attr_parser);
}
}
impl_downcast!(Attribute);
Expand Down Expand Up @@ -133,10 +136,31 @@ impl Printable for AttrName {
_state: &printable::State,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
<Self as Display>::fmt(self, f)
}
}

impl Display for AttrName {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}

impl Parsable for AttrName {
type Parsed = AttrName;

fn parse<'a>(
state_stream: &mut crate::parsable::StateStream<'a>,
) -> combine::ParseResult<Self::Parsed, combine::easy::ParseError<StateStream<'a>>>
where
Self: Sized,
{
identifier()
.map(|name| AttrName::new(&name))
.parse_stream(&mut state_stream.stream)
}
}

impl Deref for AttrName {
type Target = String;

Expand All @@ -154,14 +178,75 @@ pub struct AttrId {
impl Printable for AttrId {
fn fmt(
&self,
ctx: &Context,
_ctx: &Context,
_state: &printable::State,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
write!(f, "{}.{}", self.dialect.disp(ctx), self.name.disp(ctx))
<Self as Display>::fmt(self, f)
}
}

impl Display for AttrId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}", self.dialect, self.name)
}
}

impl Parsable for AttrId {
type Parsed = AttrId;

// Parses (but does not validate) a TypeId.
fn parse<'a>(
state_stream: &mut StateStream<'a>,
) -> ParseResult<Self::Parsed, easy::ParseError<StateStream<'a>>>
where
Self: Sized,
{
let parser = DialectName::parser()
.skip(parser::char::char('.'))
.and(AttrName::parser())
.map(|(dialect, name)| AttrId { dialect, name });
spaced(parser).parse_stream(state_stream)
}
}

/// Parse an identified attribute, which is [AttrId] followed by its contents.
pub fn attr_parse<'a>(
state_stream: &mut StateStream<'a>,
) -> ParseResult<AttrObj, easy::ParseError<StateStream<'a>>> {
let position = state_stream.stream.position();
let attr_id_parser = AttrId::parser();

let attr_parser = attr_id_parser.then(|attr_id: AttrId| {
combine::parser(move |parsable_state: &mut StateStream<'a>| {
let state = &parsable_state.state;
let dialect = state
.ctx
.dialects
.get(&attr_id.dialect)
.expect("Dialect name parsed but dialect isn't registered");
let Some(attr_parser) = dialect.attributes.get(&attr_id) else {
return to_parse_result(
input_err!("Unregistered attribute {}", attr_id.disp(state.ctx)),
position,
)
.into_result();
};
attr_parser(&()).parse_stream(parsable_state).into_result()
})
});

let mut attr_parser = spaced(attr_parser);
attr_parser.parse_stream(state_stream)
}

/// A parser combinator to parse [AttrId] followed by the attribute's contents.
pub fn attr_parser<'a>(
) -> Box<dyn Parser<StateStream<'a>, Output = AttrObj, PartialState = ()> + 'a> {
combine::parser(|parsable_state: &mut StateStream<'a>| attr_parse(parsable_state).into_result())
.boxed()
}

/// Every attribute interface must have a function named `verify` with this type.
pub type AttrInterfaceVerifier = fn(&dyn Attribute, &Context) -> Result<()>;

Expand Down
20 changes: 10 additions & 10 deletions src/dialect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ use combine::{easy, ParseResult, Parser};
use rustc_hash::FxHashMap;

use crate::{
attribute::AttrId,
attribute::{AttrId, AttrObj},
context::{Context, Ptr},
op::OpId,
op::{OpId, OpObj},
parsable::{self, Parsable, ParserFn, StateStream},
printable::{self, Printable},
r#type::{TypeId, TypeObj},
Expand Down Expand Up @@ -80,11 +80,11 @@ pub struct Dialect {
/// Name of this dialect.
pub name: DialectName,
/// Ops that are part of this dialect.
pub ops: Vec<OpId>,
pub ops: FxHashMap<OpId, ParserFn<OpObj>>,
/// Types that are part of this dialect.
pub types: FxHashMap<TypeId, ParserFn<Ptr<TypeObj>>>,
/// Attributes that are part of this dialect.
pub attributes: Vec<AttrId>,
pub attributes: FxHashMap<AttrId, ParserFn<AttrObj>>,
}

impl Printable for Dialect {
Expand All @@ -103,9 +103,9 @@ impl Dialect {
pub fn new(name: DialectName) -> Dialect {
Dialect {
name,
ops: vec![],
ops: FxHashMap::default(),
types: FxHashMap::default(),
attributes: vec![],
attributes: FxHashMap::default(),
}
}

Expand All @@ -115,9 +115,9 @@ impl Dialect {
}

/// Add an [Op](crate::op::Op) to this dialect.
pub fn add_op(&mut self, op: OpId) {
pub fn add_op(&mut self, op: OpId, op_parser: ParserFn<OpObj>) {
assert!(op.dialect == self.name);
self.ops.push(op);
self.ops.insert(op, op_parser);
}

/// Add a [Type](crate::type::Type) to this dialect.
Expand All @@ -127,9 +127,9 @@ impl Dialect {
}

/// Add an [Attribute](crate::attribute::Attribute) to this dialect.
pub fn add_attr(&mut self, attr: AttrId) {
pub fn add_attr(&mut self, attr: AttrId, attr_parser: ParserFn<AttrObj>) {
assert!(attr.dialect == self.name);
self.attributes.push(attr);
self.attributes.insert(attr, attr_parser);
}

/// This Dialect's name.
Expand Down
Loading

0 comments on commit dbae825

Please sign in to comment.