parse some things

This commit is contained in:
nora 2022-06-21 21:51:26 +02:00
parent eb68c2b207
commit 5cf64dfc55
4 changed files with 150 additions and 9 deletions

View file

@ -23,3 +23,16 @@ pub enum TypeSpecifier {
// enum-specifier
// typedef-name
}
#[derive(Debug, Default, DebugPls)]
pub struct DeclAttr {
pub is_extern: bool,
pub is_static: bool,
pub is_thread_local: bool,
}
#[derive(Debug, DebugPls)]
pub struct DeclSpec {
pub ty: TypeSpecifier,
pub attrs: DeclAttr,
}

View file

@ -6,7 +6,21 @@ mod parser;
mod pre;
mod token;
pub type Span = std::ops::Range<usize>;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub struct Span {
pub start: usize,
pub end: usize,
}
impl Span {
pub fn start_end(start: usize, end: usize) -> Self {
Self { start, end }
}
pub fn extend(&self, rhs: Self) -> Self {
Self::start_end(self.start, rhs.end)
}
}
pub fn parse_file(src: &str) {
println!("{src}");

View file

@ -1,7 +1,7 @@
use peekmore::PeekMoreIterator;
use crate::{
ast::{Spanned, TypeSpecifier},
ast::{DeclAttr, DeclSpec, Spanned, TypeSpecifier},
token::{Keyword as Kw, Token as Tok},
Span,
};
@ -17,7 +17,11 @@ impl ParserError {
}
fn eof() -> Self {
Self::new(0..0, "unexpected end of file".to_string())
Self::new(Span::default(), "unexpected end of file".to_string())
}
fn unsupported(span: Span, token: &Tok<'_>) -> Self {
Self::new(span, format!("`{token}` is not supported"))
}
}
@ -34,6 +38,86 @@ impl<'src, I> Parser<'src, I>
where
I: Iterator<Item = (Tok<'src>, Span)>,
{
fn find_typedef(&self, ident: &str) -> Option<()> {
None // TODO: this
}
fn next_t(&mut self) -> Result<(Tok<'src>, Span)> {
self.lex.next().ok_or_else(ParserError::eof)
}
fn peek_t(&mut self) -> Result<&(Tok<'src>, Span)> {
self.lex.peek().ok_or_else(ParserError::eof)
}
// -----------------------
// Declarations
// -----------------------
/// (6.7) declaration:
/// declaration-specifiers init-declarator-listopt ;
/// static_assert-declaration
fn declaration(&mut self) -> Result<Spanned<()>> {
todo!()
}
/// (6.7) declaration-specifiers:
/// storage-class-specifier declaration-specifiers.opt
/// type-specifier declaration-specifiers.opt
/// type-qualifier declaration-specifiers.opt
/// function-specifier declaration-specifiers.opt
/// alignment-specifier declaration-specifiers.opt
fn declaration_specifiers(&mut self) -> Result<Spanned<DeclSpec>> {
let mut decl_attr = DeclAttr::default();
let &(_, initial_span) = self.peek_t()?;
let (ty, span) = loop {
match self.peek_t()?.0 {
// (6.7.1) storage-class-specifier
Tok::Kw(Kw::Typedef | Kw::Auto | Kw::Register) => {
self.next_t()?; // ignore
}
Tok::Kw(Kw::Extern) => {
self.next_t()?;
decl_attr.is_extern = true;
}
Tok::Kw(Kw::Static) => {
self.next_t()?;
decl_attr.is_static = true;
}
Tok::Kw(Kw::ThreadLocal) => {
self.next_t()?;
decl_attr.is_thread_local = true;
}
// (6.7.3) type-qualifier:
Tok::Kw(Kw::Const | Kw::Restrict | Kw::Volatile | Kw::Atomic) => {
self.next_t()?; // ignore
}
// (6.7.4) function-specifier:
Tok::Kw(Kw::Inline | Kw::Noreturn) => {
self.next_t()?; // ignore
}
// (6.7.5) alignment-specifier:
Tok::Kw(Kw::Alignas) => {
let (token, span) = self.next_t()?;
return Err(ParserError::unsupported(span, &token));
}
// if it's neither of the above, it has to be a type-specifier
_ => {
let ty = self.type_specifier()?;
break ty;
}
}
};
Ok((
DeclSpec {
ty,
attrs: decl_attr,
},
initial_span.extend(span),
))
}
fn type_specifier(&mut self) -> Result<Spanned<TypeSpecifier>> {
let (token, span) = self.next_t()?;
let ty = match token {
@ -47,13 +131,43 @@ where
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::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)
// -----------------------
// External definitions
// -----------------------
/// (6.9) external-declaration:
/// function-definition
/// declaration
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));
}
let decl_spec = self.declaration_specifiers()?;
// TODO: We just assume that it's a function, that's terrible!
self.function_definition(decl_spec)?;
todo!()
}
/// (6.9.1) function-definition:
/// declaration-specifiers declarator declaration-list.opt compound-statement
fn function_definition(&mut self, specifiers: Spanned<DeclSpec>) -> Result<Spanned<()>> {
todo!()
}
}

View file

@ -3,7 +3,7 @@
//!
//! Code might be bad. Possibly.
use std::{ops::Not, fmt::Display};
use std::{fmt::Display, ops::Not};
use peekmore::PeekMore;
@ -398,11 +398,11 @@ where
}
};
Some((token, start_span..end_span + 1))
Some((token, Span::start_end(start_span, end_span + 1)))
}
}
pub fn preprocess_tokens(src: &str) -> impl Iterator<Item = (PToken<'_>, std::ops::Range<usize>)> {
pub fn preprocess_tokens(src: &str) -> impl Iterator<Item = (PToken<'_>, Span)> {
let lexer = PLexer {
src_str: src,
src: src.bytes().enumerate().peekmore(),