All the unimplementeds are gone!

This commit is contained in:
2025-11-11 13:42:19 -08:00
parent 45e49a4c84
commit c795172692
2 changed files with 177 additions and 10 deletions

View File

@@ -90,14 +90,15 @@ pub struct FunctionArg {
pub struct ValueDef {
pub name: Name,
pub location: Location,
pub mtype: Option<Type>,
pub value: Expression,
}
#[derive(Debug)]
pub struct OperatorDef {
pub operator_name: Name,
pub location: Location,
pub function_name: Name,
location: Location,
}
#[derive(Debug)]

View File

@@ -36,6 +36,14 @@ pub enum Associativity {
None,
}
/// The kind of operators we use. This is only narrowly useful inside
/// this particular crate.
enum OperatorType {
Prefix,
Infix,
Postfix,
}
impl<'lexer> Parser<'lexer> {
/// Create a new parser from the given file index and lexer.
///
@@ -614,12 +622,86 @@ impl<'lexer> Parser<'lexer> {
/// to; that variable can be declared further on in the file or even in another module,
/// as we won't try to resolve it until later.
///
/// Like most definitions, we'll abort cleanly if the first token isn't the "operator"
/// keyword, but all bets are off after that.
/// Like most definitions, we'll abort cleanly if the first token isn't "operator",
/// "infix", "postfix", or "prefix" keywords, but all bets are off after that.
pub fn parse_operator(&mut self) -> Result<OperatorDef, ParserError> {
let _operator = self.require_keyword("operator")?;
let (start, operator_type, associativity) = {
let mut optype = OperatorType::Infix;
let mut start = None;
let mut assoc = Associativity::None;
unimplemented!()
if let Ok(loc) = self.require_keyword("prefix") {
optype = OperatorType::Prefix;
start = Some(loc);
} else if let Ok(loc) = self.require_keyword("postfix") {
optype = OperatorType::Postfix;
start = Some(loc);
} else if let Ok(loc) = self.require_keyword("infix") {
start = Some(loc);
if self.require_keyword("right").is_ok() {
assoc = Associativity::Right;
} else if self.require_keyword("left").is_ok() {
assoc = Associativity::Left;
}
}
let oploc = self.require_keyword("operator")?;
(start.unwrap_or(oploc), optype, assoc)
};
let operator_name = self.parse_operator_name("operator definition")?;
let level = if self.require_keyword("at").is_ok() {
let next = self
.next()?
.ok_or_else(|| self.bad_eof("precedence value in operator definition"))?;
match next.token {
Token::Integer(int_with_base) if int_with_base.value < 10 => {
int_with_base.value as u8
}
Token::Integer(ref int_with_base) => {
return Err(ParserError::UnexpectedToken {
file: self.file.clone(),
span: next.span,
token: next.token.clone(),
expected: format!(
"number defining operator precedence ({} is too large",
int_with_base.value
),
});
}
_ => {
return Err(ParserError::UnexpectedToken {
file: self.file.clone(),
span: next.span,
token: next.token,
expected: "number defining operator precedence".into(),
});
}
}
} else {
5
};
let function_name = self.parse_name("operator function definition")?;
let end = self.require_token(Token::Semi, "end of operator definition")?;
match operator_type {
OperatorType::Infix => {
self.add_infix_precedence(operator_name.as_printed(), associativity, level)
}
OperatorType::Prefix => self.add_prefix_precedence(operator_name.as_printed(), level),
OperatorType::Postfix => self.add_postfix_precedence(operator_name.as_printed(), level),
}
Ok(OperatorDef {
location: start.extend_to(&end),
operator_name,
function_name,
})
}
/// Parse a function or a value.
@@ -648,33 +730,63 @@ impl<'lexer> Parser<'lexer> {
//
// Or any of many variations of that.
Token::OpenParen => {
unimplemented!()
self.save(next);
let arguments = self.parse_function_def_arguments()?;
let mut return_type = None;
if self.require_token(Token::Colon, "return type").is_ok() {
return_type = Some(self.parse_type()?);
}
let Expression::Block(end, body) = self.parse_block()? else {
panic!("parse_block returned something that wasn't a block.");
};
Ok(Def::Function(FunctionDef {
name,
location: start.extend_to(&end),
arguments,
return_type,
body,
}))
}
// If we see a colon, then someone's giving us a type for what is probably
// some form of simple constant, such as:
//
// foo : Int = 4
// foo : Int = 4;
//
// But honestly, there's a lot of odd possibilities of complicated things
// they could write there.
Token::Colon => {
unimplemented!()
let value_type = self.parse_type()?;
let _ = self.require_operator("=")?;
let value = self.parse_expression()?;
let end = self.require_token(Token::Semi, "at end of definition")?;
Ok(Def::Value(ValueDef {
name,
location: start.extend_to(&end),
mtype: Some(value_type),
value,
}))
}
// If we see an equal sign, we're jumping right to the value part of the
// definition, and we're doing something like this:
//
// foo = 4
// foo = 4;
//
// Again, though, you could write all sorts of interesting things after
// that.
Token::OperatorName(eq) if eq == "=" => {
let value = self.parse_expression()?;
let end = self.require_token(Token::Semi, "at end of definition")?;
Ok(Def::Value(ValueDef {
name,
location: start.extend_to(&value.location()),
location: start.extend_to(&end),
mtype: None,
value,
}))
}
@@ -690,6 +802,38 @@ impl<'lexer> Parser<'lexer> {
}
}
/// Parse the arguments to a function declaration.
///
/// Function arguments should have types, but don't have to. This function assumes
/// that it's starting at the opening parenthesis, and will error (cleanly) if it
/// isn't.
fn parse_function_def_arguments(&mut self) -> Result<Vec<FunctionArg>, ParserError> {
let _ = self.require_token(Token::OpenParen, "start of function argument definition")?;
let mut result = vec![];
loop {
let next = self
.next()?
.ok_or_else(|| self.bad_eof("parsing function arguments"))?;
if matches!(next.token, Token::CloseParen) {
break;
}
self.save(next);
let name = self.parse_name("function argument name")?;
let mut arg_type = None;
if self.require_token(Token::Colon, "").is_ok() {
arg_type = Some(self.parse_type()?);
}
result.push(FunctionArg { name, arg_type });
}
Ok(result)
}
/// Parse a single expression out of the input stream.
///
/// Because expressions can start with so many possible tokens, it's very
@@ -1580,4 +1724,26 @@ impl<'lexer> Parser<'lexer> {
})
}
}
/// Try to parse an operator from the input stream.
///
/// If we don't find a name, the stream should be returned in the same state
/// at which it entered this function.
fn parse_operator_name(&mut self, place: &'static str) -> Result<Name, ParserError> {
let maybe_name = self
.next()?
.ok_or_else(|| self.bad_eof(format!("looking for a type name in {place}")))?;
if let Token::OperatorName(x) = maybe_name.token {
Ok(Name::new(self.to_location(maybe_name.span), x))
} else {
self.save(maybe_name.clone());
Err(ParserError::UnexpectedToken {
file: self.file.clone(),
span: maybe_name.span,
token: maybe_name.token,
expected: format!("looking for an operator name in {place}"),
})
}
}
}