some stuff works

This commit is contained in:
nora 2022-06-25 22:34:07 +02:00
parent 4b646b9128
commit 79ab4bbb75
7 changed files with 239 additions and 100 deletions

View file

@ -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,

View file

@ -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)]

View file

@ -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,
),
],
)

View file

@ -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: [

View file

@ -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: [
(

View file

@ -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,
),
],
)

View file

@ -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();
"#
);
}