2020-10-07 14:12:19 +03:00
|
|
|
#define _POSIX_C_SOURCE 200809L
|
2020-10-07 14:11:16 +03:00
|
|
|
#include <assert.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2020-10-07 14:12:19 +03:00
|
|
|
typedef struct Node Node;
|
|
|
|
|
2020-10-07 14:11:16 +03:00
|
|
|
//
|
|
|
|
// tokenize.c
|
|
|
|
//
|
|
|
|
|
2020-10-07 14:12:19 +03:00
|
|
|
// Token
|
2020-10-07 14:11:16 +03:00
|
|
|
typedef enum {
|
2020-10-07 14:12:57 +03:00
|
|
|
TK_IDENT, // Identifiers
|
|
|
|
TK_PUNCT, // Punctuators
|
|
|
|
TK_KEYWORD, // Keywords
|
|
|
|
TK_NUM, // Numeric literals
|
|
|
|
TK_EOF, // End-of-file markers
|
2020-10-07 14:11:16 +03:00
|
|
|
} TokenKind;
|
|
|
|
|
|
|
|
// Token type
|
|
|
|
typedef struct Token Token;
|
|
|
|
struct Token {
|
|
|
|
TokenKind kind; // Token kind
|
|
|
|
Token *next; // Next token
|
|
|
|
int val; // If kind is TK_NUM, its value
|
|
|
|
char *loc; // Token location
|
|
|
|
int len; // Token length
|
|
|
|
};
|
|
|
|
|
|
|
|
void error(char *fmt, ...);
|
|
|
|
void error_at(char *loc, char *fmt, ...);
|
|
|
|
void error_tok(Token *tok, char *fmt, ...);
|
|
|
|
bool equal(Token *tok, char *op);
|
|
|
|
Token *skip(Token *tok, char *op);
|
|
|
|
Token *tokenize(char *input);
|
|
|
|
|
|
|
|
//
|
|
|
|
// parse.c
|
|
|
|
//
|
|
|
|
|
2020-10-07 14:12:19 +03:00
|
|
|
// Local variable
|
|
|
|
typedef struct Obj Obj;
|
|
|
|
struct Obj {
|
|
|
|
Obj *next;
|
|
|
|
char *name; // Variable name
|
|
|
|
int offset; // Offset from RBP
|
|
|
|
};
|
|
|
|
|
|
|
|
// Function
|
|
|
|
typedef struct Function Function;
|
|
|
|
struct Function {
|
|
|
|
Node *body;
|
|
|
|
Obj *locals;
|
|
|
|
int stack_size;
|
|
|
|
};
|
|
|
|
|
|
|
|
// AST node
|
2020-10-07 14:11:16 +03:00
|
|
|
typedef enum {
|
2020-09-26 02:50:44 +03:00
|
|
|
ND_ADD, // +
|
|
|
|
ND_SUB, // -
|
|
|
|
ND_MUL, // *
|
|
|
|
ND_DIV, // /
|
|
|
|
ND_NEG, // unary -
|
|
|
|
ND_EQ, // ==
|
|
|
|
ND_NE, // !=
|
|
|
|
ND_LT, // <
|
|
|
|
ND_LE, // <=
|
2020-09-26 02:59:56 +03:00
|
|
|
ND_ASSIGN, // =
|
2019-08-05 15:12:44 +03:00
|
|
|
ND_ADDR, // unary &
|
|
|
|
ND_DEREF, // unary *
|
2020-10-07 14:12:57 +03:00
|
|
|
ND_RETURN, // "return"
|
2020-10-07 06:47:09 +03:00
|
|
|
ND_IF, // "if"
|
2019-08-04 11:24:03 +03:00
|
|
|
ND_FOR, // "for" or "while"
|
2020-09-04 07:38:41 +03:00
|
|
|
ND_BLOCK, // { ... }
|
2020-09-26 02:50:44 +03:00
|
|
|
ND_EXPR_STMT, // Expression statement
|
2020-09-26 02:59:56 +03:00
|
|
|
ND_VAR, // Variable
|
2020-09-26 02:50:44 +03:00
|
|
|
ND_NUM, // Integer
|
2020-10-07 14:11:16 +03:00
|
|
|
} NodeKind;
|
|
|
|
|
|
|
|
// AST node type
|
|
|
|
struct Node {
|
|
|
|
NodeKind kind; // Node kind
|
2020-09-26 02:50:44 +03:00
|
|
|
Node *next; // Next node
|
2020-09-26 05:23:04 +03:00
|
|
|
Token *tok; // Representative token
|
2020-10-07 06:47:09 +03:00
|
|
|
|
2020-10-07 14:11:16 +03:00
|
|
|
Node *lhs; // Left-hand side
|
|
|
|
Node *rhs; // Right-hand side
|
2020-09-04 07:38:41 +03:00
|
|
|
|
2019-08-04 11:35:53 +03:00
|
|
|
// "if" or "for" statement
|
2020-10-07 06:47:09 +03:00
|
|
|
Node *cond;
|
|
|
|
Node *then;
|
|
|
|
Node *els;
|
2019-08-04 11:35:53 +03:00
|
|
|
Node *init;
|
|
|
|
Node *inc;
|
2020-10-07 06:47:09 +03:00
|
|
|
|
2020-09-04 07:38:41 +03:00
|
|
|
// Block
|
|
|
|
Node *body;
|
|
|
|
|
2020-10-07 14:12:19 +03:00
|
|
|
Obj *var; // Used if kind == ND_VAR
|
2020-10-07 14:11:16 +03:00
|
|
|
int val; // Used if kind == ND_NUM
|
|
|
|
};
|
|
|
|
|
2020-10-07 14:12:19 +03:00
|
|
|
Function *parse(Token *tok);
|
2020-10-07 14:11:16 +03:00
|
|
|
|
|
|
|
//
|
|
|
|
// codegen.c
|
|
|
|
//
|
|
|
|
|
2020-10-07 14:12:19 +03:00
|
|
|
void codegen(Function *prog);
|