|
|
|
@ -15,6 +15,7 @@ enum Scope {
|
|
|
|
|
Target,
|
|
|
|
|
DepList,
|
|
|
|
|
SourceList,
|
|
|
|
|
Function,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Parser {
|
|
|
|
@ -79,12 +80,14 @@ impl Parser {
|
|
|
|
|
let token = self.lexer.peek_or_err()?;
|
|
|
|
|
match token.kind {
|
|
|
|
|
token::Kind::DependKeyword => self.parse_depend_stmt(),
|
|
|
|
|
token::Kind::FnKeyword => self.parse_fn(false),
|
|
|
|
|
token::Kind::IfKeyword => self.parse_if_stmt(),
|
|
|
|
|
token::Kind::ReturnKeyword => self.parse_return_stmt(),
|
|
|
|
|
token::Kind::SetKeyword => self.parse_set_stmt(),
|
|
|
|
|
token::Kind::SourceKeyword => self.parse_source_stmt(),
|
|
|
|
|
token::Kind::TargetKeyword => self.parse_target_stmt(),
|
|
|
|
|
token::Kind::TypeKeyword => self.parse_type_stmt(),
|
|
|
|
|
token::Kind::Ident => self.parse_expr_stmt(),
|
|
|
|
|
k if k.is_start_of_expr() => self.parse_expr_stmt(),
|
|
|
|
|
_ => self.syntax_error(format!("Unexpected token {}", token), &token),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -111,6 +114,17 @@ impl Parser {
|
|
|
|
|
Ok(tree::Node::Block(nodes))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ```notrust
|
|
|
|
|
/// ReturnStatement
|
|
|
|
|
/// : "return" Expression ";"
|
|
|
|
|
/// ```
|
|
|
|
|
fn parse_return_stmt(&mut self) -> Result<tree::Node, Error> {
|
|
|
|
|
self.assert_scope(Scope::Function)?;
|
|
|
|
|
self.lexer.expect_kind(token::Kind::ReturnKeyword)?;
|
|
|
|
|
let expr = self.parse_expr(&[token::Kind::Semi])?;
|
|
|
|
|
Ok(tree::Node::ReturnStmt(Box::new(expr)))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ```notrust
|
|
|
|
|
/// TargetStatement
|
|
|
|
|
/// : "target" Expression BlockStatement
|
|
|
|
@ -452,6 +466,10 @@ impl Parser {
|
|
|
|
|
token::Kind::StringLiteral => Ok(tree::Node::String(token.raw)),
|
|
|
|
|
token::Kind::TrueKeyword => Ok(tree::Node::Bool(true)),
|
|
|
|
|
token::Kind::FalseKeyword => Ok(tree::Node::Bool(false)),
|
|
|
|
|
token::Kind::FnKeyword => {
|
|
|
|
|
self.lexer.prev(); // parse_fn() expects to consume the keyword
|
|
|
|
|
self.parse_fn(true)
|
|
|
|
|
}
|
|
|
|
|
token::Kind::OBracket => {
|
|
|
|
|
let elements =
|
|
|
|
|
self.parse_delimited_list(token::Kind::Comma, token::Kind::CBracket, true)?;
|
|
|
|
@ -469,6 +487,7 @@ impl Parser {
|
|
|
|
|
/// matrix[y][x]
|
|
|
|
|
/// array_of_functions[index](params)
|
|
|
|
|
/// function_returning_an_array(params)[index]
|
|
|
|
|
/// (fn(a, b) { return a + b; })(1, 2)
|
|
|
|
|
/// ```
|
|
|
|
|
fn parse_primary_expr_rest(&mut self, start: tree::Node) -> Result<tree::Node, Error> {
|
|
|
|
|
if let Some(Ok(token)) = self.lexer.peek() {
|
|
|
|
@ -499,6 +518,56 @@ impl Parser {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// ```notrust
|
|
|
|
|
/// Function
|
|
|
|
|
/// : "fn" [ Identifier ] "(" [ ParameterList ] ")" BlockStatement
|
|
|
|
|
///
|
|
|
|
|
/// ParameterList
|
|
|
|
|
/// : Identifier [ "," ParameterList ]
|
|
|
|
|
/// ```
|
|
|
|
|
fn parse_fn(&mut self, allow_anonymous: bool) -> Result<tree::Node, Error> {
|
|
|
|
|
self.scope.push(Scope::Function);
|
|
|
|
|
self.lexer.expect_kind(token::Kind::FnKeyword)?;
|
|
|
|
|
|
|
|
|
|
// function name is optional (there are inline anonymous functions)
|
|
|
|
|
let name = if let Some(Ok(token)) = self.lexer.peek() {
|
|
|
|
|
if token.kind == token::Kind::Ident {
|
|
|
|
|
self.lexer.next();
|
|
|
|
|
Some(Box::new(tree::Node::Ident(token.raw)))
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let oparen = self.lexer.expect_kind(token::Kind::OParen)?;
|
|
|
|
|
if name.is_none() && !allow_anonymous {
|
|
|
|
|
// anonymous function are not allowed for definitions as a block
|
|
|
|
|
// statement (you can only do that with inline functions)
|
|
|
|
|
return self.syntax_error(String::from("Function name required"), &oparen);
|
|
|
|
|
}
|
|
|
|
|
let params = self.parse_delimited_list(token::Kind::Comma, token::Kind::CParen, false)?;
|
|
|
|
|
for p in ¶ms {
|
|
|
|
|
match p {
|
|
|
|
|
tree::Node::Ident(_) => continue,
|
|
|
|
|
_ => {
|
|
|
|
|
return self
|
|
|
|
|
.syntax_error(format!("Not an identifier"), &self.lexer.current().unwrap())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let body = self.parse_block_stmt()?;
|
|
|
|
|
|
|
|
|
|
self.scope.pop();
|
|
|
|
|
Ok(tree::Node::Fn {
|
|
|
|
|
name,
|
|
|
|
|
params,
|
|
|
|
|
body: Box::new(body),
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Parse a terminated, delimited list of expressions. This is used for
|
|
|
|
|
/// parameter lists in function calls and elements in array literals.
|
|
|
|
|
fn parse_delimited_list(
|
|
|
|
|