Basic expression parsing

This commit is contained in:
mars 2022-02-28 19:58:34 -07:00
parent 49b3634228
commit 63943687e3
2 changed files with 175 additions and 13 deletions

View File

@ -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;");
}
}
}

View File

@ -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) {