recc/parse/
tree.rs

1use std::fmt::Display;
2
3use crate::semantic_analysis::{identifier_resolution::UniqId, label::TempLabel, type_check::slice_to_string};
4
5// <program> ::= { <function-declaration> }
6#[derive(Debug, Clone)]
7pub struct AProgram {
8        pub declarations: Vec<Declaration>,
9}
10
11// specifier ::= "int" | "static" | "extern"
12
13// <function-declaration> ::= { <specifier> }+ "int" <identifier> "(" "void" ")" ( <block> | ; )
14#[derive(Debug, Clone)]
15pub struct AFunctionDeclaration {
16        pub id: AId,
17        pub param_list: Params,
18        pub body: Option<Block>,
19        pub class: Option<StorageClass>,
20        // will be added in semantic analysis stage
21        pub global: Option<bool>,
22}
23
24// <param-list> ::= "void" | "int" <identifier> { "," "int" <identifier> }
25#[derive(Debug, Clone)]
26pub enum Params {
27        Void,
28        V(Vec<AId>),
29}
30
31#[derive(Debug, Clone)]
32pub enum Declaration {
33        V(AVariableDeclaration),
34        F(AFunctionDeclaration),
35}
36
37// <variable-declaration> ::= { <specifier> }+ "int" <identifier> [ "=" <exp> ] ";"
38#[derive(Debug, Clone)]
39pub struct AVariableDeclaration {
40        pub name: AId,
41        pub init: Option<AExpr>,
42        pub class: Option<StorageClass>,
43}
44
45#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub enum StorageClass {
47        Static,
48        Extern,
49}
50
51// <block-item> ::= <statement> | <declaration>
52#[derive(Debug, Clone)]
53pub enum ABlockItem {
54        D(Declaration),
55        S(AStatement),
56}
57
58// <statement> ::= "return" <exp> ";"
59//                 | <exp> ";"
60//                 | if "(" <exp> ")" <statement> [ "else" <statement> ]
61//                 | <block>
62//                 | break ";"
63//                 | continue ";"
64//                 | "while" "(" <exp> ")" <statement>
65//                 | "do" <statement> "while" "(" <exp> ")" ";"
66//                 | "for" "(" <for-init> [ <exp> ] ";" [ <exp> ] ")" <statement>
67//                 | ";"
68#[derive(Debug, Clone)]
69pub enum AStatement {
70        Ret(AExpr),
71        E(AExpr),
72        // if cond, then statement [ else statement ]
73        If(AExpr, Box<AStatement>, Option<Box<AStatement>>),
74        B(Block),
75        Break(Option<TempLabel>),
76        Continue(Option<TempLabel>),
77        While(AExpr, Box<AStatement>, Option<TempLabel>),
78        DoWhile(AExpr, Box<AStatement>, Option<TempLabel>),
79        // init, condition, post, body
80        For(
81                AForInit,
82                Option<AExpr>,
83                Option<AExpr>,
84                Box<AStatement>,
85                Option<TempLabel>,
86        ),
87        Nul,
88}
89
90// <for-init> ::= <variable-declaration> | [ <exp> ] ";"
91#[derive(Debug, Clone)]
92pub enum AForInit {
93        D(AVariableDeclaration),
94        E(AExpr),
95        Nul,
96}
97
98// <block> ::= "{" { <block-item> } "}"
99#[derive(Debug, Clone)]
100pub struct Block(pub Vec<ABlockItem>);
101
102// <exp> ::= <factor>
103//           | <exp> <binop> <exp>
104//           | <exp> "=" <exp>
105//           | <exp> "?" <exp> ":" <exp>
106#[derive(Debug, Clone)]
107pub enum AExpr {
108        F(Box<AFactor>),
109        B(Binop, Box<AExpr>, Box<AExpr>),
110        A(Box<AExpr>, Box<AExpr>),
111        C(Box<AExpr>, Box<AExpr>, Box<AExpr>),
112}
113
114// <factor> ::= <int> | <unop> <factor> | "(" <exp> ")" | <identifier>
115//              | <identifier> "(" [ <argument-list> ] ")"
116#[derive(Debug, Clone)]
117pub enum AFactor {
118        Int(AConstant),
119        U(Unop, Box<AFactor>),
120        E(AExpr),
121        I(AId),
122        FunctionCall(AId, Option<Vec<AExpr>>),
123}
124
125// <unop> ::= "-" | "~" | "!" | Pre AND Post ++, --
126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
127pub enum Unop {
128        Neg,
129        Complement,
130        Not,
131        PreIncr,
132        PostIncr,
133        PreDecr,
134        PostDecr,
135}
136impl Display for Unop {
137        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138                let look = self.what_does_it_look_like();
139                write!(f, "{look}")
140        }
141}
142impl Unop {
143        fn what_does_it_look_like(&self) -> &str {
144                match self {
145                        Unop::Neg => "-",
146                        Unop::Complement => "~",
147                        Unop::Not => "!",
148                        Unop::PreIncr => "++ (Pre)",
149                        Unop::PostIncr => "++ (Post)",
150                        Unop::PreDecr => "-- (Pre)",
151                        Unop::PostDecr => "-- (Post)",
152                }
153        }
154}
155
156// <binop> ::= "-" | "+" | "*" | "/" | "%" | "&&" | "||"
157// | "==" | "!=" | "<" | "<=" | ">" | ">=" | "="
158#[derive(Debug, Clone, Copy, PartialEq, Eq)]
159pub enum Binop {
160        Subtract,
161        Add,
162        Multiply,
163        Divide,
164        Modulo,
165        And,
166        Or,
167        EqualTo,
168        NotEqualTo,
169        LessThan,
170        LessThanOrEqual,
171        MoreThan,
172        MoreThanOrEqual,
173        Equal,
174        //ONLY FOR PARSING. DO NOT USE ANYWHERE ELSE. THIS IS SO THAT ITS PRECEDENCE CAN BE DEFINED, NOT BECAUSE IT MEANS SOMETHING
175        Ternary,
176}
177impl Display for Binop {
178        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179                write!(f, "{}", self.what_does_it_look_like())
180        }
181}
182
183impl Binop {
184        fn what_does_it_look_like(&self) -> &str {
185                match self {
186                        Binop::Subtract => "-",
187                        Binop::Add => "+",
188                        Binop::Multiply => "*",
189                        Binop::Divide => "/",
190                        Binop::Modulo => "%",
191                        Binop::And => "&",
192                        Binop::Or => "^",
193                        Binop::EqualTo => "==",
194                        Binop::NotEqualTo => "!=",
195                        Binop::LessThan => "<",
196                        Binop::LessThanOrEqual => "<=",
197                        Binop::MoreThan => ">",
198                        Binop::MoreThanOrEqual => ">=",
199                        Binop::Equal => "=",
200                        // shouldn't be happening because it should be in a conditional expression etc etc
201                        Binop::Ternary => panic!(),
202                }
203        }
204}
205
206// <int> ::= ? A constant token ?
207#[derive(Debug, Clone, Copy, PartialEq, Eq)]
208pub enum AConstant {
209        A(S),
210        C(i64),
211}
212impl AConstant {
213        #[must_use]
214        pub fn to_string(&self, code: &[u8]) -> String {
215                match self {
216                        AConstant::A(s) => slice_to_string(code, *s),
217                        AConstant::C(num) => num.to_string(),
218                }
219        }
220}
221
222// <identifier> ::= ? An identifier token ?
223#[derive(Debug, Clone, Copy)]
224pub struct AId(pub S, pub Option<UniqId>);
225
226// start, len of in code
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
228pub struct S(pub usize, pub usize);