mirror of
https://github.com/Noratrieb/crapderive.git
synced 2026-01-14 08:35:09 +01:00
parser works
This commit is contained in:
parent
ac63a8a5c7
commit
29219405ff
6 changed files with 227 additions and 43 deletions
3
.rustfmt.toml
Normal file
3
.rustfmt.toml
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
imports_granularity = "Crate"
|
||||
newline_style = "Unix"
|
||||
group_imports = "StdExternalCrate"
|
||||
65
Cargo.lock
generated
65
Cargo.lock
generated
|
|
@ -22,6 +22,7 @@ name = "asm-thing"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dbg-pls",
|
||||
"insta",
|
||||
"logos",
|
||||
]
|
||||
|
||||
|
|
@ -70,6 +71,19 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"terminal_size",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
|
|
@ -108,6 +122,12 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.24"
|
||||
|
|
@ -140,6 +160,20 @@ dependencies = [
|
|||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcc3e639bcba360d9237acabd22014c16f3df772db463b7446cd81b070714767"
|
||||
dependencies = [
|
||||
"console",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"similar",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.2"
|
||||
|
|
@ -345,6 +379,9 @@ name = "serde"
|
|||
version = "1.0.137"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
|
|
@ -368,6 +405,24 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"ryu",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "similar"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3"
|
||||
|
||||
[[package]]
|
||||
name = "smawk"
|
||||
version = "0.3.1"
|
||||
|
|
@ -407,6 +462,16 @@ dependencies = [
|
|||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.15.0"
|
||||
|
|
|
|||
|
|
@ -8,3 +8,6 @@ edition = "2021"
|
|||
[dependencies]
|
||||
dbg-pls = { version = "0.3.2", features = ["colors", "derive"] }
|
||||
logos = "0.12.1"
|
||||
|
||||
[dev-dependencies]
|
||||
insta = "1.14.1"
|
||||
|
|
|
|||
10
src/error.rs
Normal file
10
src/error.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
use dbg_pls::DebugPls;
|
||||
use logos::Span;
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub struct CompilerError {
|
||||
pub msg: String,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, CompilerError>;
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
use std::io;
|
||||
|
||||
mod error;
|
||||
mod parser;
|
||||
|
||||
fn main() -> Result<(), io::Error> {
|
||||
let file = std::fs::read_to_string("../test.at")?;
|
||||
parser::run(&file);
|
||||
let file = std::fs::read_to_string("./test.at")?;
|
||||
let result = parser::parse(&file);
|
||||
let _ = dbg_pls::color!(result);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
185
src/parser.rs
185
src/parser.rs
|
|
@ -1,6 +1,9 @@
|
|||
use std::{fmt::Debug, iter::Peekable};
|
||||
|
||||
use dbg_pls::DebugPls;
|
||||
use logos::{Lexer, Logos, Span};
|
||||
use std::iter::Peekable;
|
||||
|
||||
use crate::error::{CompilerError, Result};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Logos, DebugPls)]
|
||||
pub enum Token<'a> {
|
||||
|
|
@ -43,18 +46,13 @@ pub fn lex(src: &str) -> Lexer<'_, Token<'_>> {
|
|||
<Token as Logos>::lexer(src)
|
||||
}
|
||||
|
||||
pub fn run(src: &str) {
|
||||
let tokens = lex(src).collect::<Vec<_>>();
|
||||
dbg_pls::color!(tokens);
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq, DebugPls)]
|
||||
pub struct Stmt {
|
||||
pub kind: StmtKind,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq, DebugPls)]
|
||||
pub enum StmtKind {
|
||||
Mov { to: Expr, from: Expr },
|
||||
Add { to: Expr, value: Expr },
|
||||
|
|
@ -64,54 +62,85 @@ pub enum StmtKind {
|
|||
Jmp { to: Expr },
|
||||
Je { to: Expr },
|
||||
Cmp { rhs: Expr, lhs: Expr },
|
||||
Label { name: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq, DebugPls)]
|
||||
pub struct Expr {
|
||||
pub kind: ExprKind,
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq, DebugPls)]
|
||||
pub enum ExprKind {
|
||||
Register,
|
||||
Number,
|
||||
Register(u8),
|
||||
Number(u64),
|
||||
Addr(Box<Expr>),
|
||||
Name(String),
|
||||
}
|
||||
|
||||
struct Parser<'a, I>
|
||||
where
|
||||
I: Iterator<Item = Token<'a>>,
|
||||
I: Iterator<Item = (Token<'a>, Span)>,
|
||||
{
|
||||
iter: Peekable<I>,
|
||||
}
|
||||
|
||||
struct CompilerError;
|
||||
impl CompilerError {
|
||||
fn new(msg: String, span: Span) -> Self {
|
||||
Self { span, msg }
|
||||
}
|
||||
|
||||
type Result<T> = std::result::Result<T, CompilerError>;
|
||||
fn not_allowed(span: Span, token: &str) -> Self {
|
||||
Self::new(format!("`{token}` is not allowed here"), span)
|
||||
}
|
||||
|
||||
fn invalid_token(span: Span) -> Self {
|
||||
Self::new("Invalid token".to_string(), span)
|
||||
}
|
||||
fn eof() -> Self {
|
||||
Self {
|
||||
span: Default::default(),
|
||||
msg: "Unexpected end of file".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! expect {
|
||||
($self:ident, $token:pat) => {
|
||||
if let $token = $self.next()? {
|
||||
return Err(CompilerError);
|
||||
($self:ident, $token:pat) => {{
|
||||
let (next, span) = $self.next()?;
|
||||
if let $token = next {
|
||||
span
|
||||
} else {
|
||||
return Err(CompilerError {
|
||||
msg: format!(
|
||||
concat!("Expected ", stringify!($token), ", found {:?}"),
|
||||
next,
|
||||
),
|
||||
span,
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn stmt(kind: StmtKind, span: Span) -> Stmt {
|
||||
Stmt { kind, span }
|
||||
}};
|
||||
}
|
||||
|
||||
impl<'a, I> Parser<'a, I>
|
||||
where
|
||||
I: Iterator<Item = Token<'a>>,
|
||||
I: Iterator<Item = (Token<'a>, Span)>,
|
||||
{
|
||||
fn program(&mut self) -> Result<Vec<Stmt>> {
|
||||
todo!()
|
||||
let mut stmts = Vec::new();
|
||||
while let Ok(_) = self.peek() {
|
||||
let stmt = self.stmt()?;
|
||||
stmts.push(stmt);
|
||||
}
|
||||
Ok(stmts)
|
||||
}
|
||||
|
||||
fn stmt(&mut self) -> Result<Stmt> {
|
||||
Ok(match self.next()? {
|
||||
let stmt = |kind, span| Stmt { kind, span };
|
||||
|
||||
let (token, span) = self.next()?;
|
||||
Ok(match token {
|
||||
Token::Mov => {
|
||||
let to = self.expr()?;
|
||||
expect!(self, Token::Comma);
|
||||
|
|
@ -135,29 +164,101 @@ where
|
|||
let rhs = self.expr()?;
|
||||
stmt(StmtKind::Cmp { lhs, rhs }, Default::default())
|
||||
}
|
||||
Token::Add => {}
|
||||
Token::Sub => {}
|
||||
Token::Mul => {}
|
||||
Token::Div => {}
|
||||
Token::BracketOpen => {}
|
||||
Token::BracketClose => {}
|
||||
Token::Comma => {}
|
||||
Token::Label(_) => {}
|
||||
Token::Number(_) => {}
|
||||
Token::Word(_) => {}
|
||||
Token::Error => {}
|
||||
Token::Add => {
|
||||
let to = self.expr()?;
|
||||
expect!(self, Token::Comma);
|
||||
let value = self.expr()?;
|
||||
stmt(StmtKind::Add { to, value }, Default::default())
|
||||
}
|
||||
Token::Sub => {
|
||||
let to = self.expr()?;
|
||||
expect!(self, Token::Comma);
|
||||
let value = self.expr()?;
|
||||
stmt(StmtKind::Sub { to, value }, Default::default())
|
||||
}
|
||||
Token::Mul => {
|
||||
let to = self.expr()?;
|
||||
expect!(self, Token::Comma);
|
||||
let value = self.expr()?;
|
||||
stmt(StmtKind::Mul { to, value }, Default::default())
|
||||
}
|
||||
Token::Div => {
|
||||
let to = self.expr()?;
|
||||
expect!(self, Token::Comma);
|
||||
let value = self.expr()?;
|
||||
stmt(StmtKind::Div { to, value }, Default::default())
|
||||
}
|
||||
Token::Label(name) => stmt(
|
||||
StmtKind::Label {
|
||||
name: name.to_owned(),
|
||||
},
|
||||
Default::default(),
|
||||
),
|
||||
Token::BracketOpen => return Err(CompilerError::not_allowed(span, "[")),
|
||||
Token::BracketClose => return Err(CompilerError::not_allowed(span, "]")),
|
||||
Token::Comma => return Err(CompilerError::not_allowed(span, ",")),
|
||||
Token::Number(_) => return Err(CompilerError::not_allowed(span, "{number}")),
|
||||
Token::Word(_) => return Err(CompilerError::not_allowed(span, "{word}")),
|
||||
Token::Error => return Err(CompilerError::invalid_token(span)),
|
||||
})
|
||||
}
|
||||
|
||||
fn expr(&mut self) -> Result<Expr> {
|
||||
todo!()
|
||||
let expr = |kind, span| Expr { kind, span };
|
||||
|
||||
let (token, span) = self.next()?;
|
||||
Ok(match token {
|
||||
Token::BracketOpen => {
|
||||
let inner = self.expr()?;
|
||||
let bclose_span = expect!(self, Token::BracketClose);
|
||||
expr(ExprKind::Addr(Box::new(inner)), span.start..bclose_span.end)
|
||||
}
|
||||
Token::Number(n) => expr(ExprKind::Number(n), span),
|
||||
Token::Word(name) => {
|
||||
if let Some(r_number) = name.strip_prefix("r") {
|
||||
if let Ok(n) = r_number.parse::<u8>() {
|
||||
if n > 15 {
|
||||
return Err(CompilerError::new(
|
||||
format!("Only registers from 0..15 are available. Invalid register: {n}"),
|
||||
span,
|
||||
));
|
||||
}
|
||||
return Ok(expr(ExprKind::Register(n), span));
|
||||
}
|
||||
}
|
||||
expr(ExprKind::Name(name.to_owned()), span)
|
||||
}
|
||||
Token::Mov => return Err(CompilerError::not_allowed(span, "mov")),
|
||||
Token::Jmp => return Err(CompilerError::not_allowed(span, "jmp")),
|
||||
Token::Je => return Err(CompilerError::not_allowed(span, "je")),
|
||||
Token::Cmp => return Err(CompilerError::not_allowed(span, "cmp")),
|
||||
Token::Add => return Err(CompilerError::not_allowed(span, "add")),
|
||||
Token::Sub => return Err(CompilerError::not_allowed(span, "sub")),
|
||||
Token::Mul => return Err(CompilerError::not_allowed(span, "mul")),
|
||||
Token::Div => return Err(CompilerError::not_allowed(span, "div")),
|
||||
Token::BracketClose => return Err(CompilerError::not_allowed(span, "]")),
|
||||
Token::Comma => return Err(CompilerError::not_allowed(span, ",")),
|
||||
Token::Label(_) => return Err(CompilerError::not_allowed(span, "{label}")),
|
||||
Token::Error => return Err(CompilerError::invalid_token(span)),
|
||||
})
|
||||
}
|
||||
|
||||
fn peek(&mut self) -> Result<&Token<'a>> {
|
||||
self.iter.peek().ok_or(CompilerError)
|
||||
fn peek(&mut self) -> Result<&(Token<'a>, Span)> {
|
||||
self.iter.peek().ok_or(CompilerError::eof())
|
||||
}
|
||||
|
||||
fn next(&mut self) -> Result<Token<'a>> {
|
||||
self.iter.next().ok_or(CompilerError)
|
||||
fn next(&mut self) -> Result<(Token<'a>, Span)> {
|
||||
self.iter.next().ok_or(CompilerError::eof())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(src: &str) -> Result<Vec<Stmt>> {
|
||||
let lexer = lex(src).spanned();
|
||||
let mut parser = Parser {
|
||||
iter: lexer.peekable(),
|
||||
};
|
||||
parser.program()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue