add works

This commit is contained in:
nora 2022-06-26 15:14:30 +02:00
parent 37772658bd
commit 31575cbdfb
6 changed files with 104 additions and 31 deletions

View file

@ -1 +1,6 @@
# uwuc # uwuc
# Building
`uwucc` requires a nightly rust compiler because of the following features:
* `let_else`

View file

@ -1,4 +1,5 @@
#![allow(dead_code)] #![feature(let_else)]
#![allow(dead_code)] // TODO: no
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
use std::fmt::Debug; use std::fmt::Debug;

View file

@ -19,14 +19,17 @@ pub struct ParserError {
} }
impl ParserError { impl ParserError {
#[track_caller]
fn new(span: Span, message: String) -> Self { fn new(span: Span, message: String) -> Self {
Self { span, message } Self { span, message }
} }
#[track_caller]
fn eof() -> Self { fn eof() -> Self {
Self::new(Span::default(), "unexpected end of file".to_string()) Self::new(Span::default(), "unexpected end of file".to_string())
} }
#[track_caller]
fn unsupported(span: Span, token: &Tok<'_>) -> Self { fn unsupported(span: Span, token: &Tok<'_>) -> Self {
Self::new(span, format!("`{token}` is not supported")) Self::new(span, format!("`{token}` is not supported"))
} }

View file

@ -19,17 +19,19 @@ where
} }
fn get_lhs(&mut self) -> Result<Spanned<Expr>> { fn get_lhs(&mut self) -> Result<Spanned<Expr>> {
let (typ, span) = match self.next_t()? { let (typ, span) = match self.peek_t()? {
(Tok::Ident(ident), span) => (Atom::Ident(ident.to_string()), span), &(Tok::Ident(ident), span) => (Atom::Ident(ident.to_string()), span),
(Tok::StringLiteral(literal), span) => (Atom::String(literal.to_string()), span), &(Tok::StringLiteral(literal), span) => (Atom::String(literal.to_string()), span),
(Tok::Constant(Constant::Int(int)), span) => (Atom::Int(int), span), &(Tok::Constant(Constant::Int(int)), span) => (Atom::Int(int), span),
(Tok::Constant(Constant::Float(float)), span) => (Atom::Float(float), span), &(Tok::Constant(Constant::Float(float)), span) => (Atom::Float(float), span),
(Tok::Constant(Constant::Char(char)), span) => (Atom::Char(char), span), &(Tok::Constant(Constant::Char(char)), span) => (Atom::Char(char), span),
(Tok::Punct(punct), span) => { &(Tok::Punct(punct), span) => {
let r_bp = prefix_binding_power(&Tok::Punct(punct)); let r_bp = prefix_binding_power(&Tok::Punct(punct));
let op = unary_op_from_token(&Tok::Punct(punct), span)?; let Some(op) = unary_op_from_token(&Tok::Punct(punct)) else { panic!() };
let rhs = self.expr_bp(r_bp)?; let rhs = self.expr_bp(r_bp)?;
self.next_t()?;
return Ok(( return Ok((
Expr::Unary(ExprUnary { Expr::Unary(ExprUnary {
rhs: Box::new(rhs), rhs: Box::new(rhs),
@ -40,12 +42,13 @@ where
} }
(tok, span) => { (tok, span) => {
return Err(ParserError::new( return Err(ParserError::new(
span, *span,
format!("expected expression, found {tok}"), format!("expected expression, found {tok}"),
)); ));
} }
}; };
self.next_t()?;
Ok((Expr::Atom(typ), span)) Ok((Expr::Atom(typ), span))
} }
@ -54,11 +57,13 @@ where
#[allow(clippy::while_let_loop)] // idc #[allow(clippy::while_let_loop)] // idc
loop { loop {
let (tok, span) = match self.next_t() { let (tok, _) = match self.peek_t() {
Ok(tok) => tok, Ok(&tok) => tok,
Err(_) => break, Err(_) => break,
}; };
let op = binary_op_from_token(&tok, span)?; let Some(op) = binary_op_from_token(&tok) else { break; };
self.next_t()?;
let (l_bp, r_bp) = infix_binding_power(&tok); let (l_bp, r_bp) = infix_binding_power(&tok);
if l_bp < min_bp { if l_bp < min_bp {
@ -83,28 +88,22 @@ where
} }
} }
fn unary_op_from_token(tok: &Tok<'_>, span: Span) -> Result<UnaryOp> { fn unary_op_from_token(tok: &Tok<'_>) -> Option<UnaryOp> {
match tok { match tok {
Tok::Punct(P::Ampersand) => Ok(UnaryOp::AddrOf), Tok::Punct(P::Ampersand) => Some(UnaryOp::AddrOf),
Tok::Punct(P::Asterisk) => Ok(UnaryOp::Deref), Tok::Punct(P::Asterisk) => Some(UnaryOp::Deref),
Tok::Punct(P::Plus) => Ok(UnaryOp::Plus), Tok::Punct(P::Plus) => Some(UnaryOp::Plus),
Tok::Punct(P::Minus) => Ok(UnaryOp::Minus), Tok::Punct(P::Minus) => Some(UnaryOp::Minus),
Tok::Punct(P::Tilde) => Ok(UnaryOp::Tilde), Tok::Punct(P::Tilde) => Some(UnaryOp::Tilde),
Tok::Punct(P::Bang) => Ok(UnaryOp::Bang), Tok::Punct(P::Bang) => Some(UnaryOp::Bang),
_ => Err(ParserError::new( _ => None,
span,
format!("invalid unary operation: {tok}"),
)),
} }
} }
fn binary_op_from_token(tok: &Tok<'_>, span: Span) -> Result<BinaryOp> { fn binary_op_from_token(tok: &Tok<'_>) -> Option<BinaryOp> {
match tok { match tok {
Tok::Punct(P::Plus) => Ok(BinaryOp::Add), Tok::Punct(P::Plus) => Some(BinaryOp::Add),
Tok::Punct(P::Minus) => Ok(BinaryOp::Sub), Tok::Punct(P::Minus) => Some(BinaryOp::Sub),
_ => Err(ParserError::new( _ => None,
span,
format!("invalid binary operation: {tok}"),
)),
} }
} }

View file

@ -0,0 +1,63 @@
---
source: parser/src/parser/tests.rs
expression: parsed
---
Ok(
[
(
Decl(
Normal(
NormalDecl {
decl_spec: DeclSpec {
ty: Int,
attrs: (empty),
},
init_declarators: [
(
InitDecl {
declarator: Declarator {
decl: Ident(
(
"x",
5..6,
),
),
pointer: false,
},
init: Some(
(
Binary(
ExprBinary {
lhs: (
Atom(
Int(
1,
),
),
9..10,
),
rhs: (
Atom(
Int(
1,
),
),
13..14,
),
op: Add,
},
),
9..14,
),
),
},
5..6,
),
],
},
),
),
1..6,
),
],
)

2
rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "nightly-2022-06-25"