mirror of
https://github.com/Noratrieb/ub.git
synced 2026-01-14 16:45:05 +01:00
parse some things maybe
This commit is contained in:
parent
9e87a4ce91
commit
1bd5859f0c
8 changed files with 315 additions and 74 deletions
3
.rustfmt.toml
Normal file
3
.rustfmt.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
imports_granularity = "Crate"
|
||||||
|
newline_style = "Unix"
|
||||||
|
group_imports = "StdExternalCrate"
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
use crate::span::Span;
|
use std::{ops::Range, path::PathBuf};
|
||||||
use std::path::PathBuf;
|
|
||||||
|
type Span = Range<usize>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
name: PathBuf,
|
pub name: PathBuf,
|
||||||
items: Vec<Item>,
|
pub items: Vec<Stmt>, // todo make item
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Ty {
|
pub struct Ty {
|
||||||
span: Span,
|
pub span: Span,
|
||||||
kind: TyKind,
|
pub kind: TyKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -28,31 +29,31 @@ pub enum Item {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FnDecl {
|
pub struct FnDecl {
|
||||||
name: String,
|
pub name: String,
|
||||||
params: Vec<FnParam>,
|
pub params: Vec<FnParam>,
|
||||||
ret_ty: Ty,
|
pub ret_ty: Ty,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
body: Vec<Stmt>,
|
pub body: Vec<Stmt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FnParam {
|
pub struct FnParam {
|
||||||
name: String,
|
pub name: String,
|
||||||
ty: Ty,
|
pub ty: Ty,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct StructDecl {
|
pub struct StructDecl {
|
||||||
name: String,
|
pub name: String,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
fields: Vec<StructField>,
|
pub fields: Vec<StructField>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct StructField {
|
pub struct StructField {
|
||||||
name: String,
|
pub name: String,
|
||||||
ty: Ty,
|
pub ty: Ty,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -68,25 +69,25 @@ pub enum Stmt {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct VarDecl {
|
pub struct VarDecl {
|
||||||
name: String,
|
pub name: String,
|
||||||
ty: Ty,
|
pub ty: Ty,
|
||||||
rhs: Option<Expr>,
|
pub rhs: Option<Expr>,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Assignment {
|
pub struct Assignment {
|
||||||
place: Place,
|
pub place: Expr,
|
||||||
rhs: Expr,
|
pub rhs: Expr,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct IfStmt {
|
pub struct IfStmt {
|
||||||
cond: Expr,
|
pub cond: Expr,
|
||||||
body: Vec<Stmt>,
|
pub body: Vec<Stmt>,
|
||||||
else_part: Option<ElsePart>,
|
pub else_part: Option<ElsePart>,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
|
@ -97,35 +98,44 @@ pub enum ElsePart {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct WhileStmt {
|
pub struct WhileStmt {
|
||||||
cond: Expr,
|
pub cond: Expr,
|
||||||
body: Vec<Stmt>,
|
pub body: Vec<Stmt>,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct LoopStmt {
|
pub struct LoopStmt {
|
||||||
body: Vec<Stmt>,
|
pub body: Vec<Stmt>,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
BinOp(BinOp),
|
BinOp(BinOp),
|
||||||
Place(Place),
|
FieldAccess(FieldAccess),
|
||||||
Call(Call),
|
Call(Call),
|
||||||
Deref(Box<Expr>),
|
Deref(Box<Expr>),
|
||||||
|
Literal(Literal),
|
||||||
|
Name(String),
|
||||||
|
Array(Vec<Expr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct BinOp {
|
pub struct BinOp {
|
||||||
kind: BinOpKind,
|
pub kind: BinOpKind,
|
||||||
lhs: Box<Expr>,
|
pub lhs: Box<Expr>,
|
||||||
rhs: Box<Expr>,
|
pub rhs: Box<Expr>,
|
||||||
span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum BinOpKind {
|
pub enum BinOpKind {
|
||||||
|
Eq,
|
||||||
|
Neq,
|
||||||
|
Gt,
|
||||||
|
Lt,
|
||||||
|
GtEq,
|
||||||
|
LtEq,
|
||||||
Add,
|
Add,
|
||||||
Sub,
|
Sub,
|
||||||
Mul,
|
Mul,
|
||||||
|
|
@ -140,20 +150,20 @@ pub enum BinOpKind {
|
||||||
Xor,
|
Xor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum Place {
|
|
||||||
FieldAccess(FieldAccess),
|
|
||||||
Name(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct FieldAccess {
|
pub struct FieldAccess {
|
||||||
expr: Box<Expr>,
|
pub expr: Box<Expr>,
|
||||||
field_name: String,
|
pub field_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Call {
|
pub struct Call {
|
||||||
callee: Box<Expr>,
|
pub callee: Box<Expr>,
|
||||||
args: Vec<Expr>,
|
pub args: Vec<Expr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum Literal {
|
||||||
|
String(String, Span),
|
||||||
|
Integer(u64, Span),
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use logos::Logos;
|
use logos::Logos;
|
||||||
|
|
||||||
#[derive(Logos, Debug, PartialEq)]
|
#[derive(Logos, Debug, Clone, Hash, PartialEq, Eq)]
|
||||||
pub enum Token<'a> {
|
pub enum Token<'a> {
|
||||||
#[regex("//[^\n]*", logos::skip)]
|
#[regex("//[^\n]*", logos::skip)]
|
||||||
Comment,
|
Comment,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
mod lexer;
|
mod lexer;
|
||||||
mod span;
|
mod parser;
|
||||||
|
|
||||||
pub fn parse(_str: &str, _file_name: PathBuf) -> Result<ast::File, ()> {
|
pub fn parse(_str: &str, _file_name: PathBuf) -> Result<ast::File, ()> {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
||||||
168
ub_parser/src/parser.rs
Normal file
168
ub_parser/src/parser.rs
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
use std::{ops::Range, path::PathBuf};
|
||||||
|
|
||||||
|
use chumsky::{prelude::*, Stream};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::{BinOp, BinOpKind, Call, Expr, File, Literal, Stmt},
|
||||||
|
lexer::Token,
|
||||||
|
};
|
||||||
|
|
||||||
|
type Error<'src> = Simple<Token<'src>>;
|
||||||
|
type Span = Range<usize>;
|
||||||
|
|
||||||
|
fn ident_parser<'src>() -> impl Parser<Token<'src>, &'src str, Error = Error<'src>> + Clone {
|
||||||
|
filter_map(|span, tok| match tok {
|
||||||
|
Token::Ident(ident) => Ok(ident),
|
||||||
|
_ => Err(Simple::expected_input_found(span, Vec::new(), Some(tok))),
|
||||||
|
})
|
||||||
|
.labelled("identifier")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expr_parser<'src>() -> impl Parser<Token<'src>, Expr, Error = Error<'src>> + Clone {
|
||||||
|
recursive(|expr| {
|
||||||
|
let literal = filter_map(|span, token| match token {
|
||||||
|
Token::String(str) => Ok(Expr::Literal(Literal::String(
|
||||||
|
str[1..str.len() - 2].to_owned(),
|
||||||
|
span,
|
||||||
|
))),
|
||||||
|
// todo lol unwrap
|
||||||
|
Token::Integer(int) => Ok(Expr::Literal(Literal::Integer(int.parse().unwrap(), span))),
|
||||||
|
_ => Err(Simple::expected_input_found(span, Vec::new(), Some(token))),
|
||||||
|
})
|
||||||
|
.labelled("literal");
|
||||||
|
|
||||||
|
// A list of expressions
|
||||||
|
let items = expr
|
||||||
|
.clone()
|
||||||
|
.chain(just(Token::Comma).ignore_then(expr.clone()).repeated())
|
||||||
|
.then_ignore(just(Token::Comma).or_not())
|
||||||
|
.or_not()
|
||||||
|
.map(|item| item.unwrap_or_else(Vec::new));
|
||||||
|
|
||||||
|
let array = items
|
||||||
|
.clone()
|
||||||
|
.delimited_by(just(Token::BracketO), just(Token::BracketC))
|
||||||
|
.map(Expr::Array);
|
||||||
|
|
||||||
|
let atom = literal
|
||||||
|
.or(ident_parser().map(|str| Expr::Name(str.to_owned())))
|
||||||
|
.or(array)
|
||||||
|
.or(expr
|
||||||
|
.clone()
|
||||||
|
.delimited_by(just(Token::ParenO), just(Token::ParenC)));
|
||||||
|
|
||||||
|
let call = atom
|
||||||
|
.then(
|
||||||
|
items
|
||||||
|
.delimited_by(just(Token::ParenO), just(Token::ParenC))
|
||||||
|
.repeated(),
|
||||||
|
)
|
||||||
|
.foldl(|callee, args| {
|
||||||
|
Expr::Call(Call {
|
||||||
|
callee: Box::new(callee),
|
||||||
|
args,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let op = just(Token::Asterisk)
|
||||||
|
.to(BinOpKind::Mul)
|
||||||
|
.or(just(Token::Slash).to(BinOpKind::Div));
|
||||||
|
|
||||||
|
let product = call
|
||||||
|
.clone()
|
||||||
|
.then(op.then(call).repeated())
|
||||||
|
.foldl(|a, (kind, b)| {
|
||||||
|
Expr::BinOp(BinOp {
|
||||||
|
kind,
|
||||||
|
lhs: Box::new(a),
|
||||||
|
rhs: Box::new(b),
|
||||||
|
span: 0..0, // lol todo
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sum ops (add and subtract) have equal precedence
|
||||||
|
let op = just(Token::Plus)
|
||||||
|
.to(BinOpKind::Add)
|
||||||
|
.or(just(Token::Minus).to(BinOpKind::Sub));
|
||||||
|
let sum = product
|
||||||
|
.clone()
|
||||||
|
.then(op.then(product).repeated())
|
||||||
|
.foldl(|a, (kind, b)| {
|
||||||
|
Expr::BinOp(BinOp {
|
||||||
|
kind,
|
||||||
|
lhs: Box::new(a),
|
||||||
|
rhs: Box::new(b),
|
||||||
|
span: 0..0, // lol todo
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// Comparison ops (equal, not-equal) have equal precedence
|
||||||
|
let op = just(Token::EqEq)
|
||||||
|
.to(BinOpKind::Eq)
|
||||||
|
.or(just(Token::BangEq).to(BinOpKind::Neq));
|
||||||
|
let compare = sum
|
||||||
|
.clone()
|
||||||
|
.then(op.then(sum).repeated())
|
||||||
|
.foldl(|a, (kind, b)| {
|
||||||
|
Expr::BinOp(BinOp {
|
||||||
|
kind,
|
||||||
|
lhs: Box::new(a),
|
||||||
|
rhs: Box::new(b),
|
||||||
|
span: 0..0, // lol todo
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
compare
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn file_parser<'src>(
|
||||||
|
file_name: PathBuf,
|
||||||
|
) -> impl Parser<Token<'src>, File, Error = Error<'src>> + Clone {
|
||||||
|
expr_parser()
|
||||||
|
.map(move |expr| File {
|
||||||
|
name: file_name.clone(),
|
||||||
|
items: vec![Stmt::Expr(expr)],
|
||||||
|
})
|
||||||
|
.then_ignore(just(Token::Semi))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse<'src, I>(lexer: I, len: usize, file_name: PathBuf) -> (Option<File>, Vec<Error<'src>>)
|
||||||
|
where
|
||||||
|
I: 'src,
|
||||||
|
I: Iterator<Item = (Token<'src>, Span)>,
|
||||||
|
{
|
||||||
|
file_parser(file_name).parse_recovery(Stream::from_iter(len..len + 1, lexer))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::{fmt::Debug, path::PathBuf};
|
||||||
|
|
||||||
|
use logos::Logos;
|
||||||
|
|
||||||
|
use crate::lexer::Token;
|
||||||
|
|
||||||
|
fn parse(src: &str) -> impl Debug + '_ {
|
||||||
|
let lexer = Token::lexer(src);
|
||||||
|
let len = lexer.source().len();
|
||||||
|
|
||||||
|
super::parse(
|
||||||
|
lexer.spanned(),
|
||||||
|
len,
|
||||||
|
PathBuf::from(module_path!().replace("::", "__")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn addition() {
|
||||||
|
let r = parse("1 + 4;");
|
||||||
|
insta::assert_debug_snapshot!(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expression() {
|
||||||
|
let r = parse("(4 / hallo()) + 5;");
|
||||||
|
insta::assert_debug_snapshot!(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
---
|
||||||
|
source: ub_parser/src/parser.rs
|
||||||
|
expression: r
|
||||||
|
---
|
||||||
|
(
|
||||||
|
Some(
|
||||||
|
File {
|
||||||
|
name: "ub_parser__parser__tests",
|
||||||
|
items: [
|
||||||
|
Expr(
|
||||||
|
BinOp(
|
||||||
|
BinOp {
|
||||||
|
kind: Add,
|
||||||
|
lhs: Literal(
|
||||||
|
Integer(
|
||||||
|
1,
|
||||||
|
0..1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
rhs: Literal(
|
||||||
|
Integer(
|
||||||
|
4,
|
||||||
|
4..5,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
span: 0..0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
---
|
||||||
|
source: ub_parser/src/parser.rs
|
||||||
|
expression: r
|
||||||
|
---
|
||||||
|
(
|
||||||
|
Some(
|
||||||
|
File {
|
||||||
|
name: "ub_parser__parser__tests",
|
||||||
|
items: [
|
||||||
|
Expr(
|
||||||
|
BinOp(
|
||||||
|
BinOp {
|
||||||
|
kind: Add,
|
||||||
|
lhs: BinOp(
|
||||||
|
BinOp {
|
||||||
|
kind: Div,
|
||||||
|
lhs: Literal(
|
||||||
|
Integer(
|
||||||
|
4,
|
||||||
|
1..2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
rhs: Call(
|
||||||
|
Call {
|
||||||
|
callee: Name(
|
||||||
|
"hallo",
|
||||||
|
),
|
||||||
|
args: [],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
span: 0..0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
rhs: Literal(
|
||||||
|
Integer(
|
||||||
|
5,
|
||||||
|
16..17,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
span: 0..0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
use std::ops::Range;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub struct Span {
|
|
||||||
start: usize,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Span {
|
|
||||||
pub fn start_end(start: usize, end: usize) -> Self {
|
|
||||||
Self {
|
|
||||||
start,
|
|
||||||
len: end - start,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Range<usize>> for Span {
|
|
||||||
fn from(r: Range<usize>) -> Self {
|
|
||||||
Self::start_end(r.start, r.end)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue