///|
/// `start_tok` then a type (`: T`, `-> T`); `ExpectedType` at `start_tok`
/// when the type is missing; `None` without `start_tok`.
fn Parser::parse_type_annotation(
self : Parser,
start_tok : @scanner.TokenKind,
) -> @ast.TypeAst? raise ParseError {
match self.maybe_one(start_tok) {
Some((start, end)) =>
match self.parse_type() {
None => parse_error(ExpectedType, sp(start, end))
some => some
}
None => None
}
}
///|
/// A type annotation without its `:`; `None` when `token0` does not start
/// one.
fn Parser::parse_type(self : Parser) -> @ast.TypeAst? raise ParseError {
self.nested(op_type, () => self.parse_type_inner())
}
///|
fn Parser::parse_type_inner(self : Parser) -> @ast.TypeAst? raise ParseError {
match self.token0 {
// Type hole
Some({ kind: DiscardName(name), span, .. }) => {
self.advance()
Some(Hole({ location: span, name, }))
}
// Tuple
Some({ kind: Hash, span, .. }) => {
self.advance()
let _ = self.expect_one(LeftParen)
let elements = self.parse_types()
let (_, end) = self.expect_one(RightParen)
Some(Tuple({ location: sp(span.start, end), elements: elements[:], }))
}
// Function
Some({ kind: Keyword(Fn), span, .. }) => {
self.advance()
let _ = self.expect_one(LeftParen)
let arguments = self.series_of(p => p.parse_type(), Some(Comma))
let _ = self.expect_one_following_series(RightParen, "a type")
let (arr_s, arr_e) = self.expect_one(RArrow)
match self.parse_type() {
Some(return_) =>
Some(
@ast.TypeAst::Fn({
location: sp(span.start, return_.location().end),
arguments: arguments[:],
return_,
}),
)
None => parse_error(ExpectedType, sp(arr_s, arr_e))
}
}
// Constructor
Some({ kind: UpName(name), span, .. }) => {
self.advance()
self.parse_type_name_finish(
span.start,
span.end,
Unqualified(name~, location=span),
)
}
// Constructor module, or type variable
Some({ kind: Name(module_), span, .. }) => {
self.advance()
match self.maybe_one(Dot) {
Some((_, dot_end)) =>
match self.maybe_upname() {
Some((name_start, name, name_end)) =>
self.parse_type_name_finish(
span.start,
name_end,
Qualified(
module_~,
module_location=span,
dot_location=dot_end,
name=Some({ location: sp(name_start, name_end), name, }),
),
)
None =>
self.parse_type_name_finish(
span.start,
dot_end,
Qualified(
module_~,
module_location=span,
dot_location=dot_end,
name=None,
),
)
}
None => Some(Var({ location: span, name: module_, }))
}
}
_ => None
}
}
///|
/// The `( ... )` of a type name, or the angle-bracket error.
fn Parser::parse_type_name_finish(
self : Parser,
start : Int32,
end : Int32,
name : @ast.TypeAstConstructorName,
) -> @ast.TypeAst? raise ParseError {
match self.maybe_one(LeftParen) {
Some((left_paren_start, left_paren_end)) => {
// `wibble.(a, b)`: the `(` is unexpected, a type name was expected.
if name is Qualified(name=None, ..) {
parse_error(ExpectedUpName, sp(left_paren_start, left_paren_end))
}
let arguments = self.parse_types()
let (_, right_paren_end) = self.expect_one(RightParen)
Some(
Constructor({
location: sp(start, right_paren_end),
name,
arguments: arguments[:],
start_parentheses: Some(left_paren_start),
}),
)
}
None =>
match self.maybe_one(Less) {
Some((less_start, less_end)) => {
let location = sp(less_start, less_end)
let (module_, type_name) = match name {
Qualified(module_~, name=Some(n), ..) => (Some(module_), n.name)
Unqualified(name~, ..) => (None, name)
// `wibble.<`: the hint about angle brackets makes no sense.
Qualified(name=None, ..) => parse_error(ExpectedUpName, location)
}
let arguments = self.parse_types()
parse_error(
TypeUsageAngleGenerics(
module_~,
name=type_name,
arguments=arguments[:],
),
location,
)
}
None =>
Some(
Constructor({
location: sp(start, end),
name,
arguments: [][:],
start_parentheses: None,
}),
)
}
}
}
///|
/// Comma-separated types, for tuples, constructors and functions.
fn Parser::parse_types(self : Parser) -> Array[@ast.TypeAst] raise ParseError {
self.series_of(p => p.parse_type(), Some(Comma))
}