Add use statements.
This commit is contained in:
parent
0c18b976d7
commit
938391ae09
3
sketching/may_2025/use.dm
Normal file
3
sketching/may_2025/use.dm
Normal file
@ -0,0 +1,3 @@
|
||||
use std::core::println;
|
||||
use std::core::*;
|
||||
use std::core::{print, println};
|
@ -15,7 +15,11 @@ fn expect_and_use<T>(
|
||||
f(file_id, pair)
|
||||
}
|
||||
|
||||
pub fn build_ast(file_name: &str, file_id: usize, compilation_unit_pair: Pair<Rule>) -> CompilationUnit {
|
||||
pub fn build_ast(
|
||||
file_name: &str,
|
||||
file_id: usize,
|
||||
compilation_unit_pair: Pair<Rule>,
|
||||
) -> CompilationUnit {
|
||||
build_compilation_unit(file_name, file_id, compilation_unit_pair)
|
||||
}
|
||||
|
||||
@ -293,8 +297,13 @@ fn build_references(file_id: usize, ref_list_pair: Pair<Rule>) -> References {
|
||||
)
|
||||
}
|
||||
|
||||
fn build_compilation_unit(file_name: &str, file_id: usize, compilation_unit_pair: Pair<Rule>) -> CompilationUnit {
|
||||
fn build_compilation_unit(
|
||||
file_name: &str,
|
||||
file_id: usize,
|
||||
compilation_unit_pair: Pair<Rule>,
|
||||
) -> CompilationUnit {
|
||||
let mut namespace = None;
|
||||
let mut use_statements = vec![];
|
||||
let mut declarations = vec![];
|
||||
|
||||
for inner_pair in compilation_unit_pair.into_inner() {
|
||||
@ -302,10 +311,13 @@ fn build_compilation_unit(file_name: &str, file_id: usize, compilation_unit_pair
|
||||
Rule::Namespace => {
|
||||
namespace = Some(build_namespace(file_id, inner_pair));
|
||||
}
|
||||
Rule::UseStatement => {
|
||||
use_statements.push(build_use_statement(file_id, inner_pair));
|
||||
}
|
||||
Rule::ModuleLevelDeclaration => {
|
||||
declarations.push(build_module_level_declaration(file_id, inner_pair));
|
||||
}
|
||||
Rule::EOI => {}
|
||||
Rule::Semicolon | Rule::EOI => {}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
@ -314,6 +326,7 @@ fn build_compilation_unit(file_name: &str, file_id: usize, compilation_unit_pair
|
||||
file_name: file_name.to_string(),
|
||||
file_id,
|
||||
namespace,
|
||||
use_statements,
|
||||
declarations,
|
||||
}
|
||||
}
|
||||
@ -741,6 +754,53 @@ fn build_field_declaration(file_id: usize, field_pair: Pair<Rule>) -> FieldDecla
|
||||
}
|
||||
}
|
||||
|
||||
fn build_use_statement(file_id: usize, use_statement_pair: Pair<Rule>) -> UseStatement {
|
||||
let mut inner = use_statement_pair.into_inner();
|
||||
let inner_length = inner.len();
|
||||
|
||||
inner.next().unwrap(); // use
|
||||
|
||||
let mut identifiers = vec![];
|
||||
let mut last = None;
|
||||
|
||||
for (i, inner_pair) in inner.into_iter().enumerate() {
|
||||
if i != inner_length - 2 {
|
||||
identifiers.push(expect_and_use(
|
||||
file_id,
|
||||
inner_pair,
|
||||
Rule::Identifier,
|
||||
build_identifier,
|
||||
))
|
||||
} else {
|
||||
last = Some(match inner_pair.as_rule() {
|
||||
Rule::Identifier => {
|
||||
UseStatementLast::Identifier(build_identifier(file_id, inner_pair))
|
||||
}
|
||||
Rule::Star => UseStatementLast::Star,
|
||||
Rule::UseList => UseStatementLast::Identifiers(
|
||||
inner_pair
|
||||
.into_inner()
|
||||
.map(|identifier_pair| {
|
||||
expect_and_use(
|
||||
file_id,
|
||||
identifier_pair,
|
||||
Rule::Identifier,
|
||||
build_identifier,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
UseStatement {
|
||||
identifiers,
|
||||
last: last.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_block_statement(file_id: usize, block_statement_pair: Pair<Rule>) -> BlockStatement {
|
||||
let mut statements = vec![];
|
||||
let mut expression = None;
|
||||
@ -1723,4 +1783,19 @@ mod tests {
|
||||
}
|
||||
"})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_statement() {
|
||||
assert_builds("use std::core::println;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_star() {
|
||||
assert_builds("use std::core::*;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_list() {
|
||||
assert_builds("use std::core::{print, println};");
|
||||
}
|
||||
}
|
||||
|
@ -290,6 +290,7 @@ pub struct CompilationUnit {
|
||||
pub file_name: String,
|
||||
pub file_id: usize,
|
||||
pub namespace: Option<FullyQualifiedName>,
|
||||
pub use_statements: Vec<UseStatement>,
|
||||
pub declarations: Vec<ModuleLevelDeclaration>,
|
||||
}
|
||||
|
||||
@ -450,6 +451,19 @@ pub struct FieldDeclaration {
|
||||
|
||||
// Statements
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UseStatement {
|
||||
pub identifiers: Vec<Identifier>,
|
||||
pub last: UseStatementLast
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum UseStatementLast {
|
||||
Identifier(Identifier),
|
||||
Identifiers(Vec<Identifier>),
|
||||
Star,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BlockStatement {
|
||||
pub statements: Vec<Statement>,
|
||||
|
@ -282,6 +282,9 @@ impl PrettyPrint for CompilationUnit {
|
||||
namespace.pretty_print(writer)?;
|
||||
writer.decrease_indent();
|
||||
}
|
||||
for use_statement in &self.use_statements {
|
||||
use_statement.pretty_print(writer)?;
|
||||
}
|
||||
for declaration in &self.declarations {
|
||||
declaration.pretty_print(writer)?;
|
||||
}
|
||||
@ -585,6 +588,39 @@ impl PrettyPrint for FieldDeclaration {
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for UseStatement {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.writeln_indented("UseStatement")?;
|
||||
writer.increase_indent();
|
||||
for identifier in &self.identifiers {
|
||||
identifier.pretty_print(writer)?;
|
||||
}
|
||||
self.last.pretty_print(writer)?;
|
||||
writer.decrease_indent();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for UseStatementLast {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.writeln_indented("UseStatementLast")?;
|
||||
writer.increase_indent();
|
||||
match self {
|
||||
UseStatementLast::Identifier(i) => i.pretty_print(writer)?,
|
||||
UseStatementLast::Identifiers(is) => {
|
||||
for i in is {
|
||||
i.pretty_print(writer)?;
|
||||
}
|
||||
},
|
||||
UseStatementLast::Star => {
|
||||
writer.writeln_indented("Star")?;
|
||||
}
|
||||
}
|
||||
writer.decrease_indent();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl PrettyPrint for BlockStatement {
|
||||
fn pretty_print(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.writeln_indented("BlockStatement")?;
|
||||
|
@ -373,7 +373,11 @@ impl Unparse for CompilationUnit {
|
||||
if let Some(namespace) = &self.namespace {
|
||||
writer.write("ns ")?;
|
||||
namespace.unparse(writer)?;
|
||||
writer.write("\n\n")?;
|
||||
writer.write(";\n\n")?;
|
||||
}
|
||||
for use_statement in &self.use_statements {
|
||||
use_statement.unparse(writer)?;
|
||||
writer.write(";\n")?;
|
||||
}
|
||||
unparse_list(writer, "\n\n", &to_unparse_vec!(self.declarations))?;
|
||||
Ok(())
|
||||
@ -722,6 +726,41 @@ impl Unparse for FieldDeclaration {
|
||||
|
||||
/* Statements */
|
||||
|
||||
impl Unparse for UseStatement {
|
||||
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.write_indented("use ")?;
|
||||
for (i, identifier) in self.identifiers.iter().enumerate() {
|
||||
identifier.unparse(writer)?;
|
||||
if i != self.identifiers.len() - 2 {
|
||||
// 2 because of use
|
||||
writer.write("::")?;
|
||||
}
|
||||
}
|
||||
self.last.unparse(writer)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Unparse for UseStatementLast {
|
||||
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
match self {
|
||||
UseStatementLast::Star => writer.write("*"),
|
||||
UseStatementLast::Identifiers(identifiers) => {
|
||||
writer.write("{")?;
|
||||
for (i, identifier) in identifiers.iter().enumerate() {
|
||||
identifier.unparse(writer)?;
|
||||
if i != identifiers.len() - 1 {
|
||||
writer.write(", ")?;
|
||||
}
|
||||
}
|
||||
writer.write("}")?;
|
||||
Ok(())
|
||||
}
|
||||
UseStatementLast::Identifier(i) => i.unparse(writer),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Unparse for BlockStatement {
|
||||
fn unparse(&self, writer: &mut IndentWriter) -> std::io::Result<()> {
|
||||
writer.writeln_indented("{")?;
|
||||
|
@ -30,6 +30,7 @@ Move = { "move" }
|
||||
Alias = { "alias" }
|
||||
True = { "true" }
|
||||
False = { "false" }
|
||||
Use = { "use" }
|
||||
|
||||
// Keywords as a rule (for preventing identifiers with keywords, etc.)
|
||||
Keyword = {
|
||||
@ -64,6 +65,7 @@ Keyword = {
|
||||
| Alias
|
||||
| True
|
||||
| False
|
||||
| Use
|
||||
}
|
||||
|
||||
// Symbols
|
||||
@ -280,7 +282,8 @@ RefList = {
|
||||
|
||||
CompilationUnit = {
|
||||
SOI
|
||||
~ Namespace?
|
||||
~ ( Namespace ~ Semicolon )?
|
||||
~ ( UseStatement ~ Semicolon )*
|
||||
~ ModuleLevelDeclaration*
|
||||
~ EOI
|
||||
}
|
||||
@ -479,6 +482,20 @@ Field = {
|
||||
|
||||
// Statements
|
||||
|
||||
UseStatement = {
|
||||
Use
|
||||
~ Identifier
|
||||
~ ( "::" ~ Identifier )*
|
||||
~ ( "::" ~ ( Star | UseList ) )?
|
||||
}
|
||||
|
||||
UseList = {
|
||||
"{"
|
||||
~ Identifier
|
||||
~ ( "," ~ Identifier )*
|
||||
~ "}"
|
||||
}
|
||||
|
||||
BlockStatement = {
|
||||
"{"
|
||||
~ Statement*
|
||||
@ -492,6 +509,7 @@ Statement = {
|
||||
| AssignmentStatement
|
||||
| CallStatement
|
||||
| ReturnStatement
|
||||
| UseStatement
|
||||
)
|
||||
~ Semicolon
|
||||
| (
|
||||
|
@ -8,7 +8,7 @@ pub struct DeimosParser;
|
||||
mod deimos_parser_tests {
|
||||
use crate::parser::{DeimosParser, Rule};
|
||||
use indoc::indoc;
|
||||
use pest::{parses_to, Parser};
|
||||
use pest::Parser;
|
||||
|
||||
macro_rules! fail_rule {
|
||||
($pair: expr; $rule:path) => {{
|
||||
@ -160,11 +160,14 @@ mod deimos_parser_tests {
|
||||
|
||||
#[test]
|
||||
fn if_statement_with_call_condition() {
|
||||
parses_to(Rule::IfStatement, indoc! {"
|
||||
parses_to(
|
||||
Rule::IfStatement,
|
||||
indoc! {"
|
||||
if (foo()) {
|
||||
bar()
|
||||
}
|
||||
"})
|
||||
"},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -174,10 +177,28 @@ mod deimos_parser_tests {
|
||||
|
||||
#[test]
|
||||
fn for_statement_with_call_iterator() {
|
||||
parses_to(Rule::ForStatement, indoc! {"
|
||||
parses_to(
|
||||
Rule::ForStatement,
|
||||
indoc! {"
|
||||
for (foo in bar()) {
|
||||
baz(foo);
|
||||
}
|
||||
"})
|
||||
"},
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_statement() {
|
||||
parses_to(Rule::UseStatement, "use std::core::println");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_star() {
|
||||
parses_to(Rule::UseStatement, "use std::core::*")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn use_list() {
|
||||
parses_to(Rule::UseStatement, "use std::core::{print, println}");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user