mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
some stuff works
This commit is contained in:
parent
4b646b9128
commit
79ab4bbb75
7 changed files with 239 additions and 100 deletions
|
|
@ -1,6 +1,8 @@
|
|||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
use dbg_pls::DebugPls;
|
||||
|
||||
use crate::{Span, Spanned};
|
||||
use crate::Spanned;
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub enum TypeSpecifier {
|
||||
|
|
@ -24,13 +26,45 @@ pub enum TypeSpecifier {
|
|||
|
||||
pub type Ident = Spanned<String>;
|
||||
|
||||
#[derive(Debug, Default, DebugPls)]
|
||||
#[derive(Default)]
|
||||
pub struct DeclAttr {
|
||||
pub is_extern: bool,
|
||||
pub is_static: bool,
|
||||
pub is_thread_local: bool,
|
||||
}
|
||||
|
||||
impl Debug for DeclAttr {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
let mut d = f.debug_set();
|
||||
if self.is_extern {
|
||||
d.entry(&"extern");
|
||||
}
|
||||
if self.is_static {
|
||||
d.entry(&"static");
|
||||
}
|
||||
if self.is_thread_local {
|
||||
d.entry(&"thread_local");
|
||||
}
|
||||
d.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl DebugPls for DeclAttr {
|
||||
fn fmt(&self, f: dbg_pls::Formatter<'_>) {
|
||||
let mut d = f.debug_set();
|
||||
if self.is_extern {
|
||||
d = d.entry(&"extern");
|
||||
}
|
||||
if self.is_static {
|
||||
d = d.entry(&"static");
|
||||
}
|
||||
if self.is_thread_local {
|
||||
d = d.entry(&"thread_local");
|
||||
}
|
||||
d.finish();
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub struct DeclSpec {
|
||||
pub ty: TypeSpecifier,
|
||||
|
|
@ -55,12 +89,18 @@ pub struct NormalDecl {
|
|||
pub init_declarators: Vec<Spanned<InitDecl>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub struct FunctionParamDecl {
|
||||
pub decl_spec: Spanned<DeclSpec>,
|
||||
pub declarator: Spanned<Declarator>,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub enum DirectDeclarator {
|
||||
Ident(Ident),
|
||||
WithParams {
|
||||
ident: Ident,
|
||||
params: Vec<NormalDecl>,
|
||||
params: Vec<FunctionParamDecl>,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -70,18 +110,6 @@ pub struct Declarator {
|
|||
pub pointer: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub struct FunctionParamDecl {
|
||||
pub decl_spec: DeclSpec,
|
||||
pub declarator: Declarator,
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub enum FunctionParams {
|
||||
Void(Span),
|
||||
List(Vec<Spanned<NormalDecl>>),
|
||||
}
|
||||
|
||||
#[derive(Debug, DebugPls)]
|
||||
pub struct FunctionDef {
|
||||
pub declaration: Decl,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use peekmore::PeekMoreIterator;
|
|||
use crate::{
|
||||
ast::{
|
||||
Decl, DeclAttr, DeclSpec, Declarator, DirectDeclarator, ExternalDecl, FunctionDef,
|
||||
FunctionParams, Ident, InitDecl, NormalDecl, TypeSpecifier,
|
||||
FunctionParamDecl, Ident, InitDecl, NormalDecl, TypeSpecifier,
|
||||
},
|
||||
pre::Punctuator as Punct,
|
||||
token::{Keyword as Kw, Token as Tok},
|
||||
|
|
@ -154,14 +154,14 @@ where
|
|||
// -----------------------
|
||||
|
||||
/// (6.7) declaration:
|
||||
/// declaration-specifiers init-declarator-listopt ;
|
||||
/// declaration-specifiers init-declarator-list.opt ;
|
||||
/// static_assert-declaration
|
||||
fn declaration(&mut self) -> Result<Spanned<Decl>> {
|
||||
if let Some((tok, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) {
|
||||
return Err(ParserError::unsupported(span, &tok));
|
||||
}
|
||||
|
||||
let (decl_spec, span) = self.declaration_specifiers()?;
|
||||
let (decl_spec, span) = self.decl_specifiers()?;
|
||||
|
||||
let init_declarators = self.init_declarator_list()?;
|
||||
let init_declarators_span = Span::span_of_spanned_list(&init_declarators);
|
||||
|
|
@ -187,11 +187,7 @@ where
|
|||
fn init_declarator_list(&mut self) -> Result<Vec<Spanned<InitDecl>>> {
|
||||
let mut init_decls = Vec::new();
|
||||
let mut first = true;
|
||||
loop {
|
||||
println!("LOOOOP");
|
||||
if !self.is_peek_tok_start_of_declarator() && !self.is_peek_comma() {
|
||||
break;
|
||||
}
|
||||
while self.is_peek_tok_start_of_declarator() || self.is_peek_comma() {
|
||||
if !first {
|
||||
expect!(self, Tok::Punct(Punct::Comma));
|
||||
}
|
||||
|
|
@ -217,7 +213,7 @@ where
|
|||
/// type-qualifier declaration-specifiers.opt
|
||||
/// function-specifier declaration-specifiers.opt
|
||||
/// alignment-specifier declaration-specifiers.opt
|
||||
fn declaration_specifiers(&mut self) -> Result<Spanned<DeclSpec>> {
|
||||
fn decl_specifiers(&mut self) -> Result<Spanned<DeclSpec>> {
|
||||
let mut decl_attr = DeclAttr::default();
|
||||
let &(_, initial_span) = self.peek_t()?;
|
||||
let (ty, span) = loop {
|
||||
|
|
@ -299,48 +295,72 @@ where
|
|||
/// facing. For example: `int uwu` vs `int uwu()`. The parentheses indicate a function
|
||||
/// declaration. Therefore, we have no idea what we're parsing before entering this function.
|
||||
fn declarator(&mut self) -> Result<Spanned<Declarator>> {
|
||||
if let Some((_, span)) = eat!(self, Tok::Punct(Punct::Asterisk)) {
|
||||
let (decl, span2) = self.direct_declarator()?;
|
||||
|
||||
Ok((
|
||||
Declarator {
|
||||
decl,
|
||||
pointer: true,
|
||||
},
|
||||
span.extend(span2),
|
||||
))
|
||||
let pointer_span = if let Some((_, span)) = eat!(self, Tok::Punct(Punct::Asterisk)) {
|
||||
Some(span)
|
||||
} else {
|
||||
let (decl, span) = self.direct_declarator()?;
|
||||
None
|
||||
};
|
||||
|
||||
Ok((
|
||||
Declarator {
|
||||
decl,
|
||||
pointer: false,
|
||||
},
|
||||
span,
|
||||
))
|
||||
}
|
||||
let (decl, span) = self.direct_declarator()?;
|
||||
|
||||
let declarator = Declarator {
|
||||
decl,
|
||||
pointer: pointer_span.is_some(),
|
||||
};
|
||||
|
||||
let span = pointer_span.map(|s| s.extend(span)).unwrap_or(span);
|
||||
|
||||
Ok((declarator, span))
|
||||
}
|
||||
|
||||
/// direct-declarator:
|
||||
/// identifier
|
||||
/// ( declarator )
|
||||
/// direct-declarator \[ type-qualifier-listopt assignment-expressionopt ]
|
||||
/// direct-declarator \[ static type-qualifier-listopt assignment-expression ]
|
||||
/// direct-declarator \[ type-qualifier-list.opt assignment-expression.opt ]
|
||||
/// direct-declarator \[ static type-qualifier-list.opt assignment-expression ]
|
||||
/// direct-declarator \[ type-qualifier-list static assignment-expression ]
|
||||
/// direct-declarator \[ type-qualifier-listopt * ]
|
||||
/// direct-declarator \[ type-qualifier-list.opt * ]
|
||||
/// direct-declarator ( parameter-type-list )
|
||||
/// direct-declarator ( identifier-listopt )
|
||||
/// direct-declarator ( identifier-list.opt )
|
||||
fn direct_declarator(&mut self) -> Result<Spanned<DirectDeclarator>> {
|
||||
let (ident, span) = self.ident()?;
|
||||
|
||||
if (eat!(self, Tok::Punct(Punct::ParenOpen))).is_some() {
|
||||
let mut params = Vec::new();
|
||||
let mut first = true;
|
||||
|
||||
while self.is_peek_tok_start_of_ty() || self.is_peek_comma() {
|
||||
if first {
|
||||
// the wrong way around because borrowing
|
||||
if let (Tok::Punct(Punct::ParenClose), _) = self.peek_t_n(1)? {
|
||||
if let &(ref tok @ Tok::Kw(Kw::Void), span) = self.peek_t()? {
|
||||
return Err(ParserError::unsupported(span, tok));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !first {
|
||||
expect!(self, Tok::Punct(Punct::Comma));
|
||||
}
|
||||
first = false;
|
||||
|
||||
let decl_spec = self.decl_specifiers()?;
|
||||
// abstract declarator actually
|
||||
let declarator = self.declarator()?;
|
||||
|
||||
let function_param_decl = FunctionParamDecl {
|
||||
decl_spec,
|
||||
declarator,
|
||||
};
|
||||
params.push(function_param_decl);
|
||||
}
|
||||
|
||||
// nothing in the params supported yet.
|
||||
expect!(self, Tok::Punct(Punct::ParenClose));
|
||||
return Ok((
|
||||
DirectDeclarator::WithParams {
|
||||
ident: (ident, span),
|
||||
params: Vec::new(),
|
||||
params,
|
||||
},
|
||||
span,
|
||||
));
|
||||
|
|
@ -384,22 +404,6 @@ where
|
|||
}
|
||||
Ok(decls)
|
||||
}
|
||||
|
||||
fn function_param_declaration_list(&mut self) -> Result<FunctionParams> {
|
||||
// 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()?;
|
||||
self.next_t()?;
|
||||
return Ok(FunctionParams::Void(span));
|
||||
}
|
||||
}
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
---
|
||||
source: parser/src/parser/tests.rs
|
||||
expression: parsed
|
||||
---
|
||||
Ok(
|
||||
[
|
||||
(
|
||||
FunctionDef(
|
||||
FunctionDef {
|
||||
declaration: Normal(
|
||||
NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Int,
|
||||
attrs: {},
|
||||
},
|
||||
init_declarators: [
|
||||
(
|
||||
InitDecl {
|
||||
declarator: Declarator {
|
||||
decl: WithParams {
|
||||
ident: (
|
||||
"uwu",
|
||||
5..8,
|
||||
),
|
||||
params: [
|
||||
FunctionParamDecl {
|
||||
decl_spec: (
|
||||
DeclSpec {
|
||||
ty: Long,
|
||||
attrs: {},
|
||||
},
|
||||
9..13,
|
||||
),
|
||||
declarator: (
|
||||
Declarator {
|
||||
decl: Ident(
|
||||
(
|
||||
"owo",
|
||||
14..17,
|
||||
),
|
||||
),
|
||||
pointer: false,
|
||||
},
|
||||
14..17,
|
||||
),
|
||||
},
|
||||
FunctionParamDecl {
|
||||
decl_spec: (
|
||||
DeclSpec {
|
||||
ty: Int,
|
||||
attrs: {},
|
||||
},
|
||||
19..22,
|
||||
),
|
||||
declarator: (
|
||||
Declarator {
|
||||
decl: Ident(
|
||||
(
|
||||
"qwq",
|
||||
23..26,
|
||||
),
|
||||
),
|
||||
pointer: false,
|
||||
},
|
||||
23..26,
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
pointer: false,
|
||||
},
|
||||
init: None,
|
||||
},
|
||||
5..8,
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
body: [],
|
||||
},
|
||||
),
|
||||
1..30,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
@ -11,10 +11,9 @@ Ok(
|
|||
NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Int,
|
||||
attrs: DeclAttr {
|
||||
is_extern: true,
|
||||
is_static: false,
|
||||
is_thread_local: true,
|
||||
attrs: {
|
||||
"extern",
|
||||
"thread_local",
|
||||
},
|
||||
},
|
||||
init_declarators: [
|
||||
|
|
|
|||
|
|
@ -11,11 +11,7 @@ Ok(
|
|||
NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Void,
|
||||
attrs: DeclAttr {
|
||||
is_extern: false,
|
||||
is_static: false,
|
||||
is_thread_local: false,
|
||||
},
|
||||
attrs: {},
|
||||
},
|
||||
init_declarators: [
|
||||
(
|
||||
|
|
|
|||
|
|
@ -10,11 +10,7 @@ Ok(
|
|||
NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Int,
|
||||
attrs: DeclAttr {
|
||||
is_extern: false,
|
||||
is_static: false,
|
||||
is_thread_local: false,
|
||||
},
|
||||
attrs: {},
|
||||
},
|
||||
init_declarators: [
|
||||
(
|
||||
|
|
@ -44,10 +40,8 @@ Ok(
|
|||
NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Double,
|
||||
attrs: DeclAttr {
|
||||
is_extern: false,
|
||||
is_static: false,
|
||||
is_thread_local: true,
|
||||
attrs: {
|
||||
"thread_local",
|
||||
},
|
||||
},
|
||||
init_declarators: [
|
||||
|
|
@ -87,5 +81,36 @@ Ok(
|
|||
),
|
||||
11..40,
|
||||
),
|
||||
(
|
||||
Decl(
|
||||
Normal(
|
||||
NormalDecl {
|
||||
decl_spec: DeclSpec {
|
||||
ty: Int,
|
||||
attrs: {},
|
||||
},
|
||||
init_declarators: [
|
||||
(
|
||||
InitDecl {
|
||||
declarator: Declarator {
|
||||
decl: WithParams {
|
||||
ident: (
|
||||
"function",
|
||||
68..76,
|
||||
),
|
||||
params: [],
|
||||
},
|
||||
pointer: false,
|
||||
},
|
||||
init: None,
|
||||
},
|
||||
68..76,
|
||||
),
|
||||
],
|
||||
},
|
||||
),
|
||||
),
|
||||
64..76,
|
||||
),
|
||||
],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::fmt::Debug;
|
|||
use super::{Parser, Tok};
|
||||
use crate::Span;
|
||||
|
||||
fn lex_and_pre<'src>(src: &'src str) -> impl Iterator<Item = (Tok<'src>, Span)> + 'src {
|
||||
fn lex_and_pre(src: &str) -> impl Iterator<Item = (Tok<'_>, Span)> + '_ {
|
||||
let pre_tokens = crate::pre::preprocess_tokens(src);
|
||||
crate::token::pre_tokens_to_tokens(pre_tokens)
|
||||
}
|
||||
|
|
@ -28,38 +28,40 @@ macro_rules! parse_test {
|
|||
|
||||
#[test]
|
||||
fn empty_void_function() {
|
||||
let src = r#"
|
||||
parse_test!(
|
||||
r#"
|
||||
void uwu() {}
|
||||
"#;
|
||||
|
||||
parse_test!(src);
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_funky_attributes_no_params_function() {
|
||||
let src = r#"
|
||||
parse_test!(
|
||||
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);
|
||||
parse_test!(
|
||||
r#"
|
||||
int uwu(long owo, int qwq) {}
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn global_variable_declarations() {
|
||||
let src = r#"
|
||||
parse_test!(
|
||||
r#"
|
||||
int test;
|
||||
_Thread_local double uwu, owo;
|
||||
"#;
|
||||
|
||||
parse_test!(src);
|
||||
// oh no, a function
|
||||
int function();
|
||||
"#
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue