mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-17 01:55:07 +01:00
parse decl statements
This commit is contained in:
parent
8093f87fc3
commit
727cfc692c
5 changed files with 293 additions and 33 deletions
|
|
@ -91,7 +91,8 @@ pub enum Expr {
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
pub enum Stmt {
|
pub enum Stmt {
|
||||||
Labeled(Box<Spanned<Stmt>>),
|
Decl(Decl),
|
||||||
|
Labeled{label: Ident, stmt: Box<Spanned<Stmt>>},
|
||||||
Compound(Vec<Spanned<Stmt>>),
|
Compound(Vec<Spanned<Stmt>>),
|
||||||
If {
|
If {
|
||||||
cond: Expr,
|
cond: Expr,
|
||||||
|
|
@ -232,7 +233,7 @@ pub struct Declarator {
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
pub struct FunctionDef {
|
pub struct FunctionDef {
|
||||||
pub decl: Decl,
|
pub decl: Decl,
|
||||||
pub body: Vec<Stmt>,
|
pub body: Vec<Spanned<Stmt>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ use peekmore::PeekMoreIterator;
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Decl, DeclAttr, DeclSpec, Declarator, DirectDeclarator, ExternalDecl, FunctionDef,
|
Decl, DeclAttr, DeclSpec, Declarator, DirectDeclarator, ExternalDecl, FunctionDef,
|
||||||
FunctionParamDecl, Ident, InitDecl, IntTy, IntTyKind, IntTySignedness, NormalDecl,
|
FunctionParamDecl, Ident, InitDecl, IntTy, IntTyKind, IntTySignedness, NormalDecl, Stmt,
|
||||||
TypeSpecifier,
|
TypeSpecifier,
|
||||||
},
|
},
|
||||||
pre::Punctuator as Punct,
|
pre::Punctuator as P,
|
||||||
token::{Keyword as Kw, Token as Tok},
|
token::{Keyword as Kw, Token as Tok},
|
||||||
Span, Spanned,
|
Span, Spanned,
|
||||||
};
|
};
|
||||||
|
|
@ -109,10 +109,7 @@ fn is_tok_start_of_ty(tok: &Tok<'_>) -> bool {
|
||||||
|
|
||||||
/// Can be called for the start of a sequence of tokens that could be a type.
|
/// Can be called for the start of a sequence of tokens that could be a type.
|
||||||
fn is_tok_start_of_declarator(tok: &Tok<'_>) -> bool {
|
fn is_tok_start_of_declarator(tok: &Tok<'_>) -> bool {
|
||||||
matches!(
|
matches!(tok, Tok::Ident(_) | Tok::Punct(P::ParenOpen | P::Asterisk))
|
||||||
tok,
|
|
||||||
Tok::Ident(_) | Tok::Punct(Punct::ParenOpen | Punct::Asterisk)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'src, I> Parser<'src, I>
|
impl<'src, I> Parser<'src, I>
|
||||||
|
|
@ -164,7 +161,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_peek_comma(&mut self) -> bool {
|
fn is_peek_comma(&mut self) -> bool {
|
||||||
matches!(self.peek_t(), Ok((Tok::Punct(Punct::Comma), _)))
|
matches!(self.peek_t(), Ok((Tok::Punct(P::Comma), _)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
@ -174,6 +171,8 @@ where
|
||||||
/// (6.7) declaration:
|
/// (6.7) declaration:
|
||||||
/// declaration-specifiers init-declarator-list.opt ;
|
/// declaration-specifiers init-declarator-list.opt ;
|
||||||
/// static_assert-declaration
|
/// static_assert-declaration
|
||||||
|
///
|
||||||
|
/// This does NOT eat the semicolon!
|
||||||
fn declaration(&mut self) -> Result<Spanned<Decl>> {
|
fn declaration(&mut self) -> Result<Spanned<Decl>> {
|
||||||
if let Some((tok, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) {
|
if let Some((tok, span)) = eat!(self, Tok::Kw(Kw::StaticAssert)) {
|
||||||
return Err(ParserError::unsupported(span, &tok));
|
return Err(ParserError::unsupported(span, &tok));
|
||||||
|
|
@ -202,17 +201,18 @@ where
|
||||||
/// init-declarator:
|
/// init-declarator:
|
||||||
/// declarator
|
/// declarator
|
||||||
/// declarator = initializer
|
/// declarator = initializer
|
||||||
|
///
|
||||||
fn init_declarator_list(&mut self) -> Result<Vec<Spanned<InitDecl>>> {
|
fn init_declarator_list(&mut self) -> Result<Vec<Spanned<InitDecl>>> {
|
||||||
let mut init_decls = Vec::new();
|
let mut init_decls = Vec::new();
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
while self.is_peek_tok_start_of_declarator() || self.is_peek_comma() {
|
while self.is_peek_tok_start_of_declarator() || self.is_peek_comma() {
|
||||||
if !first {
|
if !first {
|
||||||
expect!(self, Tok::Punct(Punct::Comma));
|
expect!(self, Tok::Punct(P::Comma));
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
let (declarator, span) = self.declarator()?;
|
let (declarator, span) = self.declarator()?;
|
||||||
let init = if eat!(self, Tok::Punct(Punct::Eq)).is_some() {
|
let init = if eat!(self, Tok::Punct(P::Eq)).is_some() {
|
||||||
let expr = self.expr()?;
|
let expr = self.expr()?;
|
||||||
Some(expr)
|
Some(expr)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -328,7 +328,9 @@ where
|
||||||
"cannot specify signedness twice".to_string(),
|
"cannot specify signedness twice".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Ok((Tok::Kw(Kw::Char | Kw::Short| Kw::Int | Kw::Long), _)) = self.peek_t() {
|
if let Ok((Tok::Kw(Kw::Char | Kw::Short | Kw::Int | Kw::Long), _)) =
|
||||||
|
self.peek_t()
|
||||||
|
{
|
||||||
// the signed is an integer qualifier
|
// the signed is an integer qualifier
|
||||||
signedness = Some(IntTySignedness::Signed);
|
signedness = Some(IntTySignedness::Signed);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -345,7 +347,9 @@ where
|
||||||
"cannot specify signedness twice".to_string(),
|
"cannot specify signedness twice".to_string(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if let Ok((Tok::Kw(Kw::Char | Kw::Short| Kw::Int | Kw::Long), _)) = self.peek_t() {
|
if let Ok((Tok::Kw(Kw::Char | Kw::Short | Kw::Int | Kw::Long), _)) =
|
||||||
|
self.peek_t()
|
||||||
|
{
|
||||||
// the unsigned is an integer qualifier
|
// the unsigned is an integer qualifier
|
||||||
signedness = Some(IntTySignedness::Unsigned);
|
signedness = Some(IntTySignedness::Unsigned);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -378,7 +382,7 @@ where
|
||||||
/// facing. For example: `int uwu` vs `int uwu()`. The parentheses indicate a function
|
/// 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.
|
/// declaration. Therefore, we have no idea what we're parsing before entering this function.
|
||||||
fn declarator(&mut self) -> Result<Spanned<Declarator>> {
|
fn declarator(&mut self) -> Result<Spanned<Declarator>> {
|
||||||
let pointer_span = if let Some((_, span)) = eat!(self, Tok::Punct(Punct::Asterisk)) {
|
let pointer_span = if let Some((_, span)) = eat!(self, Tok::Punct(P::Asterisk)) {
|
||||||
Some(span)
|
Some(span)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -408,14 +412,14 @@ where
|
||||||
fn direct_declarator(&mut self) -> Result<Spanned<DirectDeclarator>> {
|
fn direct_declarator(&mut self) -> Result<Spanned<DirectDeclarator>> {
|
||||||
let (ident, span) = self.ident()?;
|
let (ident, span) = self.ident()?;
|
||||||
|
|
||||||
if (eat!(self, Tok::Punct(Punct::ParenOpen))).is_some() {
|
if (eat!(self, Tok::Punct(P::ParenOpen))).is_some() {
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
||||||
while self.is_peek_tok_start_of_ty() || self.is_peek_comma() {
|
while self.is_peek_tok_start_of_ty() || self.is_peek_comma() {
|
||||||
if first {
|
if first {
|
||||||
// the wrong way around because borrowing
|
// the wrong way around because borrowing
|
||||||
if let (Tok::Punct(Punct::ParenClose), _) = self.peek_t_n(1)? {
|
if let (Tok::Punct(P::ParenClose), _) = self.peek_t_n(1)? {
|
||||||
if let &(ref tok @ Tok::Kw(Kw::Void), span) = self.peek_t()? {
|
if let &(ref tok @ Tok::Kw(Kw::Void), span) = self.peek_t()? {
|
||||||
return Err(ParserError::unsupported(span, tok));
|
return Err(ParserError::unsupported(span, tok));
|
||||||
}
|
}
|
||||||
|
|
@ -423,7 +427,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
if !first {
|
if !first {
|
||||||
expect!(self, Tok::Punct(Punct::Comma));
|
expect!(self, Tok::Punct(P::Comma));
|
||||||
}
|
}
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
|
|
@ -439,7 +443,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// nothing in the params supported yet.
|
// nothing in the params supported yet.
|
||||||
expect!(self, Tok::Punct(Punct::ParenClose));
|
expect!(self, Tok::Punct(P::ParenClose));
|
||||||
return Ok((
|
return Ok((
|
||||||
DirectDeclarator::WithParams {
|
DirectDeclarator::WithParams {
|
||||||
ident: (ident, span),
|
ident: (ident, span),
|
||||||
|
|
@ -452,6 +456,57 @@ where
|
||||||
Ok((DirectDeclarator::Ident((ident, span)), span))
|
Ok((DirectDeclarator::Ident((ident, span)), span))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------------
|
||||||
|
// Statements
|
||||||
|
// -----------------------
|
||||||
|
|
||||||
|
/// (6.8.2) block-item:
|
||||||
|
/// declaration
|
||||||
|
/// statement
|
||||||
|
///
|
||||||
|
/// (6.8) statement:
|
||||||
|
/// labeled-statement
|
||||||
|
/// compound-statement
|
||||||
|
/// expression-statement
|
||||||
|
/// selection-statement
|
||||||
|
/// iteration-statement
|
||||||
|
/// jump-statement
|
||||||
|
fn statement(&mut self) -> Result<Spanned<Stmt>> {
|
||||||
|
if self.is_peek_tok_start_of_ty() {
|
||||||
|
let (decl, span) = self.declaration()?;
|
||||||
|
let span2 = expect!(self, Tok::Punct(P::Semicolon));
|
||||||
|
return Ok((Stmt::Decl(decl), span.extend(span2)));
|
||||||
|
}
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// (6.8.2) compound-statement:
|
||||||
|
/// { block-item-listopt }
|
||||||
|
///
|
||||||
|
/// The leading `{` must already have been eaten
|
||||||
|
fn compound_statement(&mut self, brace_span: Span) -> Result<Spanned<Vec<Spanned<Stmt>>>> {
|
||||||
|
let mut stmts = Vec::new();
|
||||||
|
let end_span = loop {
|
||||||
|
// the end of the block
|
||||||
|
if let Some((_, span)) = eat!(self, Tok::Punct(P::BraceClose)) {
|
||||||
|
break span;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty expression statements
|
||||||
|
// (6.8.3) expression-statement:
|
||||||
|
// expression.opt ;
|
||||||
|
if eat!(self, Tok::Punct(P::Semicolon)).is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: recover here
|
||||||
|
let stmt = self.statement()?;
|
||||||
|
|
||||||
|
stmts.push(stmt);
|
||||||
|
};
|
||||||
|
Ok((stmts, brace_span.extend(end_span)))
|
||||||
|
}
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// External definitions
|
// External definitions
|
||||||
// -----------------------
|
// -----------------------
|
||||||
|
|
@ -463,18 +518,18 @@ where
|
||||||
let (declaration, span) = self.declaration()?;
|
let (declaration, span) = self.declaration()?;
|
||||||
|
|
||||||
// the declaration might be a function definition
|
// the declaration might be a function definition
|
||||||
if eat!(self, Tok::Punct(Punct::BraceOpen)).is_some() {
|
if let Some((_, brace_span)) = eat!(self, Tok::Punct(P::BraceOpen)) {
|
||||||
let span2 = expect!(self, Tok::Punct(Punct::BraceClose));
|
let (body, span2) = self.compound_statement(brace_span)?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
ExternalDecl::FunctionDef(FunctionDef {
|
ExternalDecl::FunctionDef(FunctionDef {
|
||||||
decl: declaration,
|
decl: declaration,
|
||||||
body: Vec::new(),
|
body,
|
||||||
}),
|
}),
|
||||||
span.extend(span2),
|
span.extend(span2),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
expect!(self, Tok::Punct(Punct::Semicolon));
|
expect!(self, Tok::Punct(P::Semicolon));
|
||||||
Ok((ExternalDecl::Decl(declaration), span))
|
Ok((ExternalDecl::Decl(declaration), span))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -482,6 +537,7 @@ where
|
||||||
fn external_declarations(&mut self) -> Result<Vec<Spanned<ExternalDecl>>> {
|
fn external_declarations(&mut self) -> Result<Vec<Spanned<ExternalDecl>>> {
|
||||||
let mut decls = Vec::new();
|
let mut decls = Vec::new();
|
||||||
while self.peek_t().is_ok() {
|
while self.peek_t().is_ok() {
|
||||||
|
// TODO recover
|
||||||
let decl = self.external_declaration()?;
|
let decl = self.external_declaration()?;
|
||||||
decls.push(decl);
|
decls.push(decl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
---
|
||||||
|
source: parser/src/parser/tests.rs
|
||||||
|
expression: "(parsed_pretty, pretty_printed_source)"
|
||||||
|
---
|
||||||
|
(
|
||||||
|
Ok([
|
||||||
|
(
|
||||||
|
FunctionDef(FunctionDef {
|
||||||
|
decl: Normal(NormalDecl {
|
||||||
|
decl_spec: DeclSpec {
|
||||||
|
ty: Integer(IntTy { sign: Signed, kind: Int }),
|
||||||
|
attrs: "(empty)",
|
||||||
|
},
|
||||||
|
init_declarators: [
|
||||||
|
(
|
||||||
|
InitDecl {
|
||||||
|
declarator: Declarator {
|
||||||
|
decl: WithParams {
|
||||||
|
ident: ("main", 5..9),
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: None,
|
||||||
|
},
|
||||||
|
5..9,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
body: [
|
||||||
|
(
|
||||||
|
Decl(
|
||||||
|
Normal(NormalDecl {
|
||||||
|
decl_spec: DeclSpec {
|
||||||
|
ty: Integer(IntTy { sign: Signed, kind: Int }),
|
||||||
|
attrs: "(empty)",
|
||||||
|
},
|
||||||
|
init_declarators: [
|
||||||
|
(
|
||||||
|
InitDecl {
|
||||||
|
declarator: Declarator {
|
||||||
|
decl: Ident(("i", 22..23)),
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: Some((Atom(Int(0)), 26..27)),
|
||||||
|
},
|
||||||
|
22..23,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
18..28,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Decl(
|
||||||
|
Normal(NormalDecl {
|
||||||
|
decl_spec: DeclSpec {
|
||||||
|
ty: Float,
|
||||||
|
attrs: "(empty)",
|
||||||
|
},
|
||||||
|
init_declarators: [
|
||||||
|
(
|
||||||
|
InitDecl {
|
||||||
|
declarator: Declarator {
|
||||||
|
decl: Ident(("f", 39..40)),
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: Some((
|
||||||
|
Binary(ExprBinary {
|
||||||
|
lhs: (Atom(Int(1)), 43..44),
|
||||||
|
rhs: (Atom(Int(32)), 47..49),
|
||||||
|
op: Arith(Add),
|
||||||
|
}),
|
||||||
|
43..49,
|
||||||
|
)),
|
||||||
|
},
|
||||||
|
39..40,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
33..50,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
1..52,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
"int main() {\n int i = 0;\n float f = (1 + 32);\n}\n",
|
||||||
|
)
|
||||||
|
|
@ -121,3 +121,15 @@ unsigned long long int z = 26;
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn decl_stmts() {
|
||||||
|
parse_test!(
|
||||||
|
r#"
|
||||||
|
int main() {
|
||||||
|
int i = 0;
|
||||||
|
float f = 1 + 32;
|
||||||
|
}
|
||||||
|
"#
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -6,10 +6,10 @@ use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
ArithOpKind, Atom, BinaryOp, ComparisonKind, Decl, DeclAttr, DeclSpec, Declarator,
|
ArithOpKind, Atom, BinaryOp, ComparisonKind, Decl, DeclAttr, DeclSpec, Declarator,
|
||||||
DirectDeclarator, Expr, ExprBinary, ExprUnary, ExternalDecl, FunctionDef,
|
DirectDeclarator, Expr, ExprBinary, ExprUnary, ExternalDecl, FunctionDef,
|
||||||
FunctionParamDecl, InitDecl, IntTyKind, IntTySignedness, NormalDecl, TypeSpecifier,
|
FunctionParamDecl, InitDecl, IntTyKind, IntTySignedness, NormalDecl, Stmt, TypeSpecifier,
|
||||||
UnaryOp,
|
UnaryOp,
|
||||||
},
|
},
|
||||||
Spanned,
|
Span, Spanned,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PrettyPrinter<W> {
|
pub struct PrettyPrinter<W> {
|
||||||
|
|
@ -39,7 +39,6 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
|
|
||||||
fn linebreak(&mut self) -> Result {
|
fn linebreak(&mut self) -> Result {
|
||||||
self.string("\n")?;
|
self.string("\n")?;
|
||||||
self.print_indent()?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,23 +60,126 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
fn external_decl(&mut self, decl: &ExternalDecl) -> Result {
|
fn external_decl(&mut self, decl: &ExternalDecl) -> Result {
|
||||||
match decl {
|
match decl {
|
||||||
ExternalDecl::FunctionDef(def) => self.function_def(def),
|
ExternalDecl::FunctionDef(def) => self.function_def(def),
|
||||||
ExternalDecl::Decl(decl) => self.decl(decl, false),
|
ExternalDecl::Decl(decl) => {
|
||||||
|
self.decl(decl, false)?;
|
||||||
|
self.linebreak()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function_def(&mut self, def: &FunctionDef) -> Result {
|
fn function_def(&mut self, def: &FunctionDef) -> Result {
|
||||||
self.decl(&def.decl, true)?;
|
self.decl(&def.decl, true)?;
|
||||||
self.string(" {")?;
|
self.string(" ")?;
|
||||||
self.linebreak()?;
|
self.block(&def.body)?;
|
||||||
self.indent();
|
|
||||||
// TODO: body
|
|
||||||
self.dedent();
|
|
||||||
self.string("}")?;
|
|
||||||
self.linebreak()?;
|
self.linebreak()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// prints a block at the current location, stops right after the last `}`
|
||||||
|
fn block(&mut self, body: &[(Stmt, Span)]) -> Result {
|
||||||
|
self.string("{")?;
|
||||||
|
self.linebreak()?;
|
||||||
|
self.indent();
|
||||||
|
for (stmt, _) in body {
|
||||||
|
self.print_indent()?;
|
||||||
|
self.stmt(stmt)?;
|
||||||
|
self.linebreak()?;
|
||||||
|
}
|
||||||
|
self.dedent();
|
||||||
|
self.string("}")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn stmt(&mut self, stmt: &Stmt) -> Result {
|
||||||
|
match stmt {
|
||||||
|
Stmt::Decl(decl) => self.decl(decl, false),
|
||||||
|
Stmt::Labeled { label, stmt } => {
|
||||||
|
self.string(&label.0)?;
|
||||||
|
self.string(":")?;
|
||||||
|
self.linebreak()?;
|
||||||
|
self.print_indent()?;
|
||||||
|
self.stmt(&stmt.0)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Stmt::Compound(body) => self.block(body),
|
||||||
|
Stmt::If {
|
||||||
|
cond,
|
||||||
|
then,
|
||||||
|
otherwise,
|
||||||
|
} => {
|
||||||
|
self.string("if (")?;
|
||||||
|
self.expr(cond)?;
|
||||||
|
self.string(") ")?;
|
||||||
|
self.block(then)?;
|
||||||
|
if let Some(block) = otherwise {
|
||||||
|
self.string(" else ")?;
|
||||||
|
self.block(block)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Stmt::Switch => todo!(),
|
||||||
|
Stmt::While { cond, body } => {
|
||||||
|
self.string("while (")?;
|
||||||
|
self.expr(cond)?;
|
||||||
|
self.string(") ")?;
|
||||||
|
self.block(body)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Stmt::For {
|
||||||
|
init_decl,
|
||||||
|
init_expr,
|
||||||
|
cond,
|
||||||
|
post,
|
||||||
|
body,
|
||||||
|
} => {
|
||||||
|
if init_expr.is_some() {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
self.string("for (")?;
|
||||||
|
if let Some((decl, _)) = init_decl {
|
||||||
|
self.decl(decl, false)?;
|
||||||
|
} else {
|
||||||
|
self.string(";")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some((cond, _)) = cond {
|
||||||
|
self.string(" ")?;
|
||||||
|
self.expr(cond)?;
|
||||||
|
}
|
||||||
|
self.string(";")?;
|
||||||
|
|
||||||
|
if let Some((post, _)) = post {
|
||||||
|
self.string(" ")?;
|
||||||
|
self.expr(post)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.string(") ")?;
|
||||||
|
self.block(body)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Stmt::Goto((label, _)) => {
|
||||||
|
self.string("goto ")?;
|
||||||
|
self.string(label)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Stmt::Continue => self.string("continue"),
|
||||||
|
Stmt::Break => self.string("break"),
|
||||||
|
Stmt::Return(expr) => {
|
||||||
|
self.string("return")?;
|
||||||
|
if let Some((expr, _)) = expr {
|
||||||
|
self.string(" ")?;
|
||||||
|
self.expr(expr)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Stmt::Expr(expr) => self.expr(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn decl(&mut self, decl: &Decl, func: bool) -> Result {
|
fn decl(&mut self, decl: &Decl, func: bool) -> Result {
|
||||||
match decl {
|
match decl {
|
||||||
Decl::StaticAssert => todo!(),
|
Decl::StaticAssert => todo!(),
|
||||||
|
|
@ -85,7 +187,6 @@ impl<W: Write> PrettyPrinter<W> {
|
||||||
}
|
}
|
||||||
if !func {
|
if !func {
|
||||||
self.string(";")?;
|
self.string(";")?;
|
||||||
self.linebreak()?;
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue