Basic expression parsing
This commit is contained in:
parent
49b3634228
commit
63943687e3
184
src/parse.rs
184
src/parse.rs
|
@ -49,7 +49,7 @@ pub enum Definition<'a> {
|
|||
|
||||
impl<'a> Definition<'a> {
|
||||
pub fn build_structure(lexer: &mut Lexer<'a>) -> Self {
|
||||
let name = lexer.eat_id().unwrap();
|
||||
let name = lexer.eat_expect_id();
|
||||
lexer.eat_expect(Token::BraceOpen);
|
||||
|
||||
let mut members = Vec::new();
|
||||
|
@ -57,7 +57,7 @@ impl<'a> Definition<'a> {
|
|||
loop {
|
||||
match lexer.eat_id() {
|
||||
Ok(member_type) => {
|
||||
let member_name = lexer.eat_id().unwrap();
|
||||
let member_name = lexer.eat_expect_id();
|
||||
members.push(StructMember {
|
||||
type_name: member_type,
|
||||
name: member_name,
|
||||
|
@ -81,7 +81,7 @@ impl<'a> Definition<'a> {
|
|||
loop {
|
||||
match lexer.eat_id() {
|
||||
Ok(member_type) => {
|
||||
let member_name = lexer.eat_id().unwrap();
|
||||
let member_name = lexer.eat_expect_id();
|
||||
args.push(FunctionArg {
|
||||
type_name: member_type,
|
||||
name: member_name,
|
||||
|
@ -140,7 +140,7 @@ impl<'a> FunctionSignature<'a> {
|
|||
loop {
|
||||
match lexer.eat_id() {
|
||||
Ok(member_type) => {
|
||||
let member_name = lexer.eat_id().unwrap();
|
||||
let member_name = lexer.eat_expect_id();
|
||||
args.push(FunctionArg {
|
||||
type_name: member_type,
|
||||
name: member_name,
|
||||
|
@ -176,25 +176,52 @@ pub struct FunctionBody<'a> {
|
|||
|
||||
impl<'a> FunctionBody<'a> {
|
||||
pub fn build(lexer: &mut Lexer<'a>) -> Self {
|
||||
let mut level = 1;
|
||||
while level > 0 {
|
||||
match lexer.next().unwrap() {
|
||||
Token::BraceOpen => level += 1,
|
||||
Token::BraceClose => level -= 1,
|
||||
_ => {}
|
||||
let mut statements = Vec::new();
|
||||
|
||||
let mut tail = Some(Token::Semicolon);
|
||||
loop {
|
||||
match tail {
|
||||
Some(Token::Semicolon) => match lexer.next().unwrap() {
|
||||
Token::Let => {
|
||||
let (statement, next) = Statement::build_let(lexer);
|
||||
statements.push(statement);
|
||||
tail = Some(next);
|
||||
}
|
||||
Token::Var => {
|
||||
let (statement, next) = Statement::build_var(lexer);
|
||||
statements.push(statement);
|
||||
tail = Some(next);
|
||||
}
|
||||
Token::Identifier => {
|
||||
let var = lexer.slice();
|
||||
let (expr, next) = Statement::eat_assign(lexer);
|
||||
statements.push(Statement::Assign { var, expr });
|
||||
tail = Some(next);
|
||||
}
|
||||
Token::BraceClose => break,
|
||||
_ => lexer.panic_message("Expected var, let, or assign"),
|
||||
},
|
||||
Some(Token::BraceClose) => break,
|
||||
_ => lexer.panic_message("Unexpected token"),
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
statements: Vec::new(),
|
||||
statements,
|
||||
tail_expression: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ExpressionPair<'a> = Box<(Expression<'a>, Expression<'a>)>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Expression<'a> {
|
||||
Arithmetic(&'a str),
|
||||
BinaryOp(BinaryOp, ExpressionPair<'a>),
|
||||
Literal(Literal<'a>),
|
||||
Local(&'a str),
|
||||
Member(&'a str),
|
||||
FuncCall(&'a str, Vec<Expression<'a>>),
|
||||
If {
|
||||
test_expr: Box<Expression<'a>>,
|
||||
then_body: BranchBody<'a>,
|
||||
|
@ -202,6 +229,78 @@ pub enum Expression<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'a> Expression<'a> {
|
||||
pub fn build(lexer: &mut Lexer<'a>) -> (Option<Self>, Token) {
|
||||
let tok = lexer.next().unwrap();
|
||||
let lhs = match tok {
|
||||
Token::Identifier => Self::Local(lexer.slice()),
|
||||
Token::Dot => Self::Member(lexer.eat_expect_id()),
|
||||
Token::Semicolon | Token::BraceClose | Token::ParanClose => return (None, tok),
|
||||
_ => lexer.panic_message("Unexpected token"),
|
||||
};
|
||||
|
||||
let (rhs, next) = Self::eat_op(lexer);
|
||||
if let Some((op, rhs)) = rhs {
|
||||
(Some(Self::BinaryOp(op, Box::new((lhs, rhs)))), next)
|
||||
} else {
|
||||
(Some(lhs), next)
|
||||
}
|
||||
}
|
||||
|
||||
fn eat_op(lexer: &mut Lexer<'a>) -> (Option<(BinaryOp, Self)>, Token) {
|
||||
let tok = lexer.next().unwrap();
|
||||
if let Some(op) = BinaryOp::from_token(tok) {
|
||||
match Self::build(lexer) {
|
||||
(Some(rhs), tail) => (Some((op, rhs)), tail),
|
||||
_ => lexer.panic_message("Expected right-hand expression"),
|
||||
}
|
||||
} else {
|
||||
(None, tok)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BinaryOp {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Less,
|
||||
LessEq,
|
||||
Greater,
|
||||
GreaterEq,
|
||||
Eq,
|
||||
Neq,
|
||||
}
|
||||
|
||||
impl BinaryOp {
|
||||
pub fn from_token(tok: Token) -> Option<Self> {
|
||||
use BinaryOp::*;
|
||||
use Token::*;
|
||||
match tok {
|
||||
OpAdd => Some(Add),
|
||||
OpSub => Some(Sub),
|
||||
OpMul => Some(Mul),
|
||||
OpDiv => Some(Div),
|
||||
OpLess => Some(Less),
|
||||
OpLessEq => Some(LessEq),
|
||||
OpGreater => Some(Greater),
|
||||
OpGreaterEq => Some(GreaterEq),
|
||||
OpEq => Some(Eq),
|
||||
OpNeq => Some(Neq),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Literal<'a> {
|
||||
BinaryInteger(&'a str),
|
||||
OctalInteger(&'a str),
|
||||
DecimalInteger(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Statement<'a> {
|
||||
Assign {
|
||||
|
@ -223,6 +322,26 @@ pub enum Statement<'a> {
|
|||
},
|
||||
}
|
||||
|
||||
impl<'a> Statement<'a> {
|
||||
pub fn eat_assign(lexer: &mut Lexer<'a>) -> (Expression<'a>, Token) {
|
||||
lexer.eat_expect(Token::OpAssign);
|
||||
let (expr, tail) = Expression::build(lexer);
|
||||
(expr.unwrap(), tail)
|
||||
}
|
||||
|
||||
pub fn build_let(lexer: &mut Lexer<'a>) -> (Self, Token) {
|
||||
let var = lexer.eat_expect_id();
|
||||
let (expr, tail) = Self::eat_assign(lexer);
|
||||
(Self::Let { var, expr }, tail)
|
||||
}
|
||||
|
||||
pub fn build_var(lexer: &mut Lexer<'a>) -> (Self, Token) {
|
||||
let var = lexer.eat_expect_id();
|
||||
let (expr, tail) = Self::eat_assign(lexer);
|
||||
(Self::Var { var, expr }, tail)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BranchBody<'a> {
|
||||
pub statements: Vec<Statement<'a>>,
|
||||
|
@ -244,6 +363,11 @@ mod tests {
|
|||
parse(include_str!("test/function.fae"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tail_expression() {
|
||||
parse("fn add(i32 x, i32 y) i32 { x + y }");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn structure() {
|
||||
parse(include_str!("test/structure.fae"));
|
||||
|
@ -253,4 +377,40 @@ mod tests {
|
|||
fn example() {
|
||||
parse(include_str!("test/example.fae"));
|
||||
}
|
||||
|
||||
mod expr {
|
||||
use super::*;
|
||||
|
||||
fn parse_expr(source: &str) {
|
||||
let mut lex = Lexer::new(source);
|
||||
let expr = Expression::build(&mut lex);
|
||||
println!("{:#?}", expr);
|
||||
assert_eq!(expr.1, Token::Semicolon);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn locals() {
|
||||
parse_expr("local1 + local2 - local3;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn members() {
|
||||
parse_expr(".member1 * .member2;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn func_call() {
|
||||
parse_expr("func_call();");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn method() {
|
||||
parse_expr(".method();");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn submembers() {
|
||||
parse_expr(".member.submember1 / .member.submember2.submember3;");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
fn free_floating(i32 arg1, i32 arg2) ReturnType {}
|
||||
fn free_floating(i32 arg1, i32 arg2) ReturnType {
|
||||
let local_var = arg1 + arg2;
|
||||
}
|
||||
|
||||
// associated function for the World struct
|
||||
World fn set_next(i32 i, i32 j) {
|
||||
|
|
Loading…
Reference in New Issue