diff --git a/Cargo.lock b/Cargo.lock index e6ca942..ca6565b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,60 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +dependencies = [ + "memchr", +] + [[package]] name = "autocfg" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "console" version = "0.15.0" @@ -21,12 +69,66 @@ dependencies = [ "winapi", ] +[[package]] +name = "crc32fast" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "dbg-pls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f28b65c59b1830ac65640335cf2ebef868e8c9982d1cbab01ce843ebe74d37a" +dependencies = [ + "dbg-pls-derive", + "itoa", + "once_cell", + "prettyplease", + "proc-macro2", + "quote", + "ryu", + "syn", + "syntect", + "textwrap", +] + +[[package]] +name = "dbg-pls-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18ad0d32e09e083b0bf764cc9c2f1956518afb16b6ae0e1110c909d056f8271f" +dependencies = [ + "proc-macro2", + "quote", + "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "hashbrown" version = "0.12.1" @@ -63,28 +165,96 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +[[package]] +name = "line-wrap" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" +dependencies = [ + "safemem", +] + [[package]] name = "linked-hash-map" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "miniz_oxide" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +dependencies = [ + "adler", +] + +[[package]] +name = "num_threads" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +dependencies = [ + "libc", +] + [[package]] name = "once_cell" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +[[package]] +name = "onig" +version = "6.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ddfe2c93bb389eea6e6d713306880c7f6dcc99a75b659ce145d962c861b225" +dependencies = [ + "bitflags", + "lazy_static", + "libc", + "onig_sys", +] + +[[package]] +name = "onig_sys" +version = "69.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dd3eee045c84695b53b20255bb7317063df090b68e18bfac0abb6c39cf7f33e" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "parser" version = "0.1.0" dependencies = [ + "dbg-pls", "insta", "peekmore", ] @@ -98,6 +268,36 @@ dependencies = [ "smallvec", ] +[[package]] +name = "pkg-config" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" + +[[package]] +name = "plist" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd39bc6cdc9355ad1dc5eeedefee696bb35c34caf21768741e81826c0bbd7225" +dependencies = [ + "base64", + "indexmap", + "line-wrap", + "serde", + "time", + "xml-rs", +] + +[[package]] +name = "prettyplease" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3662417e650bd6af740f5b8b3501776aa10c3d5cbd10b40263ed250d3770884" +dependencies = [ + "proc-macro2", + "syn", +] + [[package]] name = "proc-macro2" version = "1.0.40" @@ -116,12 +316,44 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" + [[package]] name = "ryu" version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +[[package]] +name = "safemem" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.137" @@ -177,6 +409,12 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +[[package]] +name = "smawk" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043" + [[package]] name = "syn" version = "1.0.98" @@ -188,6 +426,28 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syntect" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b20815bbe80ee0be06e6957450a841185fcf690fe0178f14d77a05ce2caa031" +dependencies = [ + "bincode", + "bitflags", + "flate2", + "fnv", + "lazy_static", + "lazycell", + "onig", + "plist", + "regex-syntax", + "serde", + "serde_derive", + "serde_json", + "walkdir", + "yaml-rust", +] + [[package]] name = "terminal_size" version = "0.1.17" @@ -198,12 +458,49 @@ dependencies = [ "winapi", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + +[[package]] +name = "time" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82501a4c1c0330d640a6e176a3d6a204f5ec5237aca029029d21864a902e27b0" +dependencies = [ + "itoa", + "libc", + "num_threads", +] + [[package]] name = "unicode-ident" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +[[package]] +name = "unicode-linebreak" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f" +dependencies = [ + "regex", +] + +[[package]] +name = "unicode-width" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" + [[package]] name = "uwuc" version = "0.1.0" @@ -211,6 +508,17 @@ dependencies = [ "parser", ] +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "winapi" version = "0.3.9" @@ -227,12 +535,27 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "xml-rs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/parser/src/ast.rs b/parser/src/ast.rs index 2edee35..921ba30 100644 --- a/parser/src/ast.rs +++ b/parser/src/ast.rs @@ -37,10 +37,39 @@ pub struct DeclSpec { pub attrs: DeclAttr, } +#[derive(Debug, DebugPls)] +pub enum Declaration { + Normal { + decl_spec: DeclSpec, + name: Option, + initializer: Option<()>, + pointer: bool, + }, + StaticAssert, +} + +#[derive(Debug, DebugPls)] +pub struct Declarator { + pub identifier: String, + pub pointer: bool, +} + +#[derive(Debug, DebugPls)] +pub struct FunctionParamDecl { + pub decl_spec: DeclSpec, + pub declarator: Declarator, +} + +#[derive(Debug, DebugPls)] +pub enum FunctionParameters { + Void(Span), + List(Vec>), +} + #[derive(Debug, DebugPls)] pub struct FunctionDefinition { pub decl_spec: Spanned, pub declarator: Spanned, - pub declaration_list: Spanned>, + pub declaration_list: FunctionParameters, pub body: Vec<()>, -} \ No newline at end of file +} diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 0837772..f931b59 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -1,12 +1,14 @@ #![allow(dead_code)] #![warn(rust_2018_idioms)] +use std::fmt::Debug; + mod ast; mod parser; mod pre; mod token; -#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +#[derive(PartialEq, Eq, Clone, Copy, Default)] pub struct Span { pub start: usize, pub end: usize, @@ -23,7 +25,15 @@ impl Span { } impl dbg_pls::DebugPls for Span { - fn fmt(&self, f: dbg_pls::Formatter<'_>) {} + fn fmt(&self, f: dbg_pls::Formatter<'_>) { + dbg_pls::DebugPls::fmt(&(self.start..self.end), f) + } +} + +impl Debug for Span { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + Debug::fmt(&(self.start..self.end), f) + } } pub fn parse_file(src: &str) { diff --git a/parser/src/parser.rs b/parser/src/parser.rs index bdddd32..06b677f 100644 --- a/parser/src/parser.rs +++ b/parser/src/parser.rs @@ -1,12 +1,16 @@ use peekmore::PeekMoreIterator; use crate::{ - ast::{DeclAttr, DeclSpec, FunctionDefinition, Spanned, TypeSpecifier}, + ast::{ + DeclAttr, DeclSpec, Declaration, Declarator, FunctionDefinition, FunctionParamDecl, + FunctionParameters, Spanned, TypeSpecifier, + }, + pre::Punctuator as Punct, token::{Keyword as Kw, Token as Tok}, Span, }; -use crate::pre::Punctuator; +#[derive(Debug)] struct ParserError { span: Span, message: String, @@ -42,18 +46,49 @@ macro_rules! expect { (token, span) => { return Err(ParserError::new( span, - format!(concat!("expected `", stringify!($pat), "`, found {}"), token), + format!( + concat!("expected `", stringify!($pat), "`, found {}"), + token + ), )) } } }; } +/// Can be called for the start of a sequence of tokens that could be a type. +#[rustfmt::skip] +fn is_tok_start_of_ty(tok: &Tok<'_>) -> bool { + match tok { + Tok::Kw( + // storage specifiers + Kw::Typedef | Kw::Extern | Kw::Static | Kw::ThreadLocal | Kw::Auto | Kw::Register + // primitive types + | Kw::Void | Kw::Char | Kw::Short | Kw::Int | Kw::Long | Kw::Float | Kw::Double + | Kw::Signed | Kw::Unsigned | Kw::Bool | Kw::Complex + // struct-union-enum + | Kw::Struct | Kw::Union | Kw::Enum + // atomic + | Kw::Atomic + // type qualifiers + | Kw::Const | Kw::Restrict | Kw::Volatile /* atomic too */ + // function specifiers + | Kw::Inline | Kw::Noreturn + ) => true, + Tok::Identifier(_) => false, // TODO: lookup typedefs! + _ => false, + } +} + impl<'src, I> Parser<'src, I> where I: Iterator, Span)>, { - fn find_typedef(&self, ident: &str) -> Option<()> { + // ----------------------- + // Helpers + // ----------------------- + + fn find_typedef(&self, _: &str) -> Option<()> { None // TODO: this } @@ -65,6 +100,10 @@ where self.lex.peek().ok_or_else(ParserError::eof) } + fn peek_t_n(&mut self, n: usize) -> Result<&(Tok<'src>, Span)> { + self.lex.peek_nth(n).ok_or_else(ParserError::eof) + } + fn ident(&mut self) -> Result> { match self.next_t()? { (Tok::Identifier(ident), span) => Ok((ident.to_string(), span)), @@ -75,6 +114,13 @@ where } } + fn is_peek_tok_start_of_ty(&mut self) -> bool { + match self.peek_t() { + Ok((tok, _)) => is_tok_start_of_ty(tok), + Err(_) => false, + } + } + // ----------------------- // Declarations // ----------------------- @@ -82,8 +128,25 @@ where /// (6.7) declaration: /// declaration-specifiers init-declarator-listopt ; /// static_assert-declaration - fn declaration(&mut self) -> Result> { - todo!() + fn declaration(&mut self) -> Result> { + if let &(tok @ Tok::Kw(Kw::StaticAssert), span) = self.peek_t()? { + self.next_t()?; + return Err(ParserError::unsupported(span, &tok)); + } + + // first, some declaration-specifiers + let _decl_spec = self.declaration_specifiers()?; + // then (optionally), a declarator + // (6.7.6) declarator: + // pointer.opt direct-declarator + if let &(tok @ Tok::Punct(Punct::Asterisk), span) = self.peek_t()? { + self.next_t()?; + return Err(ParserError::unsupported(span, &tok)); + } + + // then (optionally), an initializer + + todo!("this doesn't work like this") } /// (6.7) declaration-specifiers: @@ -169,7 +232,7 @@ where /// (6.7.6) declarator: /// pointer.opt direct-declarator - fn declarator(&mut self) -> Result> { + fn declarator(&mut self) -> Result> { todo!() } @@ -180,7 +243,7 @@ where /// (6.9) external-declaration: /// function-definition /// declaration - fn external_declaration(&mut self) -> Result<()> { + fn external_declaration(&mut self) -> Result> { let (next, span) = self.peek_t()?; if let Tok::Kw(Kw::StaticAssert) = next { return Err(ParserError::unsupported(*span, next)); @@ -190,13 +253,18 @@ where // TODO: We just assume that it's a function, that's terrible! - self.function_definition(decl_spec)?; - - todo!() + self.function_definition(decl_spec) } /// (6.9.1) function-definition: /// declaration-specifiers declarator declaration-list.opt compound-statement + /// IMPORTANT TODO DO NOT FORGET THIS IS MISSION CRITICAL + /// THERE ARE RULES FOR parameter-type-list + /// WE ARE IN direct-declarator HERE + /// USE THIS + /// DO NOT DO THIS WRONGLY + /// C IS ONLY HALF HAS SHITTY AS IT SOUNDS + /// OK BUT HALF IS STILL A LOT fn function_definition( &mut self, decl_spec: Spanned, @@ -205,18 +273,67 @@ where let decl_spec_span = decl_spec.1; + expect!(self, Tok::Punct(Punct::ParenOpen)); + + let declaration_list = self.function_param_declaration_list()?; + + expect!(self, Tok::Punct(Punct::ParenClose)); + + expect!(self, Tok::Punct(Punct::BraceOpen)); + let def = FunctionDefinition { decl_spec, declarator, - declaration_list: (Vec::new(), Span::default()), + declaration_list, body: Vec::new(), }; - expect!(self, Tok::Punctuator(Punctuator::ParenOpen)); - expect!(self, Tok::Punctuator(Punctuator::ParenClose)); - expect!(self, Tok::Punctuator(Punctuator::BraceOpen)); - let last = expect!(self, Tok::Punctuator(Punctuator::BraceClose)); + let last = expect!(self, Tok::Punct(Punct::BraceClose)); Ok((def, decl_spec_span.extend(last))) } + + fn function_param_declaration_list(&mut self) -> Result { + // If the declarator includes a parameter type list, the declaration of each parameter shall + // include an identifier, except for the special case of a parameter list consisting of a single + // parameter of type void, in which case there shall not be an identifier. No declaration list + // shall follow. + if let &(Tok::Kw(Kw::Void), span) = self.peek_t()? { + if let (Tok::Punct(Punct::ParenClose), _) = self.peek_t_n(1)? { + self.next_t()?; + return Ok(FunctionParameters::Void(span)); + } + } + + let mut params = Vec::new(); + + if self.is_peek_tok_start_of_ty() { + let (decl_spec, span1) = self.declaration_specifiers()?; + let (declarator, span2) = self.declarator()?; + let param = FunctionParamDecl { + decl_spec, + declarator, + }; + + params.push((param, span1.extend(span2))); + } + + while self.is_peek_tok_start_of_ty() { + expect!(self, Tok::Punct(Punct::Comma)); + let (decl_spec, span1) = self.declaration_specifiers()?; + let (declarator, span2) = self.declarator()?; + let param = FunctionParamDecl { + decl_spec, + declarator, + }; + + params.push((param, span1.extend(span2))); + + } + + Ok(FunctionParameters::List(params)) + } } + +#[cfg(test)] +mod tests; diff --git a/parser/src/parser/snapshots/parser__parser__tests__empty_funky_attributes_no_params_function.snap b/parser/src/parser/snapshots/parser__parser__tests__empty_funky_attributes_no_params_function.snap new file mode 100644 index 0000000..1b6d7f9 --- /dev/null +++ b/parser/src/parser/snapshots/parser__parser__tests__empty_funky_attributes_no_params_function.snap @@ -0,0 +1,30 @@ +--- +source: parser/src/parser/tests.rs +expression: parsed +--- +Ok( + ( + FunctionDefinition { + decl_spec: ( + DeclSpec { + ty: Int, + attrs: DeclAttr { + is_extern: true, + is_static: false, + is_thread_local: true, + }, + }, + 1..34, + ), + declarator: ( + "uwu", + 35..38, + ), + declaration_list: List( + [], + ), + body: [], + }, + 1..43, + ), +) diff --git a/parser/src/parser/snapshots/parser__parser__tests__empty_void_function.snap b/parser/src/parser/snapshots/parser__parser__tests__empty_void_function.snap new file mode 100644 index 0000000..476dfa4 --- /dev/null +++ b/parser/src/parser/snapshots/parser__parser__tests__empty_void_function.snap @@ -0,0 +1,30 @@ +--- +source: parser/src/parser/tests.rs +expression: parsed +--- +Ok( + ( + FunctionDefinition { + decl_spec: ( + DeclSpec { + ty: Void, + attrs: DeclAttr { + is_extern: false, + is_static: false, + is_thread_local: false, + }, + }, + 1..5, + ), + declarator: ( + "uwu", + 6..9, + ), + declaration_list: List( + [], + ), + body: [], + }, + 1..14, + ), +) diff --git a/parser/src/parser/tests.rs b/parser/src/parser/tests.rs new file mode 100644 index 0000000..664fe6a --- /dev/null +++ b/parser/src/parser/tests.rs @@ -0,0 +1,55 @@ +use std::fmt::Debug; + +use super::{Parser, Tok}; +use crate::Span; + +fn lex_and_pre<'src>(src: &'src str) -> impl Iterator, Span)> + 'src { + let pre_tokens = crate::pre::preprocess_tokens(src); + crate::token::pre_tokens_to_tokens(pre_tokens) +} + +fn the_current_root_parse_thing<'src>(src: impl Iterator, Span)>) -> impl Debug { + use peekmore::PeekMore; + + let mut parser = Parser { + lex: src.peekmore(), + }; + + parser.external_declaration() +} + +macro_rules! parse_test { + ($src:expr) => { + let lexer = lex_and_pre($src); + let parsed = the_current_root_parse_thing(lexer); + insta::assert_debug_snapshot!(parsed); + }; +} + +#[test] +fn empty_void_function() { + let src = r#" +void uwu() {} + "#; + + parse_test!(src); +} + +#[test] +fn empty_funky_attributes_no_params_function() { + let src = r#" +extern volatile _Thread_local int uwu() {} + "#; + + parse_test!(src); +} + +#[test] +#[ignore = "fix declarator mess"] +fn empty_function_with_params() { + let src = r#" +int uwu(long owo, unsigned qwq) {} + "#; + + parse_test!(src); +} \ No newline at end of file diff --git a/parser/src/pre/lexer.rs b/parser/src/pre/lexer.rs index 603959c..5298158 100644 --- a/parser/src/pre/lexer.rs +++ b/parser/src/pre/lexer.rs @@ -9,7 +9,7 @@ use peekmore::PeekMore; use crate::Span; -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum PToken<'src> { HeaderName(&'src str), Identifier(&'src str), @@ -21,7 +21,7 @@ pub enum PToken<'src> { Error, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Punctuator { /// [ <: BracketOpen, diff --git a/parser/src/snapshots/parser__token__tests__hello_world.snap b/parser/src/snapshots/parser__token__tests__hello_world.snap index 7648405..64966bb 100644 --- a/parser/src/snapshots/parser__token__tests__hello_world.snap +++ b/parser/src/snapshots/parser__token__tests__hello_world.snap @@ -4,7 +4,7 @@ expression: tokens --- [ ( - Keyword( + Kw( Int, ), 1..4, @@ -16,19 +16,19 @@ expression: tokens 5..9, ), ( - Punctuator( + Punct( ParenOpen, ), 9..10, ), ( - Punctuator( + Punct( ParenClose, ), 10..11, ), ( - Punctuator( + Punct( BraceOpen, ), 12..13, @@ -40,7 +40,7 @@ expression: tokens 18..22, ), ( - Punctuator( + Punct( ParenOpen, ), 22..23, @@ -52,19 +52,19 @@ expression: tokens 23..37, ), ( - Punctuator( + Punct( ParenClose, ), 38..39, ), ( - Punctuator( + Punct( Semicolon, ), 39..40, ), ( - Punctuator( + Punct( BraceClose, ), 41..42, diff --git a/parser/src/token.rs b/parser/src/token.rs index 92802a8..fa9f07c 100644 --- a/parser/src/token.rs +++ b/parser/src/token.rs @@ -11,17 +11,17 @@ use crate::{ /// constant /// string-literal /// punctuator -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Token<'src> { Kw(Keyword), Identifier(&'src str), Constant(Constant), StringLiteral(&'src str), - Punctuator(Punctuator), + Punct(Punctuator), Error, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Keyword { Auto, Break, @@ -69,7 +69,7 @@ pub enum Keyword { ThreadLocal, } -#[derive(Debug)] +#[derive(Debug, Clone, Copy)] pub enum Constant { Int(i128), Float(f64), @@ -147,7 +147,7 @@ pub fn pre_tokens_to_tokens<'src>( .unwrap_or(Token::Error), PToken::CharConstant(u8) => Token::Constant(Constant::Char(u8)), PToken::StringLiteral(lit) => Token::StringLiteral(lit), - PToken::Punctuator(p) => Token::Punctuator(p), + PToken::Punctuator(p) => Token::Punct(p), PToken::OtherNonWs(_) => Token::Error, PToken::Error => Token::Error, }; @@ -162,7 +162,7 @@ impl Display for Token<'_> { 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::Punct(p) => Display::fmt(p, f), Token::Error => f.write_str(""), } } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..e69de29