Fixed unary minus
This commit is contained in:
Generated
+1
-1
@@ -3,5 +3,5 @@
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "tea"
|
||||
name = "matcha"
|
||||
version = "0.1.0"
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ fn get_value(v: Value, scopes: &mut [Scope]) -> Result<TeaValue, InterpreterErro
|
||||
match v {
|
||||
Value::Lit(t) => Ok(t),
|
||||
Value::Id(s) => {
|
||||
match scopes.iter().rev().skip_while(|scope| !scope.contains_key(&s)).next() {
|
||||
match scopes.iter().rev().find(|scope| scope.contains_key(&s)) {
|
||||
None => Err(InterpreterError::new("undefined variable")),
|
||||
Some(scope) => match scope.get(&s).unwrap() {
|
||||
VarType::Const(t) => Ok(t.clone()),
|
||||
|
||||
@@ -67,6 +67,7 @@ pub fn lex_tokens(s: &str) -> Result<Vec<Token>, (Vec<Token>, &str)> {
|
||||
let mut tokens: Vec<Token> = vec![];
|
||||
loop {
|
||||
if input.is_empty() {
|
||||
println!("tokens: {tokens:?}\n\n");
|
||||
return Ok(tokens);
|
||||
}
|
||||
try_parse!(parse_literal(input), tokens, input);
|
||||
|
||||
@@ -6,6 +6,8 @@ pub enum Symbol {
|
||||
Semicolon,
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
OpenParen,
|
||||
CloseParen,
|
||||
}
|
||||
|
||||
pub fn parse_symbol(input: &str) -> Option<(Token, &str)> {
|
||||
@@ -16,6 +18,8 @@ pub fn parse_symbol(input: &str) -> Option<(Token, &str)> {
|
||||
';' => Some((Token::Sym(Symbol::Semicolon), input)),
|
||||
'{' => Some((Token::Sym(Symbol::OpenBrace), input)),
|
||||
'}' => Some((Token::Sym(Symbol::CloseBrace), input)),
|
||||
'(' => Some((Token::Sym(Symbol::OpenParen), input)),
|
||||
')' => Some((Token::Sym(Symbol::CloseParen), input)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
+53
-10
@@ -71,13 +71,29 @@ fn next_expr_end(tokens: &[Token]) -> usize {
|
||||
|
||||
fn next_block_end(tokens: &[Token]) -> Result<usize, ParseError> {
|
||||
let mut index = 0;
|
||||
let mut block_count = 0usize;
|
||||
loop {
|
||||
let token = tokens.get(index);
|
||||
if token.is_none() {
|
||||
return Err(ParseError::new("} expected"));
|
||||
match tokens.get(index) {
|
||||
Some(Token::Sym(Symbol::OpenBrace)) => block_count += 1,
|
||||
Some(Token::Sym(Symbol::CloseBrace)) if block_count == 0 => return Ok(index),
|
||||
Some(Token::Sym(Symbol::CloseBrace)) => block_count -= 1,
|
||||
None => return Err(ParseError::new("mismatched {")),
|
||||
_ => (),
|
||||
}
|
||||
if matches!(token, Some(Token::Sym(Symbol::CloseBrace))) {
|
||||
return Ok(index);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn next_paren_end(tokens: &[Token]) -> Result<usize, ParseError> {
|
||||
let mut index = 0;
|
||||
let mut paren_count = 0usize;
|
||||
loop {
|
||||
match tokens.get(index) {
|
||||
Some(Token::Sym(Symbol::OpenParen)) => paren_count += 1,
|
||||
Some(Token::Sym(Symbol::CloseParen)) if paren_count == 0 => return Ok(index),
|
||||
Some(Token::Sym(Symbol::CloseParen)) => paren_count -= 1,
|
||||
None => return Err(ParseError::new("mismatched (")),
|
||||
_ => (),
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
@@ -87,26 +103,30 @@ fn parse_expr(tokens: &[Token]) -> Result<(Vec<ASTNode>, usize), ParseError> {
|
||||
let mut ast = vec![];
|
||||
let mut index = 0;
|
||||
let mut op_stack: Vec<Operator> = vec![];
|
||||
let mut unary_negate = false;
|
||||
loop {
|
||||
match tokens.get(index) {
|
||||
None => {
|
||||
while !op_stack.is_empty() {
|
||||
ast.push(ASTNode::BinOp(op_stack.pop().unwrap()));
|
||||
}
|
||||
return Ok((ast, index));
|
||||
if unary_negate && !matches!(tokens.get(index), Some(Token::Sym(Symbol::Semicolon))) {
|
||||
ast.push(ASTNode::UnaryMinus);
|
||||
}
|
||||
return Ok((ast, index));
|
||||
},
|
||||
Some(Token::Lit(v)) => ast.push(ASTNode::Val(Value::Lit(v.clone()))),
|
||||
Some(Token::Id(v)) => ast.push(ASTNode::Val(Value::Id(v.clone()))),
|
||||
Some(Token::Kw(Keyword::Let)) => {
|
||||
let id = match_or_return!(tokens.get(index + 1), Token::Id(a), a, ParseError::new("identifier expected after 'let' keyword"));
|
||||
match_or_return!(tokens.get(index + 2), Token::Sym(Symbol::EqualSign), (), ParseError::new("= expected after identifier"));
|
||||
let tokens = &tokens[(3 + index)..];
|
||||
let next_end = next_expr_end(tokens);
|
||||
let (mut expr, count) = parse_expr(&tokens[..next_end])?;
|
||||
let stokens = &tokens[(3 + index)..];
|
||||
let next_end = next_expr_end(stokens);
|
||||
let (mut expr, count) = parse_expr(&stokens[..next_end])?;
|
||||
ast.push(ASTNode::Val(Value::Id(id.to_owned())));
|
||||
ast.append(&mut expr);
|
||||
ast.push(ASTNode::ConstDecl);
|
||||
index += count + 3; // 4 + count - 1
|
||||
index += count + 2;// 4 + count - 1
|
||||
},
|
||||
Some(Token::Kw(Keyword::Fn)) => {
|
||||
/*let id = match_or_return!(tokens.get(index + 1), Token::Id(a), a, ParseError::new("identifier expected after 'let' keyword"));
|
||||
@@ -130,13 +150,36 @@ fn parse_expr(tokens: &[Token]) -> Result<(Vec<ASTNode>, usize), ParseError> {
|
||||
Some(Token::Sym(Symbol::CloseBrace)) => {
|
||||
return Err(ParseError::new("unexpected }"));
|
||||
},
|
||||
Some(Token::Sym(Symbol::OpenParen)) => {
|
||||
let end = next_paren_end(&tokens[(index + 1)..])?;
|
||||
let (expr, count) = parse_expr(&tokens[(index + 1)..(index + end + 1)])?;
|
||||
ast.push(ASTNode::Block(expr));
|
||||
index += count + 1;
|
||||
},
|
||||
Some(Token::Sym(Symbol::CloseParen)) => {
|
||||
return Err(ParseError::new("unexpected )"));
|
||||
},
|
||||
Some(Token::Sym(Symbol::Semicolon)) => {
|
||||
while !op_stack.is_empty() {
|
||||
ast.push(ASTNode::BinOp(op_stack.pop().unwrap()));
|
||||
}
|
||||
// I'll macro this later
|
||||
if unary_negate && !matches!(tokens.get(index), Some(Token::Sym(Symbol::Semicolon))) {
|
||||
ast.push(ASTNode::UnaryMinus);
|
||||
unary_negate = false;
|
||||
}
|
||||
ast.push(ASTNode::StatementEnd);
|
||||
},
|
||||
Some(Token::Op(op)) => {
|
||||
if (matches!(ast.last(), Some(ASTNode::StatementEnd) | None) || !op_stack.is_empty()) && matches!(op, Operator::Minus) {
|
||||
unary_negate = true;
|
||||
index += 1;
|
||||
continue;
|
||||
}
|
||||
if unary_negate && !matches!(tokens.get(index), Some(Token::Sym(Symbol::Semicolon))) {
|
||||
ast.push(ASTNode::UnaryMinus);
|
||||
unary_negate = false;
|
||||
}
|
||||
match op_stack.last() {
|
||||
None => op_stack.push(op.clone()),
|
||||
Some(last_op) if last_op.get_precedence() < op.get_precedence() => {
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
|
||||
let x = 5;
|
||||
let y = {
|
||||
let x = 1;
|
||||
x + 1
|
||||
let x = -x;
|
||||
x + 1 * -x
|
||||
};
|
||||
x + y
|
||||
|
||||
|
||||
Reference in New Issue
Block a user