Skip to content

Commit d191ddc

Browse files
Merge pull request #2 from fibonacci1729/include
Add include grammar
2 parents 16d7fe8 + a3c1e1a commit d191ddc

4 files changed

Lines changed: 181 additions & 5 deletions

File tree

crates/wac-parser/src/ast/keywords.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,6 @@ keywords!(
7171
(New, Rule::NewKeyword, "new"),
7272
(Let, Rule::LetKeyword, "let"),
7373
(Use, Rule::UseKeyword, "use"),
74+
(Include, Rule::IncludeKeyword, "include"),
75+
(As, Rule::AsKeyword, "as"),
7476
);

crates/wac-parser/src/ast/type.rs

Lines changed: 161 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::{
22
display,
33
keywords::{
4-
self, Bool, Enum, Export, Flags, Float32, Float64, Func, Import, Interface, Record,
5-
Resource, Static, Use, Variant, World, S16, S32, S64, S8, U16, U32, U64, U8,
4+
self, As, Bool, Enum, Export, Flags, Float32, Float64, Func, Import, Include, Interface,
5+
Record, Resource, Static, Use, Variant, With, World, S16, S32, S64, S8, U16, U32, U64, U8,
66
},
77
symbols::{
88
Arrow, CloseAngle, CloseBrace, CloseParen, Colon, Dot, Equals, OpenAngle, OpenBrace,
@@ -1247,6 +1247,8 @@ pub enum WorldItemKind<'a> {
12471247
Import(WorldImportStatement<'a>),
12481248
/// The item is a world export statement.
12491249
Export(WorldExportStatement<'a>),
1250+
/// The item is a world include statement.
1251+
Include(WorldIncludeStatement<'a>),
12501252
}
12511253

12521254
impl AstDisplay for WorldItemKind<'_> {
@@ -1256,6 +1258,7 @@ impl AstDisplay for WorldItemKind<'_> {
12561258
Self::Type(ty) => ty.fmt(f, indenter),
12571259
Self::Import(i) => i.fmt(f, indenter),
12581260
Self::Export(e) => e.fmt(f, indenter),
1261+
Self::Include(i) => i.fmt(f, indenter),
12591262
}
12601263
}
12611264
}
@@ -1412,6 +1415,108 @@ impl AstDisplay for InlineInterface<'_> {
14121415
}
14131416

