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;
|
use crate::lexer::Token;
|
||||||
|
|
||||||
pub struct Parser {
|
pub struct Parser {
|
||||||
@@ -10,7 +10,7 @@ pub struct Parser {
|
|||||||
impl Parser {
|
impl Parser {
|
||||||
pub fn new(tokens: Vec<Token>) -> Self {
|
pub fn new(tokens: Vec<Token>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ast: Node::Scope {
|
ast: Node::Block {
|
||||||
children: Vec::new(),
|
children: Vec::new(),
|
||||||
},
|
},
|
||||||
idx: 0,
|
idx: 0,
|
||||||
@@ -19,13 +19,17 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&mut self) -> Result<Node, CompileError> {
|
pub fn parse(&mut self) -> Result<Node, CompileError> {
|
||||||
|
self.parse_block()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_block(&mut self) -> Result<Node, CompileError> {
|
||||||
let mut statements = Vec::new();
|
let mut statements = Vec::new();
|
||||||
|
|
||||||
while let Some(_) = self.peek_next() {
|
while self.peek_next().is_ok() {
|
||||||
statements.push(self.parse_statement()?);
|
statements.push(self.parse_statement()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Node::Scope {
|
Ok(Node::Block {
|
||||||
children: statements,
|
children: statements,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -35,11 +39,11 @@ impl Parser {
|
|||||||
let left = if let Ok(typed_var) = self.parse_typed_var() {
|
let left = if let Ok(typed_var) = self.parse_typed_var() {
|
||||||
Box::new(typed_var)
|
Box::new(typed_var)
|
||||||
} else {
|
} else {
|
||||||
let tok = expect_type!(self.next()?, Identifier)?;
|
let tok = expect_tt!(self.next()?, Identifier)?;
|
||||||
Box::new(Node::Terminal { value: tok })
|
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()?);
|
let right = Box::new(self.parse_expression()?);
|
||||||
|
|
||||||
@@ -47,17 +51,144 @@ impl Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_typed_var(&mut self) -> Result<Node, CompileError> {
|
fn parse_typed_var(&mut self) -> Result<Node, CompileError> {
|
||||||
let name = expect_type!(self.next()?, Identifier)?;
|
let name = expect_tt!(self.next()?, Identifier)?;
|
||||||
let _ = expect_type!(self.next()?, Colon)?;
|
let _ = expect_tt!(self.next()?, Colon)?;
|
||||||
let type_ = expect_type!(self.next()?, Identifier)?;
|
let type_ = expect_tt!(self.next()?, Identifier)?;
|
||||||
|
|
||||||
Ok(Node::TypedVar { name, type_ })
|
Ok(Node::TypedVar { name, type_ })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expression(&mut self) -> Result<Node, CompileError> {
|
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)
|
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> {
|
fn next(&mut self) -> Result<Token, CompileError> {
|
||||||
if self.idx >= self.tokens.len() {
|
if self.idx >= self.tokens.len() {
|
||||||
return Err(CompileError::UnexpectedEOF);
|
return Err(CompileError::UnexpectedEOF);
|
||||||
@@ -69,53 +200,54 @@ impl Parser {
|
|||||||
Ok(token)
|
Ok(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn peek_next(&mut self) -> Option<Token> {
|
fn peek_next(&mut self) -> Result<Token, CompileError> {
|
||||||
if self.idx >= self.tokens.len() {
|
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)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Node {
|
pub enum Node {
|
||||||
Scope {
|
/// A scope, which is a list of child nodes that are evaluated in order.
|
||||||
children: Vec<Node>,
|
Block { children: Vec<Node> },
|
||||||
},
|
|
||||||
Terminal {
|
/// A leaf node with a value.
|
||||||
value: Token,
|
Terminal { value: Token },
|
||||||
},
|
|
||||||
UnaryOp {
|
/// A unary operator with a right operand.
|
||||||
op: Token,
|
UnaryOp { op: Token, right: Box<Node> },
|
||||||
right: Box<Node>,
|
|
||||||
},
|
/// A binary operator with a left and right operand.
|
||||||
BinaryOp {
|
BinaryOp {
|
||||||
left: Box<Node>,
|
left: Box<Node>,
|
||||||
op: Token,
|
op: Token,
|
||||||
right: Box<Node>,
|
right: Box<Node>,
|
||||||
},
|
},
|
||||||
Statement {
|
|
||||||
left: Box<Node>,
|
/// A statement, consisting of a value to assign to, and an expression.
|
||||||
right: Box<Node>,
|
Statement { left: Box<Node>, right: Box<Node> },
|
||||||
},
|
|
||||||
|
/// An if expression, which evaluates to either the then branch or the else branch.
|
||||||
If {
|
If {
|
||||||
condition: Box<Node>,
|
condition: Box<Node>,
|
||||||
then_branch: Box<Node>,
|
then_branch: Box<Node>,
|
||||||
else_branch: Option<Box<Node>>,
|
else_branch: Option<Box<Node>>,
|
||||||
},
|
},
|
||||||
FunctionDef {
|
|
||||||
params: Vec<Node>,
|
/// A loop expression, which evaluates to the last value of the loop.
|
||||||
body: Box<Node>,
|
/// a loop can be exited with the break keyword.
|
||||||
},
|
Loop { body: Box<Node> },
|
||||||
TypedVar {
|
|
||||||
name: Token,
|
/// A function definition. ``` | param: type .. | -> ret_type { body }```
|
||||||
type_: Token,
|
FunctionDef { params: Vec<Node>, body: Box<Node> },
|
||||||
},
|
|
||||||
TypeDef {
|
/// A typed variable definition: ```val: Type```
|
||||||
name: Token,
|
TypedVar { name: Token, type_: Token },
|
||||||
fields: Vec<Node>,
|
|
||||||
},
|
/// A type definition, which is a list of fields. ```type MyType { field: Type }```
|
||||||
|
TypeDef { name: Token, fields: Vec<Node> },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -126,16 +258,44 @@ pub enum CompileError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! expect_type {
|
macro_rules! expect_tt {
|
||||||
($token:expr, $($variant:ident),+) => {{
|
($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()),
|
stringify!($variant) => Ok($token.clone()),
|
||||||
)+
|
)+
|
||||||
_ => {
|
_ => {
|
||||||
// return an expected token error
|
println!("EXPECTED!! {} [{}]", tt, vs);
|
||||||
let expected = format!("[{}]", vec![$(stringify!($variant)),+].join(" | "));
|
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 {
|
Err(CompileError::ExpectedToken {
|
||||||
expected,
|
expected,
|
||||||
found: $token.clone(),
|
found: $token.clone(),
|
||||||
|
|||||||
Reference in New Issue
Block a user