Import statement syntax
This commit is contained in:
parent
603ea89b98
commit
a054de56a2
@ -58,7 +58,8 @@ pub struct Statement {
|
|||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum StatementKind {
|
pub enum StatementKind {
|
||||||
Expression(Expression),
|
Expression(Expression),
|
||||||
Declaration(Declaration), //TODO Declaration should also be Meta-wrapped; only Expression and Declaration are Meta-wrapped maybe?
|
Declaration(Declaration),
|
||||||
|
Import(ImportSpecifier),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Block = Vec<Statement>;
|
pub type Block = Vec<Statement>;
|
||||||
@ -272,3 +273,20 @@ pub enum ForBody {
|
|||||||
MonadicReturn(Expression),
|
MonadicReturn(Expression),
|
||||||
StatementBlock(Block),
|
StatementBlock(Block),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Derivative, Clone)]
|
||||||
|
#[derivative(PartialEq)]
|
||||||
|
pub struct ImportSpecifier {
|
||||||
|
#[derivative(PartialEq="ignore")]
|
||||||
|
pub id: ItemId,
|
||||||
|
pub path_components: Vec<Rc<String>>,
|
||||||
|
pub imported_names: ImportedNames
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum ImportedNames {
|
||||||
|
All,
|
||||||
|
LastOfPath,
|
||||||
|
List(Vec<Rc<String>>)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,8 @@
|
|||||||
//! ```
|
//! ```
|
||||||
//! ## Imports
|
//! ## Imports
|
||||||
//! ```text
|
//! ```text
|
||||||
//! import := 'import'
|
//! import := 'import' IDENTIFIER (:: IDENTIFIER)* import_suffix
|
||||||
|
//! import_suffix := ε | '::{' IDENTIFIER (, IDENTIFIER)* '}' | '*' //TODO add qualified, exclusions, etc.
|
||||||
//! ```
|
//! ```
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
@ -351,6 +352,7 @@ impl Parser {
|
|||||||
Keyword(Let) => self.binding_declaration().map(|decl| StatementKind::Declaration(decl)),
|
Keyword(Let) => self.binding_declaration().map(|decl| StatementKind::Declaration(decl)),
|
||||||
Keyword(Interface) => self.interface_declaration().map(|decl| StatementKind::Declaration(decl)),
|
Keyword(Interface) => self.interface_declaration().map(|decl| StatementKind::Declaration(decl)),
|
||||||
Keyword(Impl) => self.impl_declaration().map(|decl| StatementKind::Declaration(decl)),
|
Keyword(Impl) => self.impl_declaration().map(|decl| StatementKind::Declaration(decl)),
|
||||||
|
Keyword(Import) => self.import_declaration().map(|spec| StatementKind::Import(spec)),
|
||||||
_ => self.expression().map(|expr| { StatementKind::Expression(expr.into()) } ),
|
_ => self.expression().map(|expr| { StatementKind::Expression(expr.into()) } ),
|
||||||
}?;
|
}?;
|
||||||
Ok(Statement { kind, id: self.id_store.fresh() })
|
Ok(Statement { kind, id: self.id_store.fresh() })
|
||||||
@ -765,7 +767,8 @@ impl Parser {
|
|||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
fn identifier_expr(&mut self) -> ParseResult<Expression> {
|
fn identifier_expr(&mut self) -> ParseResult<Expression> {
|
||||||
use self::ExpressionKind::*;
|
use self::ExpressionKind::*;
|
||||||
let qualified_identifier = self.qualified_identifier()?;
|
let components = self.qualified_identifier()?;
|
||||||
|
let qualified_identifier = QualifiedName { id: self.id_store.fresh(), components };
|
||||||
Ok(match self.token_handler.peek_kind() {
|
Ok(match self.token_handler.peek_kind() {
|
||||||
LCurlyBrace if !self.restrictions.no_struct_literal => {
|
LCurlyBrace if !self.restrictions.no_struct_literal => {
|
||||||
let fields = self.record_block()?;
|
let fields = self.record_block()?;
|
||||||
@ -776,7 +779,7 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
fn qualified_identifier(&mut self) -> ParseResult<QualifiedName> {
|
fn qualified_identifier(&mut self) -> ParseResult<Vec<Rc<String>>> {
|
||||||
let mut components = vec![self.identifier()?];
|
let mut components = vec![self.identifier()?];
|
||||||
loop {
|
loop {
|
||||||
match (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
|
match (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
|
||||||
@ -787,7 +790,7 @@ impl Parser {
|
|||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(QualifiedName { id: self.id_store.fresh(), components })
|
Ok(components)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[recursive_descent_method]
|
#[recursive_descent_method]
|
||||||
@ -939,18 +942,19 @@ impl Parser {
|
|||||||
fn simple_pattern(&mut self) -> ParseResult<Pattern> {
|
fn simple_pattern(&mut self) -> ParseResult<Pattern> {
|
||||||
Ok(match self.token_handler.peek_kind() {
|
Ok(match self.token_handler.peek_kind() {
|
||||||
Identifier(_) => {
|
Identifier(_) => {
|
||||||
let qualified_name = self.qualified_identifier()?;
|
let components = self.qualified_identifier()?;
|
||||||
|
let qualified_identifier = QualifiedName { id: self.id_store.fresh(), components };
|
||||||
match self.token_handler.peek_kind() {
|
match self.token_handler.peek_kind() {
|
||||||
LCurlyBrace => {
|
LCurlyBrace => {
|
||||||
let members = delimited!(self, LCurlyBrace, record_pattern_entry, Comma, RCurlyBrace);
|
let members = delimited!(self, LCurlyBrace, record_pattern_entry, Comma, RCurlyBrace);
|
||||||
Pattern::Record(qualified_name, members)
|
Pattern::Record(qualified_identifier, members)
|
||||||
},
|
},
|
||||||
LParen => {
|
LParen => {
|
||||||
let members = delimited!(self, LParen, pattern, Comma, RParen);
|
let members = delimited!(self, LParen, pattern, Comma, RParen);
|
||||||
Pattern::TupleStruct(qualified_name, members)
|
Pattern::TupleStruct(qualified_identifier, members)
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Pattern::VarOrName(qualified_name)
|
Pattern::VarOrName(qualified_identifier)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1233,6 +1237,59 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
Ok(ds)
|
Ok(ds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[recursive_descent_method]
|
||||||
|
fn import_declaration(&mut self) -> ParseResult<ImportSpecifier> {
|
||||||
|
expect!(self, Keyword(Import));
|
||||||
|
let mut path_components = vec![];
|
||||||
|
path_components.push(self.identifier()?);
|
||||||
|
loop {
|
||||||
|
match (self.token_handler.peek_kind(), self.token_handler.peek_kind_n(1)) {
|
||||||
|
(Colon, Colon) => {
|
||||||
|
self.token_handler.next(); self.token_handler.next();
|
||||||
|
if let Identifier(_) = self.token_handler.peek_kind() {
|
||||||
|
path_components.push(self.identifier()?);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let imported_names = match self.token_handler.peek_kind() {
|
||||||
|
LCurlyBrace => {
|
||||||
|
let names = delimited!(self, LCurlyBrace, identifier, Comma, RCurlyBrace);
|
||||||
|
ImportedNames::List(names)
|
||||||
|
},
|
||||||
|
Operator(ref s) if **s == "*" => {
|
||||||
|
self.token_handler.next();
|
||||||
|
ImportedNames::All
|
||||||
|
},
|
||||||
|
_ => ImportedNames::LastOfPath
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(ImportSpecifier {
|
||||||
|
id: self.id_store.fresh(),
|
||||||
|
path_components,
|
||||||
|
imported_names
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[recursive_descent_method]
|
||||||
|
fn import_suffix(&mut self) -> ParseResult<ImportedNames> {
|
||||||
|
Ok(match self.token_handler.peek_kind() {
|
||||||
|
Operator(ref s) if **s == "*" => {
|
||||||
|
self.token_handler.next();
|
||||||
|
ImportedNames::All
|
||||||
|
},
|
||||||
|
LCurlyBrace => {
|
||||||
|
let names = delimited!(self, LCurlyBrace, identifier, Comma, RCurlyBrace);
|
||||||
|
ImportedNames::List(names)
|
||||||
|
},
|
||||||
|
_ => return ParseError::new_with_token("Expected '{{' or '*'", self.token_handler.peek()),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_binary(digits: String, tok: Token) -> ParseResult<u64> {
|
fn parse_binary(digits: String, tok: Token) -> ParseResult<u64> {
|
||||||
@ -1267,3 +1324,4 @@ fn parse_hex(digits: String, tok: Token) -> ParseResult<u64> {
|
|||||||
}
|
}
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ use std::str::FromStr;
|
|||||||
|
|
||||||
use super::tokenize;
|
use super::tokenize;
|
||||||
use super::ParseResult;
|
use super::ParseResult;
|
||||||
use crate::ast::{ItemIdStore, AST, Expression, Statement, StatementKind, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName};
|
use crate::ast::{ItemIdStore, AST, Expression, Statement, StatementKind, IfExpressionBody, Discriminator, Pattern, PatternLiteral, TypeBody, Enumerator, ForBody, InvocationArgument, FormalParam, PrefixOp, BinOp, QualifiedName, ImportSpecifier, ImportedNames};
|
||||||
use super::Declaration::*;
|
use super::Declaration::*;
|
||||||
use super::Signature;
|
use super::Signature;
|
||||||
use super::TypeIdentifier::*;
|
use super::TypeIdentifier::*;
|
||||||
@ -57,6 +57,12 @@ macro_rules! decl {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! import {
|
||||||
|
($import_spec:expr) => {
|
||||||
|
Statement { id: ItemIdStore::new_id(), kind: StatementKind::Import($import_spec) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! ex {
|
macro_rules! ex {
|
||||||
($expr_type:expr) => { Expression::new(ItemIdStore::new_id(), $expr_type) };
|
($expr_type:expr) => { Expression::new(ItemIdStore::new_id(), $expr_type) };
|
||||||
($expr_type:expr, $type_anno:expr) => { Expression::with_anno(ItemIdStore::new_id(), $expr_type, $type_anno) };
|
($expr_type:expr, $type_anno:expr) => { Expression::with_anno(ItemIdStore::new_id(), $expr_type, $type_anno) };
|
||||||
@ -702,3 +708,55 @@ fn pattern_literals() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imports() {
|
||||||
|
parse_test_wrap_ast! {
|
||||||
|
"import harbinger::draughts::Norgleheim",
|
||||||
|
import!(ImportSpecifier {
|
||||||
|
id: ItemIdStore::new_id(),
|
||||||
|
path_components: vec![rc!(harbinger), rc!(draughts), rc!(Norgleheim)],
|
||||||
|
imported_names: ImportedNames::LastOfPath
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imports_2() {
|
||||||
|
parse_test_wrap_ast! {
|
||||||
|
"import harbinger::draughts::{Norgleheim, Xraksenlaigar}",
|
||||||
|
import!(ImportSpecifier {
|
||||||
|
id: ItemIdStore::new_id(),
|
||||||
|
path_components: vec![rc!(harbinger), rc!(draughts)],
|
||||||
|
imported_names: ImportedNames::List(vec![
|
||||||
|
rc!(Norgleheim),
|
||||||
|
rc!(Xraksenlaigar)
|
||||||
|
])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imports_3() {
|
||||||
|
parse_test_wrap_ast! {
|
||||||
|
"import bespouri::{}",
|
||||||
|
import!(ImportSpecifier {
|
||||||
|
id: ItemIdStore::new_id(),
|
||||||
|
path_components: vec![rc!(bespouri)],
|
||||||
|
imported_names: ImportedNames::List(vec![])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn imports_4() {
|
||||||
|
parse_test_wrap_ast! {
|
||||||
|
"import bespouri::*",
|
||||||
|
import!(ImportSpecifier {
|
||||||
|
id: ItemIdStore::new_id(),
|
||||||
|
path_components: vec![rc!(bespouri)],
|
||||||
|
imported_names: ImportedNames::All
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -129,6 +129,7 @@ impl<'a> Reducer<'a> {
|
|||||||
match &stmt.kind {
|
match &stmt.kind {
|
||||||
StatementKind::Expression(expr) => Stmt::Expr(self.expression(&expr)),
|
StatementKind::Expression(expr) => Stmt::Expr(self.expression(&expr)),
|
||||||
StatementKind::Declaration(decl) => self.declaration(&decl),
|
StatementKind::Declaration(decl) => self.declaration(&decl),
|
||||||
|
StatementKind::Import(_) => Stmt::Noop,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ impl<'a> ScopeResolver<'a> {
|
|||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::Declaration(ref decl) => self.decl(decl),
|
StatementKind::Declaration(ref decl) => self.decl(decl),
|
||||||
StatementKind::Expression(ref expr) => self.expr(expr),
|
StatementKind::Expression(ref expr) => self.expr(expr),
|
||||||
|
StatementKind::Import(_) => Ok(())
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -32,6 +33,7 @@ impl<'a> ScopeResolver<'a> {
|
|||||||
match statement.kind {
|
match statement.kind {
|
||||||
StatementKind::Declaration(ref decl) => self.decl(decl),
|
StatementKind::Declaration(ref decl) => self.decl(decl),
|
||||||
StatementKind::Expression(ref expr) => self.expr(expr),
|
StatementKind::Expression(ref expr) => self.expr(expr),
|
||||||
|
StatementKind::Import(_) => Ok(())
|
||||||
}?;
|
}?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -274,6 +274,7 @@ impl<'a> TypeContext<'a> {
|
|||||||
match &statement.kind {
|
match &statement.kind {
|
||||||
StatementKind::Expression(e) => self.expr(e),
|
StatementKind::Expression(e) => self.expr(e),
|
||||||
StatementKind::Declaration(decl) => self.decl(&decl),
|
StatementKind::Declaration(decl) => self.decl(&decl),
|
||||||
|
StatementKind::Import(_) => Ok(ty!(Unit)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user