14141417
display!(InlineInterface);
1418+
1419+
/// Represents a world include statement in the AST.
1420+
#[derive(Debug, Clone, FromPest)]
1421+
#[pest_ast(rule(Rule::WorldIncludeStatement))]
1422+
pub struct WorldIncludeStatement<'a> {
1423+
/// The `include` keyword in the statement.
1424+
pub keyword: Include<'a>,
1425+
/// The reference to the world to include.
1426+
pub world: WorldRef<'a>,
1427+
/// The optional include-with clause.
1428+
pub with: std::option::Option<WorldIncludeWithClause<'a>>,
1429+
/// The semicolon of the include statement.
1430+
pub semicolon: Semicolon<'a>,
1431+
}
1432+
1433+
impl AstDisplay for WorldIncludeStatement<'_> {
1434+
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
1435+
write!(f, "{indenter}{keyword} ", keyword = self.keyword)?;
1436+
self.world.fmt(f, indenter)?;
1437+
if let Some(with) = &self.with {
1438+
with.fmt(f, indenter)?;
1439+
}
1440+
write!(f, "{semi}", semi = self.semicolon)
1441+
}
1442+
}
1443+
1444+
display!(WorldIncludeStatement);
1445+
1446+
/// Represents a reference to a world in the AST (local or foreign).
1447+
#[derive(Debug, Clone, FromPest)]
1448+
#[pest_ast(rule(Rule::WorldRef))]
1449+
pub enum WorldRef<'a> {
1450+
/// The reference is by identifier.
1451+
Ident(Ident<'a>),
1452+
/// The reference is by package path.
1453+
Path(PackagePath<'a>),
1454+
}
1455+
1456+
impl AstDisplay for WorldRef<'_> {
1457+
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
1458+
match self {
1459+
Self::Ident(id) => id.fmt(f, indenter),
1460+
Self::Path(path) => path.fmt(f, indenter),
1461+
}
1462+
}
1463+
}
1464+
1465+
display!(WorldRef);
1466+
1467+
/// Represents the `with` clause of the `include` statement.
1468+
#[derive(Debug, Clone, FromPest)]
1469+
#[pest_ast(rule(Rule::WorldIncludeWithClause))]
1470+
pub struct WorldIncludeWithClause<'a> {
1471+
/// The `with` keyword in the clause.
1472+
pub keyword: With<'a>,
1473+
/// The opening brace of the body.
1474+
pub open: OpenBrace<'a>,
1475+
/// The list of names to be included.
1476+
pub names: Vec<WorldIncludeItem<'a>>,
1477+
/// The closing brace of the body.
1478+
pub close: CloseBrace<'a>,
1479+
}
1480+
1481+
impl AstDisplay for WorldIncludeWithClause<'_> {
1482+
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
1483+
write!(f, " {keyword} ", keyword = self.keyword)?;
1484+
writeln!(f, "{open}", open = self.open)?;
1485+
indenter.indent();
1486+
for name in &self.names {
1487+
write!(f, "{indenter}")?;
1488+
name.fmt(f, indenter)?;
1489+
writeln!(f, ",")?;
1490+
}
1491+
indenter.dedent();
1492+
write!(f, "{indenter}{close}", close = self.close)
1493+
}
1494+
}
1495+
1496+
display!(WorldIncludeWithClause);
1497+
1498+
/// Represents a renaming of an included name.
1499+
#[derive(Debug, Clone, FromPest)]
1500+
#[pest_ast(rule(Rule::WorldIncludeItem))]
1501+
pub struct WorldIncludeItem<'a> {
1502+
/// The source name include from a world.
1503+
pub name: Ident<'a>,
1504+
/// The `as` keyword.
1505+
pub keyword: As<'a>,
1506+
/// The new name given to the included name.
1507+
pub other: Ident<'a>,
1508+
}
1509+
1510+
impl AstDisplay for WorldIncludeItem<'_> {
1511+
fn fmt(&self, f: &mut fmt::Formatter<'_>, indenter: &mut Indenter) -> fmt::Result {
1512+
self.name.fmt(f, indenter)?;
1513+
write!(f, " {keyword} ", keyword = self.keyword)?;
1514+
self.other.fmt(f, indenter)
1515+
}
1516+
}
1517+
1518+
display!(WorldIncludeItem);
1519+
14151520
#[cfg(test)]
14161521
mod test {
14171522
use super::*;
@@ -1610,6 +1715,30 @@ mod test {
16101715
16111716
/// Export with package path
16121717
export foo:bar/baz@1.0.0;
1718+
1719+
/// Include world from package path with 2 renames.
1720+
include foo:bar/baz with { a as a1, b as b1 };
1721+
1722+
/// Include world from package path with 1 rename.
1723+
include foo:bar/baz with {foo as foo1};
1724+
1725+
/// Include world from package path (spacing).
1726+
include foo:bar/baz with { foo as foo1 };
1727+
1728+
/// Include world from package path newline delimited renaming.
1729+
include foo:bar/baz with {
1730+
foo as foo1,
1731+
bar as bar1
1732+
};
1733+
1734+
/// Include local world.
1735+
include foo-bar;
1736+
1737+
/// Include local world with renaming.
1738+
include foo-bar with { foo as bar };
1739+
};
1740+
1741+
include myworld;
16131742
}
16141743
"#,
16151744
r#"world foo {
@@ -1649,6 +1778,36 @@ mod test {
16491778
16501779
/// Export with package path
16511780
export foo:bar/baz@1.0.0;
1781+
1782+
/// Include world from package path with 2 renames.
1783+
include foo:bar/baz with {
1784+
a as a1,
1785+
b as b1,
1786+
};
1787+
1788+
/// Include world from package path with 1 rename.
1789+
include foo:bar/baz with {
1790+
foo as foo1,
1791+
};
1792+
1793+
/// Include world from package path (spacing).
1794+
include foo:bar/baz with {
1795+
foo as foo1,
1796+
};
1797+
1798+
/// Include world from package path newline delimited renaming.
1799+
include foo:bar/baz with {
1800+
foo as foo1,
1801+
bar as bar1,
1802+
};
1803+
1804+
/// Include local world.
1805+
include foo-bar;
1806+
1807+
/// Include local world with renaming.
1808+
include foo-bar with {
1809+
foo as bar,
1810+
};
16521811
}"#,
16531812
)
16541813
.unwrap();

