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> {
|
impl<'a> Definition<'a> {
|
||||||
pub fn build_structure(lexer: &mut Lexer<'a>) -> Self {
|
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);
|
lexer.eat_expect(Token::BraceOpen);
|
||||||
|
|
||||||
let mut members = Vec::new();
|
let mut members = Vec::new();
|
||||||
|
@ -57,7 +57,7 @@ impl<'a> Definition<'a> {
|
||||||
loop {
|
loop {
|
||||||
match lexer.eat_id() {
|
match lexer.eat_id() {
|
||||||
Ok(member_type) => {
|
Ok(member_type) => {
|
||||||
let member_name = lexer.eat_id().unwrap();
|
let member_name = lexer.eat_expect_id();
|
||||||
members.push(StructMember {
|
members.push(StructMember {
|
||||||
type_name: member_type,
|
type_name: member_type,
|
||||||
name: member_name,
|
name: member_name,
|
||||||
|
@ -81,7 +81,7 @@ impl<'a> Definition<'a> {
|
||||||
loop {
|
loop {
|
||||||
match lexer.eat_id() {
|
match lexer.eat_id() {
|
||||||
Ok(member_type) => {
|
Ok(member_type) => {
|
||||||
let member_name = lexer.eat_id().unwrap();
|
let member_name = lexer.eat_expect_id();
|
||||||
args.push(FunctionArg {
|
args.push(FunctionArg {
|
||||||
type_name: member_type,
|
type_name: member_type,
|
||||||
name: member_name,
|
name: member_name,
|
||||||
|
@ -140,7 +140,7 @@ impl<'a> FunctionSignature<'a> {
|
||||||
loop {
|
loop {
|
||||||
match lexer.eat_id() {
|
match lexer.eat_id() {
|
||||||
Ok(member_type) => {
|
Ok(member_type) => {
|
||||||
let member_name = lexer.eat_id().unwrap();
|
let member_name = lexer.eat_expect_id();
|
||||||
args.push(FunctionArg {
|
args.push(FunctionArg {
|
||||||
type_name: member_type,
|
type_name: member_type,
|
||||||
name: member_name,
|
name: member_name,
|
||||||
|
@ -176,25 +176,52 @@ pub struct FunctionBody<'a> {
|
||||||
|
|
||||||
impl<'a> FunctionBody<'a> {
|
impl<'a> FunctionBody<'a> {
|
||||||
pub fn build(lexer: &mut Lexer<'a>) -> Self {
|
pub fn build(lexer: &mut Lexer<'a>) -> Self {
|
||||||
let mut level = 1;
|
let mut statements = Vec::new();
|
||||||
while level > 0 {
|
|
||||||
match lexer.next().unwrap() {
|
let mut tail = Some(Token::Semicolon);
|
||||||
Token::BraceOpen => level += 1,
|
loop {
|
||||||
Token::BraceClose => level -= 1,
|
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 {
|
Self {
|
||||||
statements: Vec::new(),
|
statements,
|
||||||
tail_expression: None,
|
tail_expression: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ExpressionPair<'a> = Box<(Expression<'a>, Expression<'a>)>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Expression<'a> {
|
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 {
|
If {
|
||||||
test_expr: Box<Expression<'a>>,
|
test_expr: Box<Expression<'a>>,
|
||||||
then_body: BranchBody<'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)]
|
#[derive(Debug)]
|
||||||
pub enum Statement<'a> {
|
pub enum Statement<'a> {
|
||||||
Assign {
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct BranchBody<'a> {
|
pub struct BranchBody<'a> {
|
||||||
pub statements: Vec<Statement<'a>>,
|
pub statements: Vec<Statement<'a>>,
|
||||||
|
@ -244,6 +363,11 @@ mod tests {
|
||||||
parse(include_str!("test/function.fae"));
|
parse(include_str!("test/function.fae"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn tail_expression() {
|
||||||
|
parse("fn add(i32 x, i32 y) i32 { x + y }");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn structure() {
|
fn structure() {
|
||||||
parse(include_str!("test/structure.fae"));
|
parse(include_str!("test/structure.fae"));
|
||||||
|
@ -253,4 +377,40 @@ mod tests {
|
||||||
fn example() {
|
fn example() {
|
||||||
parse(include_str!("test/example.fae"));
|
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
|
// associated function for the World struct
|
||||||
World fn set_next(i32 i, i32 j) {
|
World fn set_next(i32 i, i32 j) {
|
||||||
|
|
Loading…
Reference in New Issue