fixup parsing
This commit is contained in:
parent
5d563527fd
commit
21857307d7
@ -1,11 +1,12 @@
|
|||||||
|
|
||||||
|
|
||||||
fn b() {
|
fn b() {
|
||||||
a();
|
a()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn a() {
|
fn a() {
|
||||||
|
let abc = 123;
|
||||||
|
abc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
101
src/ast.rs
Normal file
101
src/ast.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use crate::pos::Pos;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct Stmt {
|
||||||
|
pub kind: StmtKind,
|
||||||
|
pub pos: Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stmt {
|
||||||
|
pub fn new(kind: StmtKind, pos: Pos) -> Self {
|
||||||
|
Self { kind, pos }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub enum StmtKind {
|
||||||
|
Error,
|
||||||
|
Let {
|
||||||
|
subject: Box<Param>,
|
||||||
|
value: Box<Expr>,
|
||||||
|
},
|
||||||
|
Fn {
|
||||||
|
subject: Box<Expr>,
|
||||||
|
params: Vec<Param>,
|
||||||
|
return_typ: Option<Box<Typ>>,
|
||||||
|
body: Box<Expr>,
|
||||||
|
},
|
||||||
|
Return {
|
||||||
|
expr: Option<Box<Expr>>,
|
||||||
|
},
|
||||||
|
Break {
|
||||||
|
expr: Option<Box<Expr>>,
|
||||||
|
},
|
||||||
|
Assign {
|
||||||
|
subject: Box<Expr>,
|
||||||
|
value: Box<Expr>,
|
||||||
|
},
|
||||||
|
Expr(Box<Expr>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct Expr {
|
||||||
|
pub kind: ExprKind,
|
||||||
|
pub pos: Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Expr {
|
||||||
|
pub fn new(kind: ExprKind, pos: Pos) -> Self {
|
||||||
|
Self { kind, pos }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub enum ExprKind {
|
||||||
|
Error,
|
||||||
|
Ident(u64),
|
||||||
|
Int(i64),
|
||||||
|
Str(String),
|
||||||
|
Group(Box<Expr>),
|
||||||
|
Block {
|
||||||
|
stmts: Vec<Stmt>,
|
||||||
|
expr: Option<Box<Expr>>,
|
||||||
|
},
|
||||||
|
Call {
|
||||||
|
subject: Box<Expr>,
|
||||||
|
args: Vec<Expr>,
|
||||||
|
},
|
||||||
|
If {
|
||||||
|
cond: Box<Expr>,
|
||||||
|
truthy: Box<Expr>,
|
||||||
|
falsy: Option<Box<Expr>>,
|
||||||
|
},
|
||||||
|
Loop {
|
||||||
|
body: Box<Expr>,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct Typ {
|
||||||
|
pub kind: TypKind,
|
||||||
|
pub pos: Pos,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Typ {
|
||||||
|
pub fn new(kind: TypKind, pos: Pos) -> Self {
|
||||||
|
Self { kind, pos }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub enum TypKind {
|
||||||
|
Error,
|
||||||
|
Ident(u64),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
|
pub struct Param {
|
||||||
|
pub subject: Box<Expr>,
|
||||||
|
pub typ: Option<Box<Typ>>,
|
||||||
|
pub pos: Pos,
|
||||||
|
}
|
11
src/lexer.rs
11
src/lexer.rs
@ -1,7 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
pos::{Error, ErrorAcc, Pos},
|
pos::{Error, ErrorAcc, Pos},
|
||||||
token::{Token, TokenKind, TokenValue},
|
token::{Token, TokenKind, TokenValue},
|
||||||
util::hash,
|
|
||||||
};
|
};
|
||||||
use std::{collections::HashMap, rc::Rc, str::Chars, sync::Mutex};
|
use std::{collections::HashMap, rc::Rc, str::Chars, sync::Mutex};
|
||||||
|
|
||||||
@ -72,9 +71,13 @@ impl<'a> Lexer<'a> {
|
|||||||
if let Some(kind) = self.keywords.get(&value) {
|
if let Some(kind) = self.keywords.get(&value) {
|
||||||
return self.token(kind.clone(), pos);
|
return self.token(kind.clone(), pos);
|
||||||
}
|
}
|
||||||
let id = hash(&value);
|
let id = self.symbols.len() as u64;
|
||||||
self.symbols.insert(id, value);
|
self.symbols.insert(id, value);
|
||||||
break self.token_with_value(TokenKind::Id, TokenValue::Id(id), pos);
|
break self.token_with_value(
|
||||||
|
TokenKind::Ident,
|
||||||
|
TokenValue::Ident(id),
|
||||||
|
pos,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -242,7 +245,7 @@ impl<'a> Lexer<'a> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> Pos {
|
pub fn pos(&self) -> Pos {
|
||||||
Pos {
|
Pos {
|
||||||
index: self.index,
|
index: self.index,
|
||||||
line: self.line,
|
line: self.line,
|
||||||
|
34
src/main.rs
34
src/main.rs
@ -1,13 +1,39 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
use std::{rc::Rc, sync::Mutex};
|
||||||
|
|
||||||
|
use parser::Parser;
|
||||||
|
use pos::{ErrorAcc, Pos};
|
||||||
|
|
||||||
|
mod ast;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod parsed;
|
|
||||||
mod parser;
|
mod parser;
|
||||||
mod pos;
|
mod pos;
|
||||||
mod sym;
|
|
||||||
mod token;
|
mod token;
|
||||||
mod util;
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("Hello, world!");
|
let args = std::env::args().collect::<Vec<_>>();
|
||||||
|
let filename = args[1].clone();
|
||||||
|
let text = std::fs::read_to_string(filename).unwrap();
|
||||||
|
|
||||||
|
let error_acc = Rc::new(Mutex::new(ErrorAcc::new()));
|
||||||
|
|
||||||
|
let mut parser = Parser::new(&text, error_acc.clone());
|
||||||
|
|
||||||
|
let ast = parser.parse();
|
||||||
|
|
||||||
|
println!("{ast:#?}");
|
||||||
|
|
||||||
|
let error_acc = error_acc.lock().unwrap();
|
||||||
|
if !error_acc.ok() {
|
||||||
|
println!("Compilation failed");
|
||||||
|
for error in error_acc.iter() {
|
||||||
|
match error.pos {
|
||||||
|
Some(Pos { line, col, .. }) => {
|
||||||
|
println!("{:?} at {line}:{col}: {}", error.kind, error.msg)
|
||||||
|
}
|
||||||
|
None => println!("{:?}: {}", error.kind, error.msg),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
use crate::pos::Pos;
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
pub struct Node {
|
|
||||||
pub kind: NodeKind,
|
|
||||||
pub pos: Pos,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Node {
|
|
||||||
pub fn new(kind: NodeKind, pos: Pos) -> Self {
|
|
||||||
Self { kind, pos }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Debug)]
|
|
||||||
pub enum NodeKind {
|
|
||||||
Error,
|
|
||||||
Id(u64),
|
|
||||||
Int(i64),
|
|
||||||
Str(String),
|
|
||||||
Group(Box<Node>),
|
|
||||||
Block(Vec<Node>),
|
|
||||||
Call {
|
|
||||||
subject: Box<Node>,
|
|
||||||
args: Vec<Node>,
|
|
||||||
},
|
|
||||||
If {
|
|
||||||
cond: Box<Node>,
|
|
||||||
truthy: Box<Node>,
|
|
||||||
falsy: Option<Box<Node>>,
|
|
||||||
},
|
|
||||||
Loop {
|
|
||||||
body: Box<Node>,
|
|
||||||
},
|
|
||||||
Break,
|
|
||||||
Assign {
|
|
||||||
subject: Box<Node>,
|
|
||||||
value: Box<Node>,
|
|
||||||
},
|
|
||||||
Let {
|
|
||||||
subject: Box<Node>,
|
|
||||||
value: Box<Node>,
|
|
||||||
},
|
|
||||||
Fn {
|
|
||||||
subject: Box<Node>,
|
|
||||||
params: Vec<Node>,
|
|
||||||
return_typ: Box<Node>,
|
|
||||||
body: Box<Node>,
|
|
||||||
},
|
|
||||||
Return {
|
|
||||||
value: Option<Box<Node>>,
|
|
||||||
},
|
|
||||||
Param {
|
|
||||||
subject: Box<Node>,
|
|
||||||
typ: Option<Box<Node>>,
|
|
||||||
},
|
|
||||||
}
|
|
443
src/parser.rs
443
src/parser.rs
@ -1,10 +1,10 @@
|
|||||||
use std::{collections::HashMap, rc::Rc, sync::Mutex};
|
use std::{collections::HashMap, rc::Rc, sync::Mutex};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
ast::{Expr, ExprKind as EK, Param, Stmt, StmtKind as SK, Typ, TypKind},
|
||||||
lexer::Lexer,
|
lexer::Lexer,
|
||||||
parsed::{Node, NodeKind},
|
|
||||||
pos::{Error, ErrorAcc, Pos},
|
pos::{Error, ErrorAcc, Pos},
|
||||||
token::{Token, TokenKind, TokenValue},
|
token::{Token, TokenKind as TK, TokenValue},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Parser<'a> {
|
pub struct Parser<'a> {
|
||||||
@ -24,7 +24,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(&mut self) -> Vec<Node> {
|
pub fn parse(&mut self) -> Vec<Stmt> {
|
||||||
self.parse_file()
|
self.parse_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ impl<'a> Parser<'a> {
|
|||||||
self.lexer.symbols()
|
self.lexer.symbols()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_file(&mut self) -> Vec<Node> {
|
fn parse_file(&mut self) -> Vec<Stmt> {
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
match self.current {
|
match self.current {
|
||||||
@ -42,73 +42,66 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_stmt(&mut self) -> Node {
|
fn parse_stmt(&mut self) -> Stmt {
|
||||||
let pos = self.pos().unwrap();
|
use TK::*;
|
||||||
|
let pos = self.pos();
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
Some(TokenKind::LBrace) => self.parse_block(),
|
Some(Fn) => self.parse_fn(),
|
||||||
Some(TokenKind::If) => self.parse_if(),
|
Some(kind @ (LBrace | If | Loop)) => Stmt::new(
|
||||||
Some(TokenKind::Loop) => self.parse_loop(),
|
SK::Expr(Box::new(match kind {
|
||||||
Some(TokenKind::Fn) => self.parse_fn(),
|
LBrace => self.parse_block(),
|
||||||
_ => {
|
If => self.parse_if(),
|
||||||
let stmt = match self.curr_kind() {
|
Loop => self.parse_loop(),
|
||||||
Some(TokenKind::Let) => self.parse_let(),
|
_ => unreachable!(),
|
||||||
Some(TokenKind::Break) => {
|
})),
|
||||||
self.step();
|
pos,
|
||||||
self.node(NodeKind::Break, pos.clone())
|
),
|
||||||
}
|
Some(kind) => {
|
||||||
Some(TokenKind::Return) => {
|
let stmt = match kind {
|
||||||
self.step();
|
Let => self.parse_let(),
|
||||||
let value = match self.curr_kind() {
|
Return => self.parse_return(),
|
||||||
Some(TokenKind::Semicolon) => None,
|
Break => self.parse_break(),
|
||||||
_ => Some(Box::new(self.parse_expr())),
|
_ => match self.parse_assign() {
|
||||||
};
|
ParsedAssign::Assign(stmt) => stmt,
|
||||||
self.node(NodeKind::Return { value }, pos.clone())
|
ParsedAssign::Expr(expr, pos) => Stmt::new(SK::Expr(Box::new(expr)), pos),
|
||||||
}
|
},
|
||||||
_ => self.parse_assign(),
|
|
||||||
};
|
};
|
||||||
match self.curr_kind() {
|
self.eat_semicolon();
|
||||||
Some(TokenKind::Semicolon) => {
|
stmt
|
||||||
self.step();
|
|
||||||
stmt
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
self.error("expected ';'", pos.clone());
|
|
||||||
self.error_node(pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fn(&mut self) -> Node {
|
fn parse_fn(&mut self) -> Stmt {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
if !self.curr_is(TokenKind::Id) {
|
if !self.curr_is(TK::Ident) {
|
||||||
self.error("expected id", pos.clone());
|
self.error("expected id", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_stmt(pos);
|
||||||
}
|
}
|
||||||
let subject = Box::new(self.parse_id());
|
let subject = Box::new(self.parse_ident_expr());
|
||||||
if !self.curr_is(TokenKind::LParen) {
|
if !self.curr_is(TK::LParen) {
|
||||||
self.error("expected '('", pos.clone());
|
self.error("expected '('", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_stmt(pos);
|
||||||
}
|
}
|
||||||
let params = match self.parse_fn_params() {
|
let params = match self.parse_fn_params() {
|
||||||
Ok(params) => params,
|
Ok(params) => params,
|
||||||
Err(expr) => return expr,
|
Err(pos) => return self.error_stmt(pos),
|
||||||
};
|
};
|
||||||
if !self.curr_is(TokenKind::MinusLt) {
|
let return_typ = if self.curr_is(TK::MinusLt) {
|
||||||
self.error("expected '->'", pos.clone());
|
self.step();
|
||||||
return self.error_node(pos);
|
Some(Box::new(self.parse_typ()))
|
||||||
}
|
} else {
|
||||||
self.step();
|
None
|
||||||
let return_typ = Box::new(self.parse_typ());
|
};
|
||||||
if !self.curr_is(TokenKind::LBrace) {
|
if !self.curr_is(TK::LBrace) {
|
||||||
self.error("expected '{'", pos.clone());
|
self.error("expected '{'", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_stmt(pos);
|
||||||
}
|
}
|
||||||
let body = Box::new(self.parse_block());
|
let body = Box::new(self.parse_block());
|
||||||
self.node(
|
Stmt::new(
|
||||||
NodeKind::Fn {
|
SK::Fn {
|
||||||
subject,
|
subject,
|
||||||
params,
|
params,
|
||||||
return_typ,
|
return_typ,
|
||||||
@ -118,49 +111,49 @@ impl<'a> Parser<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fn_params(&mut self) -> Result<Vec<Node>, Node> {
|
fn parse_fn_params(&mut self) -> Result<Vec<Param>, Pos> {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
if !self.curr_is(TokenKind::RParen) {
|
if !self.curr_is(TK::RParen) {
|
||||||
if !self.curr_is(TokenKind::Id) {
|
if !self.curr_is(TK::Ident) {
|
||||||
self.error("expected id", pos.clone());
|
self.error("expected id", pos.clone());
|
||||||
return Err(self.error_node(pos));
|
return Err(pos);
|
||||||
}
|
}
|
||||||
params.push(self.parse_param());
|
params.push(self.parse_param());
|
||||||
while let Some(TokenKind::Comma) = self.curr_kind() {
|
while let Some(TK::Comma) = self.curr_kind() {
|
||||||
self.step();
|
self.step();
|
||||||
if self.curr_is(TokenKind::RParen) {
|
if self.curr_is(TK::RParen) {
|
||||||
self.error("expected ')'", pos.clone());
|
self.error("expected ')'", pos.clone());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
params.push(self.parse_param());
|
params.push(self.parse_param());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.curr_is(TokenKind::RParen) {
|
if !self.curr_is(TK::RParen) {
|
||||||
self.error("expected ')'", pos.clone());
|
self.error("expected ')'", pos.clone());
|
||||||
return Err(self.error_node(pos));
|
return Err(pos);
|
||||||
}
|
}
|
||||||
self.step();
|
self.step();
|
||||||
Ok(params)
|
Ok(params)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_let(&mut self) -> Node {
|
fn parse_let(&mut self) -> Stmt {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
if !self.curr_is(TokenKind::Id) {
|
if !self.curr_is(TK::Ident) {
|
||||||
self.error("expected id", pos.clone());
|
self.error("expected id", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_stmt(pos);
|
||||||
}
|
}
|
||||||
let subject = self.parse_param();
|
let subject = self.parse_param();
|
||||||
if !self.curr_is(TokenKind::Equal) {
|
if !self.curr_is(TK::Equal) {
|
||||||
self.error("expected '='", pos.clone());
|
self.error("expected '='", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_stmt(pos);
|
||||||
}
|
}
|
||||||
self.step();
|
self.step();
|
||||||
let value = self.parse_expr();
|
let value = self.parse_expr();
|
||||||
self.node(
|
Stmt::new(
|
||||||
NodeKind::Let {
|
SK::Let {
|
||||||
subject: Box::new(subject),
|
subject: Box::new(subject),
|
||||||
value: Box::new(value),
|
value: Box::new(value),
|
||||||
},
|
},
|
||||||
@ -168,68 +161,64 @@ impl<'a> Parser<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_param(&mut self) -> Node {
|
fn parse_return(&mut self) -> Stmt {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
let subject = Box::new(self.parse_id());
|
self.step();
|
||||||
let typ = if let Some(TokenKind::Colon) = self.curr_kind() {
|
let expr = match self.curr_kind() {
|
||||||
self.step();
|
Some(TK::Semicolon) => None,
|
||||||
Some(Box::new(self.parse_typ()))
|
_ => Some(Box::new(self.parse_expr())),
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
};
|
||||||
self.node(NodeKind::Param { subject, typ }, pos)
|
Stmt::new(SK::Return { expr }, pos.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_typ(&mut self) -> Node {
|
fn parse_break(&mut self) -> Stmt {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
match self.curr_kind() {
|
self.step();
|
||||||
Some(TokenKind::Id) => self.parse_id(),
|
let expr = match self.curr_kind() {
|
||||||
_ => {
|
Some(TK::Semicolon) => None,
|
||||||
self.error("expected type", pos.clone());
|
_ => Some(Box::new(self.parse_expr())),
|
||||||
self.step();
|
};
|
||||||
self.error_node(pos)
|
Stmt::new(SK::Break { expr }, pos.clone())
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_assign(&mut self) -> Node {
|
fn parse_assign(&mut self) -> ParsedAssign {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
let subject = self.parse_expr();
|
let subject = self.parse_expr();
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
Some(TokenKind::Equal) => {
|
Some(TK::Equal) => {
|
||||||
self.step();
|
self.step();
|
||||||
let value = self.parse_expr();
|
let value = self.parse_expr();
|
||||||
self.node(
|
ParsedAssign::Assign(Stmt::new(
|
||||||
NodeKind::Assign {
|
SK::Assign {
|
||||||
subject: Box::new(subject),
|
subject: Box::new(subject),
|
||||||
value: Box::new(value),
|
value: Box::new(value),
|
||||||
},
|
},
|
||||||
pos,
|
pos,
|
||||||
)
|
))
|
||||||
}
|
}
|
||||||
_ => subject,
|
_ => ParsedAssign::Expr(subject, pos),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(&mut self) -> Node {
|
fn parse_expr(&mut self) -> Expr {
|
||||||
self.parse_call()
|
self.parse_call()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_call(&mut self) -> Node {
|
fn parse_call(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
let mut subject = self.parse_value();
|
let mut subject = self.parse_value();
|
||||||
loop {
|
loop {
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
Some(TokenKind::LParen) => {
|
Some(TK::LParen) => {
|
||||||
self.step();
|
self.step();
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
None | Some(TokenKind::RParen) => {}
|
None | Some(TK::RParen) => {}
|
||||||
Some(_) => {
|
Some(_) => {
|
||||||
args.push(self.parse_expr());
|
args.push(self.parse_expr());
|
||||||
while let Some(TokenKind::Comma) = self.curr_kind() {
|
while let Some(TK::Comma) = self.curr_kind() {
|
||||||
self.step();
|
self.step();
|
||||||
if let Some(TokenKind::RParen) = self.curr_kind() {
|
if let Some(TK::RParen) = self.curr_kind() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
args.push(self.parse_expr());
|
args.push(self.parse_expr());
|
||||||
@ -237,15 +226,15 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
Some(TokenKind::RParen) => {}
|
Some(TK::RParen) => {}
|
||||||
_ => {
|
_ => {
|
||||||
self.error("expected ')'", pos.clone());
|
self.error("expected ')'", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_expr(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.step();
|
self.step();
|
||||||
subject = self.node(
|
subject = Expr::new(
|
||||||
NodeKind::Call {
|
EK::Call {
|
||||||
subject: Box::new(subject),
|
subject: Box::new(subject),
|
||||||
args,
|
args,
|
||||||
},
|
},
|
||||||
@ -257,42 +246,42 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_value(&mut self) -> Node {
|
fn parse_value(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
Some(TokenKind::Id) => self.parse_id(),
|
Some(TK::Ident) => self.parse_ident_expr(),
|
||||||
Some(TokenKind::Int) => self.parse_int(),
|
Some(TK::Int) => self.parse_int(),
|
||||||
Some(TokenKind::Str) => self.parse_string(),
|
Some(TK::Str) => self.parse_string(),
|
||||||
Some(TokenKind::LParen) => self.parse_group(),
|
Some(TK::LParen) => self.parse_group(),
|
||||||
Some(TokenKind::LBrace) => self.parse_block(),
|
Some(TK::LBrace) => self.parse_block(),
|
||||||
Some(TokenKind::If) => self.parse_if(),
|
Some(TK::If) => self.parse_if(),
|
||||||
Some(TokenKind::Loop) => self.parse_loop(),
|
Some(TK::Loop) => self.parse_loop(),
|
||||||
_ => {
|
_ => {
|
||||||
self.error("expected value", pos.clone());
|
self.error("expected value", pos.clone());
|
||||||
self.step();
|
self.step();
|
||||||
self.error_node(pos)
|
self.error_expr(pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_id(&mut self) -> Node {
|
fn parse_ident_expr(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
let Some(Token {
|
let Some(Token {
|
||||||
kind: TokenKind::Id,
|
kind: TK::Ident,
|
||||||
value: TokenValue::Id(value),
|
value: TokenValue::Ident(value),
|
||||||
..
|
..
|
||||||
}) = self.current
|
}) = self.current
|
||||||
else {
|
else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
self.step();
|
self.step();
|
||||||
self.node(NodeKind::Id(value), pos)
|
Expr::new(EK::Ident(value), pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_int(&mut self) -> Node {
|
fn parse_int(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
let Some(Token {
|
let Some(Token {
|
||||||
kind: TokenKind::Int,
|
kind: TK::Int,
|
||||||
value: TokenValue::Int(value),
|
value: TokenValue::Int(value),
|
||||||
..
|
..
|
||||||
}) = self.current
|
}) = self.current
|
||||||
@ -300,13 +289,13 @@ impl<'a> Parser<'a> {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
self.step();
|
self.step();
|
||||||
self.node(NodeKind::Int(value), pos)
|
Expr::new(EK::Int(value), pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_string(&mut self) -> Node {
|
fn parse_string(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
let Some(Token {
|
let Some(Token {
|
||||||
kind: TokenKind::Str,
|
kind: TK::Str,
|
||||||
value: TokenValue::Str(value),
|
value: TokenValue::Str(value),
|
||||||
..
|
..
|
||||||
}) = self.current.clone()
|
}) = self.current.clone()
|
||||||
@ -314,62 +303,121 @@ impl<'a> Parser<'a> {
|
|||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
self.step();
|
self.step();
|
||||||
self.node(NodeKind::Str(value.clone()), pos)
|
Expr::new(EK::Str(value.clone()), pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_group(&mut self) -> Node {
|
fn parse_group(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
let expr = Box::new(self.parse_expr());
|
let expr = Box::new(self.parse_expr());
|
||||||
if !self.curr_is(TokenKind::RParen) {
|
if !self.curr_is(TK::RParen) {
|
||||||
self.error("expected ')'", pos.clone());
|
self.error("expected ')'", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_expr(pos);
|
||||||
}
|
}
|
||||||
self.step();
|
self.step();
|
||||||
self.node(NodeKind::Group(expr), pos)
|
Expr::new(EK::Group(expr), pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_block(&mut self) -> Node {
|
fn parse_block(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
use TK::*;
|
||||||
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
let mut stmts = Vec::new();
|
let mut stmts = Vec::new();
|
||||||
loop {
|
loop {
|
||||||
match self.curr_kind() {
|
match self.curr_kind() {
|
||||||
None => {
|
None => {
|
||||||
self.error("expected ')'", pos.clone());
|
self.error("expected '}'", pos.clone());
|
||||||
break self.error_node(pos);
|
break self.error_expr(pos);
|
||||||
}
|
}
|
||||||
Some(TokenKind::RBrace) => {
|
Some(RBrace) => {
|
||||||
self.step();
|
self.step();
|
||||||
break self.node(NodeKind::Block(stmts), pos);
|
break Expr::new(EK::Block { stmts, expr: None }, pos);
|
||||||
}
|
}
|
||||||
_ => stmts.push(self.parse_stmt()),
|
Some(Fn) => stmts.push(self.parse_fn()),
|
||||||
|
Some(kind @ (Let | Return | Break)) => {
|
||||||
|
let stmt = match kind {
|
||||||
|
Let => self.parse_let(),
|
||||||
|
Return => self.parse_return(),
|
||||||
|
Break => self.parse_break(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
self.eat_semicolon();
|
||||||
|
stmts.push(stmt);
|
||||||
|
}
|
||||||
|
Some(kind @ (LBrace | If | Loop)) => {
|
||||||
|
let expr = match kind {
|
||||||
|
LBrace => self.parse_block(),
|
||||||
|
If => self.parse_if(),
|
||||||
|
Loop => self.parse_loop(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
match self.curr_kind() {
|
||||||
|
Some(TK::Semicolon) => {
|
||||||
|
self.step();
|
||||||
|
stmts.push(Stmt::new(SK::Expr(Box::new(expr)), pos.clone()))
|
||||||
|
}
|
||||||
|
Some(TK::RBrace) => {
|
||||||
|
self.step();
|
||||||
|
break Expr::new(
|
||||||
|
EK::Block {
|
||||||
|
stmts,
|
||||||
|
expr: Some(Box::new(expr)),
|
||||||
|
},
|
||||||
|
pos,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(_) => match self.parse_assign() {
|
||||||
|
ParsedAssign::Assign(stmt) => {
|
||||||
|
self.eat_semicolon();
|
||||||
|
stmts.push(stmt);
|
||||||
|
}
|
||||||
|
ParsedAssign::Expr(expr, pos) => match self.curr_kind() {
|
||||||
|
Some(TK::Semicolon) => {
|
||||||
|
self.step();
|
||||||
|
stmts.push(Stmt::new(SK::Expr(Box::new(expr)), pos))
|
||||||
|
}
|
||||||
|
Some(TK::RBrace) => {
|
||||||
|
self.step();
|
||||||
|
break Expr::new(
|
||||||
|
EK::Block {
|
||||||
|
stmts,
|
||||||
|
expr: Some(Box::new(expr)),
|
||||||
|
},
|
||||||
|
pos,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_if(&mut self) -> Node {
|
fn parse_if(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
let cond = Box::new(self.parse_expr());
|
let cond = Box::new(self.parse_expr());
|
||||||
if !self.curr_is(TokenKind::LBrace) {
|
if !self.curr_is(TK::LBrace) {
|
||||||
self.error("expected '}'", pos.clone());
|
self.error("expected '}'", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_expr(pos);
|
||||||
}
|
}
|
||||||
let truthy = Box::new(self.parse_block());
|
let truthy = Box::new(self.parse_block());
|
||||||
let falsy = match self.curr_kind() {
|
let falsy = match self.curr_kind() {
|
||||||
Some(TokenKind::Else) => {
|
Some(TK::Else) => {
|
||||||
self.step();
|
self.step();
|
||||||
if !self.curr_is(TokenKind::LBrace) {
|
if !self.curr_is(TK::LBrace) {
|
||||||
self.error("expected '}'", pos.clone());
|
self.error("expected '}'", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_expr(pos);
|
||||||
}
|
}
|
||||||
Some(Box::new(self.parse_block()))
|
Some(Box::new(self.parse_block()))
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
self.node(
|
Expr::new(
|
||||||
NodeKind::If {
|
EK::If {
|
||||||
cond,
|
cond,
|
||||||
truthy,
|
truthy,
|
||||||
falsy,
|
falsy,
|
||||||
@ -378,15 +426,65 @@ impl<'a> Parser<'a> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_loop(&mut self) -> Node {
|
fn parse_loop(&mut self) -> Expr {
|
||||||
let pos = self.pos().unwrap();
|
let pos = self.pos();
|
||||||
self.step();
|
self.step();
|
||||||
if !self.curr_is(TokenKind::LBrace) {
|
if !self.curr_is(TK::LBrace) {
|
||||||
self.error("expected '}'", pos.clone());
|
self.error("expected '}'", pos.clone());
|
||||||
return self.error_node(pos);
|
return self.error_expr(pos);
|
||||||
}
|
}
|
||||||
let body = Box::new(self.parse_block());
|
let body = Box::new(self.parse_block());
|
||||||
self.node(NodeKind::Loop { body }, pos)
|
Expr::new(EK::Loop { body }, pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_typ(&mut self) -> Typ {
|
||||||
|
let pos = self.pos();
|
||||||
|
match self.curr_kind() {
|
||||||
|
Some(TK::Ident) => self.parse_ident_typ(),
|
||||||
|
_ => {
|
||||||
|
self.error("expected type", pos.clone());
|
||||||
|
self.step();
|
||||||
|
self.error_typ(pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_ident_typ(&mut self) -> Typ {
|
||||||
|
let pos = self.pos();
|
||||||
|
let Some(Token {
|
||||||
|
kind: TK::Ident,
|
||||||
|
value: TokenValue::Ident(value),
|
||||||
|
..
|
||||||
|
}) = self.current
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
self.step();
|
||||||
|
Typ::new(TypKind::Ident(value), pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_param(&mut self) -> Param {
|
||||||
|
let pos = self.pos();
|
||||||
|
let subject = Box::new(self.parse_ident_expr());
|
||||||
|
let typ = if let Some(TK::Colon) = self.curr_kind() {
|
||||||
|
self.step();
|
||||||
|
Some(Box::new(self.parse_typ()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
Param { subject, typ, pos }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn eat_semicolon(&mut self) {
|
||||||
|
let pos = self.pos();
|
||||||
|
match self.curr_kind() {
|
||||||
|
Some(TK::Semicolon) => {
|
||||||
|
self.step();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.error("expected ';'", pos.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error<S: Into<String>>(&mut self, msg: S, pos: Pos) {
|
fn error<S: Into<String>>(&mut self, msg: S, pos: Pos) {
|
||||||
@ -402,26 +500,35 @@ impl<'a> Parser<'a> {
|
|||||||
self.current = self.lexer.next();
|
self.current = self.lexer.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn node(&self, kind: NodeKind, pos: Pos) -> Node {
|
fn error_stmt(&self, pos: Pos) -> Stmt {
|
||||||
Node { kind, pos }
|
Stmt::new(SK::Error, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn error_node(&self, pos: Pos) -> Node {
|
fn error_expr(&self, pos: Pos) -> Expr {
|
||||||
Node {
|
Expr::new(EK::Error, pos)
|
||||||
kind: NodeKind::Error,
|
|
||||||
pos,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pos(&self) -> Option<Pos> {
|
fn error_typ(&self, pos: Pos) -> Typ {
|
||||||
self.current.as_ref().map(|token| token.pos.clone())
|
Typ::new(TypKind::Error, pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn curr_is(&self, kind: TokenKind) -> bool {
|
fn pos(&self) -> Pos {
|
||||||
|
self.current
|
||||||
|
.as_ref()
|
||||||
|
.map(|token| token.pos.clone())
|
||||||
|
.unwrap_or_else(|| self.lexer.pos())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn curr_is(&self, kind: TK) -> bool {
|
||||||
self.curr_kind() == Some(kind)
|
self.curr_kind() == Some(kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn curr_kind(&self) -> Option<TokenKind> {
|
fn curr_kind(&self) -> Option<TK> {
|
||||||
self.current.as_ref().map(|t| t.kind.clone())
|
self.current.as_ref().map(|t| t.kind.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum ParsedAssign {
|
||||||
|
Assign(Stmt),
|
||||||
|
Expr(Expr, Pos),
|
||||||
|
}
|
||||||
|
@ -41,4 +41,8 @@ impl ErrorAcc {
|
|||||||
pub fn add(&mut self, error: Error) {
|
pub fn add(&mut self, error: Error) {
|
||||||
self.errors.push(error)
|
self.errors.push(error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &Error> {
|
||||||
|
self.errors.iter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ pub struct Token {
|
|||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum TokenKind {
|
pub enum TokenKind {
|
||||||
Error,
|
Error,
|
||||||
Id,
|
Ident,
|
||||||
Int,
|
Int,
|
||||||
Str,
|
Str,
|
||||||
If,
|
If,
|
||||||
@ -34,7 +34,7 @@ pub enum TokenKind {
|
|||||||
#[derive(Clone, PartialEq, Debug)]
|
#[derive(Clone, PartialEq, Debug)]
|
||||||
pub enum TokenValue {
|
pub enum TokenValue {
|
||||||
None,
|
None,
|
||||||
Id(u64),
|
Ident(u64),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
Str(String),
|
Str(String),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user