crates/wac-parser/src/parser.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,11 @@ mod pest {
8888
Self::ExternType => "extern type",
8989
Self::InlineInterface => "inline interface",
9090

91+
Self::WorldIncludeStatement => "world include statement",
92+
Self::WorldIncludeWithClause => "world include with clause",
93+
Self::WorldIncludeItem => "world include item",
94+
Self::WorldRef => "world reference",
95+
9196
Self::Expr => "expression",
9297
Self::PrimaryExpr => "primary expression",
9398
Self::NewExpr => "new expression",
@@ -141,6 +146,8 @@ mod pest {
141146
Self::NewKeyword => "`new` keyword",
142147
Self::LetKeyword => "`let` keyword",
143148
Self::UseKeyword => "`use` keyword",
149+
Self::IncludeKeyword => "`include` keyword",
150+
Self::AsKeyword => "`as` keyword",
144151

145152
Self::Semicolon => "`;`",
146153
Self::OpenBrace => "`{`",

crates/wac-parser/wac.pest

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,10 @@ InterfaceBody = !{ OpenBrace ~ InterfaceItem* ~ CloseBrace }
7272
InterfaceItem = ${ DocComment* ~ WHITESPACE* ~ InterfaceItemKind }
7373
InterfaceItemKind = !{ UseStatement | ValueTypeStatement | InterfaceExportStatement }
7474
InterfaceExportStatement = { Ident ~ Colon ~ FuncTypeRef ~ Semicolon }
75-
// TODO: support world include statements
7675
WorldDecl = ${ WorldKeyword ~ DelimitingSpace+ ~ Ident ~ DelimitingSpace* ~ WorldBody }
7776
WorldBody = !{ OpenBrace ~ WorldItem* ~ CloseBrace }
7877
WorldItem = ${ DocComment* ~ WHITESPACE* ~ WorldItemKind }
79-
WorldItemKind = !{ UseStatement | ValueTypeStatement | WorldImportStatement | WorldExportStatement }
78+
WorldItemKind = !{ UseStatement | ValueTypeStatement | WorldImportStatement | WorldExportStatement | WorldIncludeStatement }
8079
WorldImportStatement = ${ ImportKeyword ~ DelimitingSpace+ ~ WorldItemDecl ~ DelimitingSpace* ~ Semicolon }
8180
WorldExportStatement = ${ ExportKeyword ~ DelimitingSpace+ ~ WorldItemDecl ~ DelimitingSpace* ~ Semicolon }
8281
WorldItemDecl = !{ WorldNamedItem | InterfaceRef }
@@ -85,6 +84,11 @@ InterfaceRef = { PackagePath | Ident }
8584
ExternType = !{ FuncType | InlineInterface | Ident }
8685
InlineInterface = { InterfaceKeyword ~ InterfaceBody }
8786

87+
WorldIncludeStatement = ${ IncludeKeyword ~ DelimitingSpace+ ~ WorldRef ~ DelimitingSpace* ~ WorldIncludeWithClause? ~ DelimitingSpace* ~ Semicolon }
88+
WorldIncludeWithClause = !{ WithKeyword ~ OpenBrace ~ WorldIncludeItem ~ ("," ~ WorldIncludeItem)* ~ ","? ~ CloseBrace }
89+
WorldIncludeItem = ${ Ident ~ DelimitingSpace+ ~ AsKeyword ~ DelimitingSpace+ ~ Ident }
90+
WorldRef = { PackagePath | Ident }
91+
8892
// Let statement
8993
LetStatement = ${ LetKeyword ~ DelimitingSpace+ ~ Ident ~ DelimitingSpace* ~ Equals ~ DelimitingSpace* ~ Expr ~ DelimitingSpace* ~ Semicolon }
9094

@@ -112,7 +116,7 @@ UsePath = { PackagePath | Ident }
112116

113117
// Identifiers
114118
RawIdent = _{ Percent ~ IdentPart ~ (Hyphen ~ IdentPart)* }
115-
Ident = @{ RawIdent | !Keyword ~ IdentPart ~ (Hyphen ~ IdentPart)* }
119+
Ident = @{ RawIdent | !(Keyword ~ !Hyphen) ~ IdentPart ~ (Hyphen ~ IdentPart)* }
116120
IdentPart = @{ ASCII_ALPHA_LOWER ~ (ASCII_ALPHA_LOWER | ASCII_DIGIT)* }
117121

118122
// Strings
@@ -154,6 +158,8 @@ ExportKeyword = { "export" }
154158
NewKeyword = { "new" }
155159
LetKeyword = { "let" }
156160
UseKeyword = { "use" }
161+
IncludeKeyword = { "include" }
162+
AsKeyword = { "as" }
157163
Keyword = _{
158164
ImportKeyword
159165
| WithKeyword
@@ -190,6 +196,8 @@ Keyword = _{
190196
| NewKeyword
191197
| LetKeyword
192198
| UseKeyword
199+
| IncludeKeyword
200+
| AsKeyword
193201
}
194202

195203
// Comments

0 commit comments

Comments
 (0)