Merge remote-tracking branch 'refs/remotes/origin/compiler' into compiler
This commit is contained in:
+203
-43
@@ -1,4 +1,4 @@
|
||||
use crate::expect_type;
|
||||
use crate::expect_tt;
|
||||
use crate::lexer::Token;
|
||||
|
||||
pub struct Parser {
|
||||
@@ -10,7 +10,7 @@ pub struct Parser {
|
||||
impl Parser {
|
||||
pub fn new(tokens: Vec<Token>) -> Self {
|
||||
Self {
|
||||
ast: Node::Scope {
|
||||
ast: Node::Block {
|
||||
children: Vec::new(),
|
||||
},
|
||||
idx: 0,
|
||||
@@ -19,13 +19,17 @@ impl Parser {
|
||||
}
|
||||
|
||||
pub fn parse(&mut self) -> Result<Node, CompileError> {
|
||||
self.parse_block()
|
||||
}
|
||||
|
||||
fn parse_block(&mut self) -> Result<Node, CompileError> {
|
||||
let mut statements = Vec::new();
|
||||
|
||||
while let Some(_) = self.peek_next() {
|
||||
while self.peek_next().is_ok() {
|
||||
statements.push(self.parse_statement()?);
|
||||
}
|
||||
|
||||
Ok(Node::Scope {
|
||||
Ok(Node::Block {
|
||||
children: statements,
|
||||
})
|
||||
}
|
||||
@@ -35,11 +39,11 @@ impl Parser {
|
||||
let left = if let Ok(typed_var) = self.parse_typed_var() {
|
||||
Box::new(typed_var)
|
||||
} else {
|
||||
let tok = expect_type!(self.next()?, Identifier)?;
|
||||
let tok = expect_tt!(self.next()?, Identifier)?;
|
||||
Box::new(Node::Terminal { value: tok })
|
||||
};
|
||||
|
||||
let _ = expect_type!(self.next()?, Assign)?;
|
||||
let _ = expect_tt!(self.next()?, Assign)?;
|
||||
|
||||
let right = Box::new(self.parse_expression()?);
|
||||
|
||||
@@ -47,17 +51,144 @@ impl Parser {
|
||||
}
|
||||
|
||||
fn parse_typed_var(&mut self) -> Result<Node, CompileError> {
|
||||
let name = expect_type!(self.next()?, Identifier)?;
|
||||
let _ = expect_type!(self.next()?, Colon)?;
|
||||
let type_ = expect_type!(self.next()?, Identifier)?;
|
||||
let name = expect_tt!(self.next()?, Identifier)?;
|
||||
let _ = expect_tt!(self.next()?, Colon)?;
|
||||
let type_ = expect_tt!(self.next()?, Identifier)?;
|
||||
|
||||
Ok(Node::TypedVar { name, type_ })
|
||||
}
|
||||
|
||||
fn parse_expression(&mut self) -> Result<Node, CompileError> {
|
||||
if expect_tt!(self.peek_next()?, Pipe).is_ok() {
|
||||
return self.parse_func();
|
||||
}
|
||||
|
||||
if expect_tt!(self.peek_next()?, If).is_ok() {
|
||||
return self.parse_if();
|
||||
}
|
||||
|
||||
if expect_tt!(self.peek_next()?, Loop).is_ok() {
|
||||
return self.parse_loop();
|
||||
}
|
||||
|
||||
if expect_tt!(self.peek_next()?, Identifier, String, Number).is_ok() {
|
||||
let left = Node::Terminal {
|
||||
value: self.next()?,
|
||||
};
|
||||
|
||||
if expect_tt!(
|
||||
self.next()?,
|
||||
Plus,
|
||||
Minus,
|
||||
Star,
|
||||
Slash,
|
||||
EqualEqual,
|
||||
BangEqual,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
GreaterEqual
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return Ok(left);
|
||||
}
|
||||
|
||||
let operator = self.next()?;
|
||||
let right = Box::new(self.parse_expression()?);
|
||||
|
||||
return Ok(Node::BinaryOp {
|
||||
left: Box::new(left),
|
||||
op: operator,
|
||||
right,
|
||||
});
|
||||
}
|
||||
|
||||
Err(CompileError::Generic)
|
||||
}
|
||||
|
||||
fn parse_func(&mut self) -> Result<Node, CompileError> {
|
||||
// left arg delimiter
|
||||
let _ = expect_tt!(self.next()?, Pipe)?;
|
||||
|
||||
// parse args
|
||||
let mut args = Vec::new();
|
||||
|
||||
while expect_tt!(self.peek_next()?, Identifier).is_ok() {
|
||||
// add a typed var
|
||||
let arg = self.parse_typed_var()?;
|
||||
args.push(arg);
|
||||
}
|
||||
|
||||
// right arg delimiter
|
||||
let _ = expect_tt!(self.next()?, Pipe)?;
|
||||
|
||||
// ensure we have an open brace
|
||||
let _ = expect_tt!(self.next()?, LeftBrace)?;
|
||||
|
||||
// parse the body
|
||||
let body = Box::new(self.parse_block()?);
|
||||
|
||||
// ensure we have a close brace
|
||||
let _ = expect_tt!(self.next()?, RightBrace)?;
|
||||
|
||||
Ok(Node::FunctionDef { params: args, body })
|
||||
}
|
||||
|
||||
fn parse_loop(&mut self) -> Result<Node, CompileError> {
|
||||
let _ = expect_tt!(self.next()?, Loop)?;
|
||||
|
||||
// ensure we have an open brace
|
||||
let _ = expect_tt!(self.next()?, LeftBrace)?;
|
||||
|
||||
// parse the body
|
||||
let body = Box::new(self.parse_block()?);
|
||||
|
||||
// ensure we have a close brace
|
||||
let _ = expect_tt!(self.next()?, RightBrace)?;
|
||||
|
||||
Ok(Node::Loop { body })
|
||||
}
|
||||
|
||||
fn parse_if(&mut self) -> Result<Node, CompileError> {
|
||||
let _ = expect_tt!(self.next()?, If)?;
|
||||
|
||||
// parse condition (expr)
|
||||
let condition = Box::new(self.parse_expression()?);
|
||||
|
||||
// ensure we have an open brace
|
||||
let _ = expect_tt!(self.next()?, LeftBrace)?;
|
||||
|
||||
// parse the "then" branch (expr/statement)
|
||||
let then_branch = Box::new(self.parse_expression()?);
|
||||
|
||||
// ensure we have a close brace
|
||||
let _ = expect_tt!(self.next()?, RightBrace)?;
|
||||
|
||||
// if there is an else branch, we include it in the statement
|
||||
let else_branch = self.parse_else()?.map(Box::new);
|
||||
|
||||
Ok(Node::If {
|
||||
condition,
|
||||
then_branch,
|
||||
else_branch,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_else(&mut self) -> Result<Option<Node>, CompileError> {
|
||||
// if there is no else branch, return None.
|
||||
if expect_tt!(self.peek_next()?, Else).is_err() {
|
||||
return Ok(None);
|
||||
}
|
||||
let _ = self.next()?;
|
||||
|
||||
if expect_tt!(self.peek_next()?, If).is_ok() {
|
||||
Ok(Some(self.parse_if()?))
|
||||
} else {
|
||||
Ok(Some(self.parse_expression()?))
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) -> Result<Token, CompileError> {
|
||||
if self.idx >= self.tokens.len() {
|
||||
return Err(CompileError::UnexpectedEOF);
|
||||
@@ -69,53 +200,54 @@ impl Parser {
|
||||
Ok(token)
|
||||
}
|
||||
|
||||
fn peek_next(&mut self) -> Option<Token> {
|
||||
fn peek_next(&mut self) -> Result<Token, CompileError> {
|
||||
if self.idx >= self.tokens.len() {
|
||||
return None;
|
||||
return Err(CompileError::UnexpectedEOF);
|
||||
}
|
||||
|
||||
Some(self.tokens[self.idx].clone())
|
||||
Ok(self.tokens[self.idx].clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum Node {
|
||||
Scope {
|
||||
children: Vec<Node>,
|
||||
},
|
||||
Terminal {
|
||||
value: Token,
|
||||
},
|
||||
UnaryOp {
|
||||
op: Token,
|
||||
right: Box<Node>,
|
||||
},
|
||||
/// A scope, which is a list of child nodes that are evaluated in order.
|
||||
Block { children: Vec<Node> },
|
||||
|
||||
/// A leaf node with a value.
|
||||
Terminal { value: Token },
|
||||
|
||||
/// A unary operator with a right operand.
|
||||
UnaryOp { op: Token, right: Box<Node> },
|
||||
|
||||
/// A binary operator with a left and right operand.
|
||||
BinaryOp {
|
||||
left: Box<Node>,
|
||||
op: Token,
|
||||
right: Box<Node>,
|
||||
},
|
||||
Statement {
|
||||
left: Box<Node>,
|
||||
right: Box<Node>,
|
||||
},
|
||||
|
||||
/// A statement, consisting of a value to assign to, and an expression.
|
||||
Statement { left: Box<Node>, right: Box<Node> },
|
||||
|
||||
/// An if expression, which evaluates to either the then branch or the else branch.
|
||||
If {
|
||||
condition: Box<Node>,
|
||||
then_branch: Box<Node>,
|
||||
else_branch: Option<Box<Node>>,
|
||||
},
|
||||
FunctionDef {
|
||||
params: Vec<Node>,
|
||||
body: Box<Node>,
|
||||
},
|
||||
TypedVar {
|
||||
name: Token,
|
||||
type_: Token,
|
||||
},
|
||||
TypeDef {
|
||||
name: Token,
|
||||
fields: Vec<Node>,
|
||||
},
|
||||
|
||||
/// A loop expression, which evaluates to the last value of the loop.
|
||||
/// a loop can be exited with the break keyword.
|
||||
Loop { body: Box<Node> },
|
||||
|
||||
/// A function definition. ``` | param: type .. | -> ret_type { body }```
|
||||
FunctionDef { params: Vec<Node>, body: Box<Node> },
|
||||
|
||||
/// A typed variable definition: ```val: Type```
|
||||
TypedVar { name: Token, type_: Token },
|
||||
|
||||
/// A type definition, which is a list of fields. ```type MyType { field: Type }```
|
||||
TypeDef { name: Token, fields: Vec<Node> },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -126,16 +258,44 @@ pub enum CompileError {
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! expect_type {
|
||||
macro_rules! expect_tt {
|
||||
($token:expr, $($variant:ident),+) => {{
|
||||
match $token.tt() {
|
||||
let tt = $token.tt().to_string();
|
||||
|
||||
println!("CASE");
|
||||
println!("TOK {:?}", $token);
|
||||
println!("TT {}", tt);
|
||||
|
||||
let mut vs = String::new();
|
||||
$(
|
||||
let s = stringify!($variant);
|
||||
vs.push_str(s);
|
||||
vs.push_str("|");
|
||||
)+
|
||||
|
||||
match tt.as_str() {
|
||||
$(
|
||||
stringify!($variant) => Ok($token.clone()),
|
||||
)+
|
||||
_ => {
|
||||
// return an expected token error
|
||||
println!("EXPECTED!! {} [{}]", tt, vs);
|
||||
let expected = format!("[{}]", vec![$(stringify!($variant)),+].join(" | "));
|
||||
|
||||
Err(CompileError::ExpectedToken {
|
||||
expected,
|
||||
found: $token.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! expect_value {
|
||||
($token:expr, $variant:expr) => {{
|
||||
match $token {
|
||||
$variant(x) => Ok(x),
|
||||
_ => {
|
||||
let expected = format!("[{}]")
|
||||
Err(CompileError::ExpectedToken {
|
||||
expected,
|
||||
found: $token.clone(),
|
||||
|
||||
Reference in New Issue
Block a user