From eb68c2b2070fc8c2518ac96cc51aac2b15d531c0 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Tue, 21 Jun 2022 19:56:57 +0200 Subject: [PATCH] lmao what --- parser/Cargo.toml | 1 + parser/src/ast.rs | 25 +++++++++++++ parser/src/lib.rs | 2 + parser/src/parser.rs | 59 +++++++++++++++++++++++++++++ parser/src/pre/lexer.rs | 56 +++++++++++++++++++++++++++- parser/src/token.rs | 82 +++++++++++++++++++++++++++++++++++++++-- 6 files changed, 221 insertions(+), 4 deletions(-) create mode 100644 parser/src/ast.rs create mode 100644 parser/src/parser.rs diff --git a/parser/Cargo.toml b/parser/Cargo.toml index 45dcb69..becd3e5 100644 --- a/parser/Cargo.toml +++ b/parser/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +dbg-pls = { version = "0.3.2", features = ["derive", "colors"] } peekmore = { version = "1.0.0", features = ["smallvec"] } [dev-dependencies] diff --git a/parser/src/ast.rs b/parser/src/ast.rs new file mode 100644 index 0000000..a162f0c --- /dev/null +++ b/parser/src/ast.rs @@ -0,0 +1,25 @@ +use dbg_pls::DebugPls; + +use crate::Span; + +pub type Spanned = (T, Span); + +#[derive(Debug, DebugPls)] +pub enum TypeSpecifier { + Void, + Char, + Short, + Int, + Long, + Float, + Double, + Signed, + Unsigned, + Bool, + Complex, + // TODO + // atomic-type-specifier + // struct-or-union-specifier + // enum-specifier + // typedef-name +} diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 7acd491..e65cf86 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -1,6 +1,8 @@ #![allow(dead_code)] #![warn(rust_2018_idioms)] +mod ast; +mod parser; mod pre; mod token; diff --git a/parser/src/parser.rs b/parser/src/parser.rs new file mode 100644 index 0000000..bd62903 --- /dev/null +++ b/parser/src/parser.rs @@ -0,0 +1,59 @@ +use peekmore::PeekMoreIterator; + +use crate::{ + ast::{Spanned, TypeSpecifier}, + token::{Keyword as Kw, Token as Tok}, + Span, +}; + +struct ParserError { + span: Span, + message: String, +} + +impl ParserError { + fn new(span: Span, message: String) -> Self { + Self { span, message } + } + + fn eof() -> Self { + Self::new(0..0, "unexpected end of file".to_string()) + } +} + +type Result = std::result::Result; + +struct Parser<'src, I> +where + I: Iterator, Span)>, +{ + lex: PeekMoreIterator, +} + +impl<'src, I> Parser<'src, I> +where + I: Iterator, Span)>, +{ + fn type_specifier(&mut self) -> Result> { + let (token, span) = self.next_t()?; + let ty = match token { + Tok::Kw(Kw::Void) => TypeSpecifier::Void, + Tok::Kw(Kw::Char) => TypeSpecifier::Char, + Tok::Kw(Kw::Short) => TypeSpecifier::Short, + Tok::Kw(Kw::Int) => TypeSpecifier::Int, + Tok::Kw(Kw::Long) => TypeSpecifier::Long, + Tok::Kw(Kw::Float) => TypeSpecifier::Float, + Tok::Kw(Kw::Double) => TypeSpecifier::Double, + Tok::Kw(Kw::Signed) => TypeSpecifier::Signed, + Tok::Kw(Kw::Unsigned) => TypeSpecifier::Unsigned, + Tok::Kw(Kw::Bool) => TypeSpecifier::Bool, + Tok::Kw(Kw::Complex) => return Err(ParserError::new(span, "tf are you doing with complex numbers".to_string())), + tok => return Err(ParserError::new(span, format!("Invalid token: `{tok}`"))), + }; + Ok((ty, span)) + } + + fn next_t(&mut self) -> Result<(Tok<'src>, Span)> { + self.lex.next().ok_or_else(ParserError::eof) + } +} diff --git a/parser/src/pre/lexer.rs b/parser/src/pre/lexer.rs index f1d09d6..398b3bd 100644 --- a/parser/src/pre/lexer.rs +++ b/parser/src/pre/lexer.rs @@ -3,7 +3,7 @@ //! //! Code might be bad. Possibly. -use std::ops::Not; +use std::{ops::Not, fmt::Display}; use peekmore::PeekMore; @@ -119,6 +119,60 @@ pub enum Punctuator { HashHash, } +impl Display for Punctuator { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Punctuator::BracketOpen => f.write_str("["), + Punctuator::BracketClose => f.write_str("]"), + Punctuator::ParenOpen => f.write_str("("), + Punctuator::ParenClose => f.write_str(")"), + Punctuator::BraceOpen => f.write_str("{"), + Punctuator::BraceClose => f.write_str("}"), + Punctuator::Dot => f.write_str("."), + Punctuator::Arrow => f.write_str("->"), + Punctuator::PlusPlus => f.write_str("++"), + Punctuator::MinusMinus => f.write_str("--"), + Punctuator::Ampersand => f.write_str("&"), + Punctuator::Asterisk => f.write_str("*"), + Punctuator::Plus => f.write_str("+"), + Punctuator::Minus => f.write_str("-"), + Punctuator::Tilde => f.write_str("~"), + Punctuator::Bang => f.write_str("!"), + Punctuator::Percent => f.write_str("%"), + Punctuator::LeftLeftChevron => f.write_str("<<"), + Punctuator::RightRightChevron => f.write_str(">>"), + Punctuator::LeftChevron => f.write_str("<"), + Punctuator::RightChevron => f.write_str(">"), + Punctuator::LeftChevronEq => f.write_str("<="), + Punctuator::RightChevronEq => f.write_str(">="), + Punctuator::EqEq => f.write_str("=="), + Punctuator::BangEq => f.write_str("!="), + Punctuator::Caret => f.write_str("^"), + Punctuator::Pipe => f.write_str("|"), + Punctuator::AmpersandAmpersand => f.write_str("&&"), + Punctuator::PipePipe => f.write_str("||"), + Punctuator::QuestionMark => f.write_str("?"), + Punctuator::Colon => f.write_str(":"), + Punctuator::Semicolon => f.write_str(";"), + Punctuator::DotDotDot => f.write_str("..."), + Punctuator::Eq => f.write_str("="), + Punctuator::AsteriskEq => f.write_str("*="), + Punctuator::SlashEq => f.write_str("/="), + Punctuator::PercentEq => f.write_str("%="), + Punctuator::PlusEq => f.write_str("+="), + Punctuator::MinusEq => f.write_str("-="), + Punctuator::LeftLeftChevronEq => f.write_str("<<="), + Punctuator::RightRightChevronEq => f.write_str(">>="), + Punctuator::AmspersandEq => f.write_str("&="), + Punctuator::CaretEq => f.write_str("^="), + Punctuator::PipeEq => f.write_str("|="), + Punctuator::Comma => f.write_str(","), + Punctuator::Hash => f.write_str("#"), + Punctuator::HashHash => f.write_str("##"), + } + } +} + struct PLexer<'src, I> where I: Iterator, diff --git a/parser/src/token.rs b/parser/src/token.rs index 296ee5f..92802a8 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use crate::{ pre::{PToken, Punctuator}, Span, @@ -11,7 +13,7 @@ use crate::{ /// punctuator #[derive(Debug)] pub enum Token<'src> { - Keyword(Keyword), + Kw(Keyword), Identifier(&'src str), Constant(Constant), StringLiteral(&'src str), @@ -137,7 +139,7 @@ pub fn pre_tokens_to_tokens<'src>( let token = match token { PToken::HeaderName(_) => todo!("header names aren't real, wake up"), PToken::Identifier(ident) => match ident_to_keyword(ident) { - Some(keyword) => Token::Keyword(keyword), + Some(keyword) => Token::Kw(keyword), None => Token::Identifier(ident), }, PToken::PpNumber(number) => pp_number_to_constant(number) @@ -153,6 +155,80 @@ pub fn pre_tokens_to_tokens<'src>( }) } +impl Display for Token<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Token::Kw(kw) => Display::fmt(kw, f), + Token::Identifier(ident) => Display::fmt(ident, f), + Token::Constant(c) => Display::fmt(c, f), + Token::StringLiteral(str) => write!(f, "\"{}\"", str), + Token::Punctuator(p) => Display::fmt(p, f), + Token::Error => f.write_str(""), + } + } +} + +impl Display for Keyword { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Keyword::Auto => f.write_str("auto"), + Keyword::Break => f.write_str("break"), + Keyword::Case => f.write_str("case"), + Keyword::Char => f.write_str("char"), + Keyword::Const => f.write_str("const"), + Keyword::Continue => f.write_str("continue"), + Keyword::Default => f.write_str("default"), + Keyword::Do => f.write_str("do"), + Keyword::Double => f.write_str("double"), + Keyword::Else => f.write_str("else"), + Keyword::Enum => f.write_str("enum"), + Keyword::Extern => f.write_str("extern"), + Keyword::Float => f.write_str("float"), + Keyword::For => f.write_str("for"), + Keyword::Goto => f.write_str("goto"), + Keyword::If => f.write_str("if"), + Keyword::Inline => f.write_str("inline"), + Keyword::Int => f.write_str("int"), + Keyword::Long => f.write_str("long"), + Keyword::Register => f.write_str("register"), + Keyword::Restrict => f.write_str("restrict"), + Keyword::Return => f.write_str("return"), + Keyword::Short => f.write_str("short"), + Keyword::Signed => f.write_str("signed"), + Keyword::Sizeof => f.write_str("sizeof"), + Keyword::Static => f.write_str("static"), + Keyword::Struct => f.write_str("struct"), + Keyword::Switch => f.write_str("switch"), + Keyword::Typedef => f.write_str("typedef"), + Keyword::Union => f.write_str("union"), + Keyword::Unsigned => f.write_str("unsigned"), + Keyword::Void => f.write_str("void"), + Keyword::Volatile => f.write_str("volatile"), + Keyword::While => f.write_str("while"), + Keyword::Alignas => f.write_str("_Alignas"), + Keyword::Alignof => f.write_str("_Alignof"), + Keyword::Atomic => f.write_str("_Atomic"), + Keyword::Bool => f.write_str("_Bool"), + Keyword::Complex => f.write_str("_Complex"), + Keyword::Generic => f.write_str("_Generic"), + Keyword::Imaginary => f.write_str("_Imaginary"), + Keyword::Noreturn => f.write_str("_Noreturn"), + Keyword::StaticAssert => f.write_str("_Static_assert"), + Keyword::ThreadLocal => f.write_str("_Thread_local"), + } + } +} + +impl Display for Constant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Constant::Int(int) => Display::fmt(int, f), + Constant::Float(float) => Display::fmt(float, f), + Constant::Char(c) => write!(f, "'{}'", *c as char), + } + } +} + #[cfg(test)] mod tests { macro_rules! lex_test { @@ -173,4 +249,4 @@ int main() { "#; lex_test!(src); } -} \ No newline at end of file +}