mirror of
https://github.com/Noratrieb/uwucc.git
synced 2026-01-14 16:45:07 +01:00
start pretty printer
This commit is contained in:
parent
d90e21e06c
commit
68258a9a95
10 changed files with 604 additions and 299 deletions
|
|
@ -173,8 +173,8 @@ pub struct Declarator {
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
pub struct FunctionDef {
|
pub struct FunctionDef {
|
||||||
pub declaration: Decl,
|
pub decl: Decl,
|
||||||
pub body: Vec<Expr>,
|
pub body: Vec<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, DebugPls)]
|
#[derive(Debug, DebugPls)]
|
||||||
|
|
@ -182,3 +182,5 @@ pub enum ExternalDecl {
|
||||||
Decl(Decl),
|
Decl(Decl),
|
||||||
FunctionDef(FunctionDef),
|
FunctionDef(FunctionDef),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type TranslationUnit = Vec<ExternalDecl>;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ use crate::token::Token;
|
||||||
mod ast;
|
mod ast;
|
||||||
mod parser;
|
mod parser;
|
||||||
mod pre;
|
mod pre;
|
||||||
|
mod pretty;
|
||||||
mod token;
|
mod token;
|
||||||
|
|
||||||
pub type Spanned<T> = (T, Span);
|
pub type Spanned<T> = (T, Span);
|
||||||
|
|
|
||||||
|
|
@ -402,7 +402,7 @@ where
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
ExternalDecl::FunctionDef(FunctionDef {
|
ExternalDecl::FunctionDef(FunctionDef {
|
||||||
declaration,
|
decl: declaration,
|
||||||
body: Vec::new(),
|
body: Vec::new(),
|
||||||
}),
|
}),
|
||||||
span.extend(span2),
|
span.extend(span2),
|
||||||
|
|
|
||||||
|
|
@ -1,66 +1,69 @@
|
||||||
---
|
---
|
||||||
source: parser/src/parser/tests.rs
|
source: parser/src/parser/tests.rs
|
||||||
expression: parsed_pretty
|
expression: "(parsed_pretty, pretty_printed_source)"
|
||||||
---
|
---
|
||||||
Ok([
|
(
|
||||||
(
|
Ok([
|
||||||
FunctionDef(FunctionDef {
|
(
|
||||||
declaration: Normal(NormalDecl {
|
FunctionDef(FunctionDef {
|
||||||
decl_spec: DeclSpec {
|
decl: Normal(NormalDecl {
|
||||||
ty: Int,
|
decl_spec: DeclSpec {
|
||||||
attrs: "(empty)",
|
ty: Int,
|
||||||
},
|
attrs: "(empty)",
|
||||||
init_declarators: [
|
},
|
||||||
(
|
init_declarators: [
|
||||||
InitDecl {
|
(
|
||||||
declarator: Declarator {
|
InitDecl {
|
||||||
decl: WithParams {
|
declarator: Declarator {
|
||||||
ident: ("uwu", 5..8),
|
decl: WithParams {
|
||||||
params: [
|
ident: ("uwu", 5..8),
|
||||||
FunctionParamDecl {
|
params: [
|
||||||
decl_spec: (
|
FunctionParamDecl {
|
||||||
DeclSpec {
|
decl_spec: (
|
||||||
ty: Long,
|
DeclSpec {
|
||||||
attrs: "(empty)",
|
ty: Long,
|
||||||
},
|
attrs: "(empty)",
|
||||||
9..13,
|
},
|
||||||
),
|
9..13,
|
||||||
declarator: (
|
),
|
||||||
Declarator {
|
declarator: (
|
||||||
decl: Ident(("owo", 14..17)),
|
Declarator {
|
||||||
pointer: false,
|
decl: Ident(("owo", 14..17)),
|
||||||
},
|
pointer: false,
|
||||||
14..17,
|
},
|
||||||
),
|
14..17,
|
||||||
},
|
),
|
||||||
FunctionParamDecl {
|
},
|
||||||
decl_spec: (
|
FunctionParamDecl {
|
||||||
DeclSpec {
|
decl_spec: (
|
||||||
ty: Int,
|
DeclSpec {
|
||||||
attrs: "(empty)",
|
ty: Int,
|
||||||
},
|
attrs: "(empty)",
|
||||||
19..22,
|
},
|
||||||
),
|
19..22,
|
||||||
declarator: (
|
),
|
||||||
Declarator {
|
declarator: (
|
||||||
decl: Ident(("qwq", 23..26)),
|
Declarator {
|
||||||
pointer: false,
|
decl: Ident(("qwq", 23..26)),
|
||||||
},
|
pointer: false,
|
||||||
23..26,
|
},
|
||||||
),
|
23..26,
|
||||||
},
|
),
|
||||||
],
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
pointer: false,
|
||||||
},
|
},
|
||||||
pointer: false,
|
init: None,
|
||||||
},
|
},
|
||||||
init: None,
|
5..8,
|
||||||
},
|
),
|
||||||
5..8,
|
],
|
||||||
),
|
}),
|
||||||
],
|
body: [],
|
||||||
}),
|
}),
|
||||||
body: [],
|
1..30,
|
||||||
}),
|
),
|
||||||
1..30,
|
]),
|
||||||
),
|
"",
|
||||||
])
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,36 @@
|
||||||
---
|
---
|
||||||
source: parser/src/parser/tests.rs
|
source: parser/src/parser/tests.rs
|
||||||
expression: parsed_pretty
|
expression: "(parsed_pretty, pretty_printed_source)"
|
||||||
---
|
---
|
||||||
Ok([
|
(
|
||||||
(
|
Ok([
|
||||||
FunctionDef(FunctionDef {
|
(
|
||||||
declaration: Normal(NormalDecl {
|
FunctionDef(FunctionDef {
|
||||||
decl_spec: DeclSpec {
|
decl: Normal(NormalDecl {
|
||||||
ty: Int,
|
decl_spec: DeclSpec {
|
||||||
attrs: "EXTERN | THREAD_LOCAL",
|
ty: Int,
|
||||||
},
|
attrs: "EXTERN | THREAD_LOCAL",
|
||||||
init_declarators: [
|
},
|
||||||
(
|
init_declarators: [
|
||||||
InitDecl {
|
(
|
||||||
declarator: Declarator {
|
InitDecl {
|
||||||
decl: WithParams {
|
declarator: Declarator {
|
||||||
ident: ("uwu", 35..38),
|
decl: WithParams {
|
||||||
params: [],
|
ident: ("uwu", 35..38),
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
pointer: false,
|
||||||
},
|
},
|
||||||
pointer: false,
|
init: None,
|
||||||
},
|
},
|
||||||
init: None,
|
35..38,
|
||||||
},
|
),
|
||||||
35..38,
|
],
|
||||||
),
|
}),
|
||||||
],
|
body: [],
|
||||||
}),
|
}),
|
||||||
body: [],
|
1..43,
|
||||||
}),
|
),
|
||||||
1..43,
|
]),
|
||||||
),
|
"",
|
||||||
])
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,36 @@
|
||||||
---
|
---
|
||||||
source: parser/src/parser/tests.rs
|
source: parser/src/parser/tests.rs
|
||||||
expression: parsed_pretty
|
expression: "(parsed_pretty, pretty_printed_source)"
|
||||||
---
|
---
|
||||||
Ok([
|
(
|
||||||
(
|
Ok([
|
||||||
FunctionDef(FunctionDef {
|
(
|
||||||
declaration: Normal(NormalDecl {
|
FunctionDef(FunctionDef {
|
||||||
decl_spec: DeclSpec {
|
decl: Normal(NormalDecl {
|
||||||
ty: Void,
|
decl_spec: DeclSpec {
|
||||||
attrs: "(empty)",
|
ty: Void,
|
||||||
},
|
attrs: "(empty)",
|
||||||
init_declarators: [
|
},
|
||||||
(
|
init_declarators: [
|
||||||
InitDecl {
|
(
|
||||||
declarator: Declarator {
|
InitDecl {
|
||||||
decl: WithParams {
|
declarator: Declarator {
|
||||||
ident: ("uwu", 6..9),
|
decl: WithParams {
|
||||||
params: [],
|
ident: ("uwu", 6..9),
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
pointer: false,
|
||||||
},
|
},
|
||||||
pointer: false,
|
init: None,
|
||||||
},
|
},
|
||||||
init: None,
|
6..9,
|
||||||
},
|
),
|
||||||
6..9,
|
],
|
||||||
),
|
}),
|
||||||
],
|
body: [],
|
||||||
}),
|
}),
|
||||||
body: [],
|
1..14,
|
||||||
}),
|
),
|
||||||
1..14,
|
]),
|
||||||
),
|
"",
|
||||||
])
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,88 +1,91 @@
|
||||||
---
|
---
|
||||||
source: parser/src/parser/tests.rs
|
source: parser/src/parser/tests.rs
|
||||||
expression: parsed_pretty
|
expression: "(parsed_pretty, pretty_printed_source)"
|
||||||
---
|
---
|
||||||
Ok([
|
(
|
||||||
(
|
Ok([
|
||||||
Decl(
|
(
|
||||||
Normal(NormalDecl {
|
Decl(
|
||||||
decl_spec: DeclSpec {
|
Normal(NormalDecl {
|
||||||
ty: Int,
|
decl_spec: DeclSpec {
|
||||||
attrs: "(empty)",
|
ty: Int,
|
||||||
},
|
attrs: "(empty)",
|
||||||
init_declarators: [
|
},
|
||||||
(
|
init_declarators: [
|
||||||
InitDecl {
|
(
|
||||||
declarator: Declarator {
|
InitDecl {
|
||||||
decl: Ident(("test", 5..9)),
|
declarator: Declarator {
|
||||||
pointer: false,
|
decl: Ident(("test", 5..9)),
|
||||||
},
|
pointer: false,
|
||||||
init: None,
|
|
||||||
},
|
|
||||||
5..9,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
1..9,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
Decl(
|
|
||||||
Normal(NormalDecl {
|
|
||||||
decl_spec: DeclSpec {
|
|
||||||
ty: Double,
|
|
||||||
attrs: "THREAD_LOCAL",
|
|
||||||
},
|
|
||||||
init_declarators: [
|
|
||||||
(
|
|
||||||
InitDecl {
|
|
||||||
declarator: Declarator {
|
|
||||||
decl: Ident(("uwu", 32..35)),
|
|
||||||
pointer: false,
|
|
||||||
},
|
|
||||||
init: None,
|
|
||||||
},
|
|
||||||
32..35,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
InitDecl {
|
|
||||||
declarator: Declarator {
|
|
||||||
decl: Ident(("owo", 37..40)),
|
|
||||||
pointer: false,
|
|
||||||
},
|
|
||||||
init: None,
|
|
||||||
},
|
|
||||||
37..40,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
11..40,
|
|
||||||
),
|
|
||||||
(
|
|
||||||
Decl(
|
|
||||||
Normal(NormalDecl {
|
|
||||||
decl_spec: DeclSpec {
|
|
||||||
ty: Int,
|
|
||||||
attrs: "(empty)",
|
|
||||||
},
|
|
||||||
init_declarators: [
|
|
||||||
(
|
|
||||||
InitDecl {
|
|
||||||
declarator: Declarator {
|
|
||||||
decl: WithParams {
|
|
||||||
ident: ("function", 68..76),
|
|
||||||
params: [],
|
|
||||||
},
|
},
|
||||||
pointer: false,
|
init: None,
|
||||||
},
|
},
|
||||||
init: None,
|
5..9,
|
||||||
},
|
),
|
||||||
68..76,
|
],
|
||||||
),
|
}),
|
||||||
],
|
),
|
||||||
}),
|
1..9,
|
||||||
),
|
),
|
||||||
64..76,
|
(
|
||||||
),
|
Decl(
|
||||||
])
|
Normal(NormalDecl {
|
||||||
|
decl_spec: DeclSpec {
|
||||||
|
ty: Double,
|
||||||
|
attrs: "THREAD_LOCAL",
|
||||||
|
},
|
||||||
|
init_declarators: [
|
||||||
|
(
|
||||||
|
InitDecl {
|
||||||
|
declarator: Declarator {
|
||||||
|
decl: Ident(("uwu", 32..35)),
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: None,
|
||||||
|
},
|
||||||
|
32..35,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
InitDecl {
|
||||||
|
declarator: Declarator {
|
||||||
|
decl: Ident(("owo", 37..40)),
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: None,
|
||||||
|
},
|
||||||
|
37..40,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
11..40,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Decl(
|
||||||
|
Normal(NormalDecl {
|
||||||
|
decl_spec: DeclSpec {
|
||||||
|
ty: Int,
|
||||||
|
attrs: "(empty)",
|
||||||
|
},
|
||||||
|
init_declarators: [
|
||||||
|
(
|
||||||
|
InitDecl {
|
||||||
|
declarator: Declarator {
|
||||||
|
decl: WithParams {
|
||||||
|
ident: ("function", 68..76),
|
||||||
|
params: [],
|
||||||
|
},
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: None,
|
||||||
|
},
|
||||||
|
68..76,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
64..76,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
"",
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,103 +1,106 @@
|
||||||
---
|
---
|
||||||
source: parser/src/parser/tests.rs
|
source: parser/src/parser/tests.rs
|
||||||
expression: parsed_pretty
|
expression: "(parsed_pretty, pretty_printed_source)"
|
||||||
---
|
---
|
||||||
Ok([
|
(
|
||||||
(
|
Ok([
|
||||||
Decl(
|
(
|
||||||
Normal(NormalDecl {
|
Decl(
|
||||||
decl_spec: DeclSpec {
|
Normal(NormalDecl {
|
||||||
ty: Int,
|
decl_spec: DeclSpec {
|
||||||
attrs: "(empty)",
|
ty: Int,
|
||||||
},
|
attrs: "(empty)",
|
||||||
init_declarators: [
|
},
|
||||||
(
|
init_declarators: [
|
||||||
InitDecl {
|
(
|
||||||
declarator: Declarator {
|
InitDecl {
|
||||||
decl: Ident(("x", 5..6)),
|
declarator: Declarator {
|
||||||
pointer: false,
|
decl: Ident(("x", 5..6)),
|
||||||
|
pointer: false,
|
||||||
|
},
|
||||||
|
init: Some((
|
||||||
|
Binary(ExprBinary {
|
||||||
|
lhs: (Atom(Int(1)), 9..10),
|
||||||
|
rhs: (Atom(Int(1)), 13..14),
|
||||||
|
op: Arith(Add),
|
||||||
|
}),
|
||||||
|
9..14,
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
init: Some((
|
5..6,
|
||||||
Binary(ExprBinary {
|
),
|
||||||
lhs: (Atom(Int(1)), 9..10),
|
],
|
||||||
rhs: (Atom(Int(1)), 13..14),
|
}),
|
||||||
op: Add,
|
),
|
||||||
}),
|
1..6,
|
||||||
9..14,
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
5..6,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
1..6,
|
(
|
||||||
),
|
Decl(
|
||||||
(
|
Normal(NormalDecl {
|
||||||
Decl(
|
decl_spec: DeclSpec {
|
||||||
Normal(NormalDecl {
|
ty: Int,
|
||||||
decl_spec: DeclSpec {
|
attrs: "(empty)",
|
||||||
ty: Int,
|
},
|
||||||
attrs: "(empty)",
|
init_declarators: [
|
||||||
},
|
(
|
||||||
init_declarators: [
|
InitDecl {
|
||||||
(
|
declarator: Declarator {
|
||||||
InitDecl {
|
decl: Ident(("y", 21..22)),
|
||||||
declarator: Declarator {
|
pointer: false,
|
||||||
decl: Ident(("y", 21..22)),
|
},
|
||||||
pointer: false,
|
init: Some((
|
||||||
|
Binary(ExprBinary {
|
||||||
|
lhs: (Atom(Int(1)), 26..27),
|
||||||
|
rhs: (
|
||||||
|
Binary(ExprBinary {
|
||||||
|
lhs: (Atom(Int(2)), 31..32),
|
||||||
|
rhs: (Atom(Int(3)), 35..36),
|
||||||
|
op: Arith(Sub),
|
||||||
|
}),
|
||||||
|
31..36,
|
||||||
|
),
|
||||||
|
op: Arith(Add),
|
||||||
|
}),
|
||||||
|
26..36,
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
init: Some((
|
21..22,
|
||||||
Binary(ExprBinary {
|
),
|
||||||
lhs: (Atom(Int(1)), 26..27),
|
],
|
||||||
rhs: (
|
}),
|
||||||
Binary(ExprBinary {
|
),
|
||||||
lhs: (Atom(Int(2)), 31..32),
|
17..22,
|
||||||
rhs: (Atom(Int(3)), 35..36),
|
|
||||||
op: Sub,
|
|
||||||
}),
|
|
||||||
31..36,
|
|
||||||
),
|
|
||||||
op: Add,
|
|
||||||
}),
|
|
||||||
26..36,
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
21..22,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
17..22,
|
(
|
||||||
),
|
Decl(
|
||||||
(
|
Normal(NormalDecl {
|
||||||
Decl(
|
decl_spec: DeclSpec {
|
||||||
Normal(NormalDecl {
|
ty: Int,
|
||||||
decl_spec: DeclSpec {
|
attrs: "(empty)",
|
||||||
ty: Int,
|
},
|
||||||
attrs: "(empty)",
|
init_declarators: [
|
||||||
},
|
(
|
||||||
init_declarators: [
|
InitDecl {
|
||||||
(
|
declarator: Declarator {
|
||||||
InitDecl {
|
decl: Ident(("z", 45..46)),
|
||||||
declarator: Declarator {
|
pointer: false,
|
||||||
decl: Ident(("z", 45..46)),
|
},
|
||||||
pointer: false,
|
init: Some((
|
||||||
|
Binary(ExprBinary {
|
||||||
|
lhs: (Atom(Ident("array")), 50..55),
|
||||||
|
rhs: (Atom(Int(9)), 56..57),
|
||||||
|
op: Index,
|
||||||
|
}),
|
||||||
|
50..58,
|
||||||
|
)),
|
||||||
},
|
},
|
||||||
init: Some((
|
45..46,
|
||||||
Binary(ExprBinary {
|
),
|
||||||
lhs: (Atom(Ident("array")), 50..55),
|
],
|
||||||
rhs: (Atom(Int(9)), 56..57),
|
}),
|
||||||
op: Index,
|
),
|
||||||
}),
|
41..46,
|
||||||
50..58,
|
|
||||||
)),
|
|
||||||
},
|
|
||||||
45..46,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
41..46,
|
]),
|
||||||
),
|
"",
|
||||||
])
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
use std::fmt::Debug;
|
|
||||||
|
|
||||||
use super::Tok;
|
use super::Tok;
|
||||||
use crate::Span;
|
use crate::{ast::ExternalDecl, parser::ParserError, Span, Spanned};
|
||||||
|
|
||||||
fn lex_and_pre(src: &str) -> impl Iterator<Item = (Tok<'_>, Span)> + '_ {
|
fn lex_and_pre(src: &str) -> impl Iterator<Item = (Tok<'_>, Span)> + '_ {
|
||||||
let pre_tokens = crate::pre::preprocess_tokens(src);
|
let pre_tokens = crate::pre::preprocess_tokens(src);
|
||||||
crate::token::pre_tokens_to_tokens(pre_tokens)
|
crate::token::pre_tokens_to_tokens(pre_tokens)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn the_current_root_parse_thing<'src>(src: impl Iterator<Item = (Tok<'src>, Span)>) -> impl Debug {
|
fn pretty_print(ast: &Result<Vec<Spanned<ExternalDecl>>, ParserError>) -> String {
|
||||||
super::parse_declarations(src)
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
String::from_utf8_lossy(&vec).into_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! parse_test {
|
macro_rules! parse_test {
|
||||||
|
|
@ -17,8 +17,9 @@ macro_rules! parse_test {
|
||||||
let lexer = lex_and_pre($src);
|
let lexer = lex_and_pre($src);
|
||||||
let parsed = super::parse_declarations(lexer);
|
let parsed = super::parse_declarations(lexer);
|
||||||
let parsed_pretty = dbg_pls::pretty(&parsed);
|
let parsed_pretty = dbg_pls::pretty(&parsed);
|
||||||
|
let pretty_printed_source = pretty_print(&parsed);
|
||||||
|
|
||||||
insta::assert_debug_snapshot!(parsed_pretty);
|
insta::assert_debug_snapshot!((parsed_pretty, pretty_printed_source));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
286
parser/src/pretty.rs
Normal file
286
parser/src/pretty.rs
Normal file
|
|
@ -0,0 +1,286 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
type Result = std::io::Result<()>;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
ast::{
|
||||||
|
ArithOpKind, Atom, BinaryOp, ComparisonKind, Decl, DeclAttr, DeclSpec, Declarator,
|
||||||
|
DirectDeclarator, Expr, ExprBinary, ExprUnary, ExternalDecl, FunctionDef,
|
||||||
|
FunctionParamDecl, InitDecl, NormalDecl, TypeSpecifier, UnaryOp,
|
||||||
|
},
|
||||||
|
Spanned,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct PrettyPrinter<W> {
|
||||||
|
indent: usize,
|
||||||
|
output: W,
|
||||||
|
force_parens: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const INDENT: &str = " ";
|
||||||
|
|
||||||
|
impl<W: Write> PrettyPrinter<W> {
|
||||||
|
pub fn new(output: W, force_parens: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
indent: 0,
|
||||||
|
output,
|
||||||
|
force_parens,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string(&mut self, str: &str) -> Result {
|
||||||
|
write!(self.output, "{}", str)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_indent(&mut self) -> Result {
|
||||||
|
self.string(&INDENT.repeat(self.indent))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn linebreak(&mut self) -> Result {
|
||||||
|
self.string("\n")?;
|
||||||
|
self.print_indent()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn indent(&mut self) {
|
||||||
|
self.indent += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dedent(&mut self) {
|
||||||
|
self.indent -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn translation_unit(&mut self, unit: &[Spanned<ExternalDecl>]) -> Result {
|
||||||
|
for decl in unit {
|
||||||
|
self.external_decl(&decl.0)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn external_decl(&mut self, decl: &ExternalDecl) -> Result {
|
||||||
|
match decl {
|
||||||
|
ExternalDecl::FunctionDef(def) => self.function_def(def),
|
||||||
|
ExternalDecl::Decl(decl) => self.decl(decl),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_def(&mut self, def: &FunctionDef) -> Result {
|
||||||
|
self.decl(&def.decl)?;
|
||||||
|
self.string(" {")?;
|
||||||
|
self.indent();
|
||||||
|
self.linebreak()?;
|
||||||
|
// TODO: body
|
||||||
|
self.dedent();
|
||||||
|
self.linebreak()?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decl(&mut self, decl: &Decl) -> Result {
|
||||||
|
match decl {
|
||||||
|
Decl::StaticAssert => todo!(),
|
||||||
|
Decl::Normal(normal_decl) => self.normal_decl(normal_decl),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normal_decl(&mut self, decl: &NormalDecl) -> Result {
|
||||||
|
self.decl_spec(&decl.decl_spec)?;
|
||||||
|
self.string(" ")?;
|
||||||
|
let mut first = true;
|
||||||
|
for declarator in &decl.init_declarators {
|
||||||
|
if !first {
|
||||||
|
self.string(", ")?;
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
self.init_declarator(&declarator.0)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decl_spec(&mut self, decl_spec: &DeclSpec) -> Result {
|
||||||
|
self.type_specifier(&decl_spec.ty)?;
|
||||||
|
self.string(" ")?;
|
||||||
|
self.decl_attr(&decl_spec.attrs)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_declarator(&mut self, init_declarator: &InitDecl) -> Result {
|
||||||
|
self.declarator(&init_declarator.declarator)?;
|
||||||
|
if let Some(init) = &init_declarator.init {
|
||||||
|
self.string(" = ")?;
|
||||||
|
self.expr(&init.0)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_specifier(&mut self, spec: &TypeSpecifier) -> Result {
|
||||||
|
self.string(match spec {
|
||||||
|
TypeSpecifier::Void => "void",
|
||||||
|
TypeSpecifier::Char => "char",
|
||||||
|
TypeSpecifier::Short => "short",
|
||||||
|
TypeSpecifier::Int => "int",
|
||||||
|
TypeSpecifier::Long => "long",
|
||||||
|
TypeSpecifier::Float => "float",
|
||||||
|
TypeSpecifier::Double => "double",
|
||||||
|
TypeSpecifier::Signed => "signed",
|
||||||
|
TypeSpecifier::Unsigned => "unsigned",
|
||||||
|
TypeSpecifier::Bool => "_Bool",
|
||||||
|
TypeSpecifier::Complex => "_Complex",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn decl_attr(&mut self, attr: &DeclAttr) -> Result {
|
||||||
|
let mut attrs = Vec::new();
|
||||||
|
if attr.contains(DeclAttr::EXTERN) {
|
||||||
|
attrs.push("extern");
|
||||||
|
}
|
||||||
|
if attr.contains(DeclAttr::STATIC) {
|
||||||
|
attrs.push("static");
|
||||||
|
}
|
||||||
|
if attr.contains(DeclAttr::THREAD_LOCAL) {
|
||||||
|
attrs.push("_Thread_local");
|
||||||
|
}
|
||||||
|
self.string(&attrs.join(" "))?;
|
||||||
|
self.string(" ")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declarator(&mut self, declarator: &Declarator) -> Result {
|
||||||
|
if declarator.pointer {
|
||||||
|
self.string("*")?;
|
||||||
|
}
|
||||||
|
self.direct_declarator(&declarator.decl)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn direct_declarator(&mut self, declarator: &DirectDeclarator) -> Result {
|
||||||
|
match declarator {
|
||||||
|
DirectDeclarator::Ident(ident) => self.string(&ident.0),
|
||||||
|
DirectDeclarator::WithParams { ident, params } => {
|
||||||
|
self.string(&ident.0)?;
|
||||||
|
self.string("(")?;
|
||||||
|
self.function_param_decls(params)?;
|
||||||
|
self.string(")")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_param_decls(&mut self, decls: &[FunctionParamDecl]) -> Result {
|
||||||
|
let mut first = true;
|
||||||
|
for decl in decls {
|
||||||
|
if !first {
|
||||||
|
self.string(", ")?;
|
||||||
|
}
|
||||||
|
first = false;
|
||||||
|
self.decl_spec(&decl.decl_spec.0)?;
|
||||||
|
self.declarator(&decl.declarator.0)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn expr(&mut self, expr: &Expr) -> Result {
|
||||||
|
match expr {
|
||||||
|
Expr::Atom(atom) => match atom {
|
||||||
|
Atom::Ident(ident) => self.string(ident),
|
||||||
|
Atom::Int(int) => write!(self.output, "{}", int),
|
||||||
|
Atom::Float(float) => write!(self.output, "{}", float),
|
||||||
|
Atom::String(string) => {
|
||||||
|
self.string("\"")?;
|
||||||
|
// bare attempt at escpaing
|
||||||
|
self.string(&string.replace('\"', "\\\""))?;
|
||||||
|
self.string("\"")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Atom::Char(char) => {
|
||||||
|
self.string("'")?;
|
||||||
|
let ascii = *char as char;
|
||||||
|
write!(self.output, "{}", ascii)?;
|
||||||
|
self.string("'")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Expr::Unary(unary) => self.unary(unary),
|
||||||
|
Expr::Binary(ExprBinary {
|
||||||
|
op: BinaryOp::Index,
|
||||||
|
lhs,
|
||||||
|
rhs,
|
||||||
|
}) => {
|
||||||
|
self.expr(&lhs.as_ref().0)?;
|
||||||
|
self.string("[")?;
|
||||||
|
self.expr(&rhs.as_ref().0)?;
|
||||||
|
self.string("]")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Expr::Binary(binary) => self.binary(binary),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unary(&mut self, unary: &ExprUnary) -> Result {
|
||||||
|
self.string(match unary.op {
|
||||||
|
UnaryOp::AddrOf => "&",
|
||||||
|
UnaryOp::Deref => "*",
|
||||||
|
UnaryOp::Plus => "+",
|
||||||
|
UnaryOp::Minus => "-",
|
||||||
|
UnaryOp::Tilde => "~",
|
||||||
|
UnaryOp::Bang => "!",
|
||||||
|
})?;
|
||||||
|
if self.force_parens {
|
||||||
|
self.string("(")?;
|
||||||
|
}
|
||||||
|
self.expr(&unary.rhs.as_ref().0)?;
|
||||||
|
if self.force_parens {
|
||||||
|
self.string(")")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn binary(&mut self, binary: &ExprBinary) -> Result {
|
||||||
|
if self.force_parens {
|
||||||
|
self.string("(")?;
|
||||||
|
}
|
||||||
|
self.expr(&binary.lhs.as_ref().0)?;
|
||||||
|
self.string(" ")?;
|
||||||
|
self.string(match binary.op {
|
||||||
|
BinaryOp::Arith(ArithOpKind::Mul) => "*",
|
||||||
|
BinaryOp::Arith(ArithOpKind::Div) => "/",
|
||||||
|
BinaryOp::Arith(ArithOpKind::Mod) => "%",
|
||||||
|
BinaryOp::Arith(ArithOpKind::Add) => "+",
|
||||||
|
BinaryOp::Arith(ArithOpKind::Sub) => "-",
|
||||||
|
BinaryOp::Arith(ArithOpKind::Shl) => "<<",
|
||||||
|
BinaryOp::Arith(ArithOpKind::Shr) => ">>",
|
||||||
|
BinaryOp::Arith(ArithOpKind::BitAnd) => "&",
|
||||||
|
BinaryOp::Arith(ArithOpKind::BitXor) => "^",
|
||||||
|
BinaryOp::Arith(ArithOpKind::BitOr) => "|",
|
||||||
|
BinaryOp::LogicalAnd => "&&",
|
||||||
|
BinaryOp::LogicalOr => "||",
|
||||||
|
BinaryOp::Comparison(ComparisonKind::Lt) => "<",
|
||||||
|
BinaryOp::Comparison(ComparisonKind::Gt) => ">",
|
||||||
|
BinaryOp::Comparison(ComparisonKind::LtEq) => "<=",
|
||||||
|
BinaryOp::Comparison(ComparisonKind::GtEq) => ">=",
|
||||||
|
BinaryOp::Comparison(ComparisonKind::Eq) => "==",
|
||||||
|
BinaryOp::Comparison(ComparisonKind::Neq) => "!=",
|
||||||
|
BinaryOp::Comma => ",",
|
||||||
|
BinaryOp::Index => unreachable!("special case outside"),
|
||||||
|
BinaryOp::Assign(None) => "=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Mul)) => "*=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Div)) => "/=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Mod)) => "%=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Add)) => "+=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Sub)) => "-=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Shl)) => "<<=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::Shr)) => ">>=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::BitAnd)) => "&=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::BitXor)) => "^=",
|
||||||
|
BinaryOp::Assign(Some(ArithOpKind::BitOr)) => "|=",
|
||||||
|
})?;
|
||||||
|
self.string(" ")?;
|
||||||
|
self.expr(&binary.rhs.as_ref().0)?;
|
||||||
|
if self.force_parens {
|
||||||
|
self.string(")")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue