colored demo
This commit is contained in:
parent
1bcff515b7
commit
e425464aab
5 changed files with 183 additions and 35 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ cov
|
|||
*.s
|
||||
*.ans
|
||||
*.elf
|
||||
*.html
|
88
boot.c
88
boot.c
|
@ -20,13 +20,10 @@ void exit(int status);
|
|||
int fprintf(void* file, char* format, ...);
|
||||
int ungetc(int ch, void* file);
|
||||
|
||||
void ungetchar(int ch) {
|
||||
ungetc(ch, stdin);
|
||||
}
|
||||
|
||||
// limitations
|
||||
|
||||
enum {
|
||||
ECHO_BUFFER_SIZE = 65536,
|
||||
STRING_TABLE_SIZE = 65536,
|
||||
STRING_LUT_SIZE = 4096,
|
||||
ID_TABLE_SIZE = 65536,
|
||||
|
@ -35,6 +32,28 @@ enum {
|
|||
REG_SIZE = 4096,
|
||||
};
|
||||
|
||||
// hooks
|
||||
|
||||
char echo_buffer[ECHO_BUFFER_SIZE];
|
||||
int echo_size;
|
||||
|
||||
int readchar() {
|
||||
int ch = getchar();
|
||||
if (ch != '\n') {
|
||||
echo_buffer[echo_size++] = ch;
|
||||
} else {
|
||||
echo_buffer[echo_size++] = 0;
|
||||
printf("#@%s\n", echo_buffer);
|
||||
echo_size = 0;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
void ungetchar(int ch) {
|
||||
--echo_size;
|
||||
ungetc(ch, stdin);
|
||||
}
|
||||
|
||||
// constants
|
||||
|
||||
enum {
|
||||
|
@ -220,7 +239,7 @@ int is_id_cont(int ch) {
|
|||
|
||||
int parse_int(int ch) {
|
||||
int num = ch - '0';
|
||||
while (is_digit(ch = getchar())) {
|
||||
while (is_digit(ch = readchar())) {
|
||||
num *= 10;
|
||||
num += ch - '0';
|
||||
}
|
||||
|
@ -229,7 +248,7 @@ int parse_int(int ch) {
|
|||
}
|
||||
|
||||
int get_escaped_char() {
|
||||
int ch = getchar();
|
||||
int ch = readchar();
|
||||
if (ch == 'n') return '\n';
|
||||
if (ch == 't') return '\t';
|
||||
if (ch == 'r') return '\r';
|
||||
|
@ -252,7 +271,7 @@ int string_lut_size;
|
|||
int parse_string() {
|
||||
int offset = string_offset;
|
||||
int ch;
|
||||
while ((ch = getchar()) != '"') {
|
||||
while ((ch = readchar()) != '"') {
|
||||
if (ch == -1 || ch == '\n') {
|
||||
fprintf(stderr, "expecting '\"'\n");
|
||||
exit(1);
|
||||
|
@ -292,7 +311,7 @@ int id_lut_size;
|
|||
int parse_id(int ch) {
|
||||
int offset = id_offset;
|
||||
id_table[id_offset++] = ch;
|
||||
while (is_id_cont(ch = getchar())) {
|
||||
while (is_id_cont(ch = readchar())) {
|
||||
id_table[id_offset++] = ch;
|
||||
}
|
||||
ungetchar(ch);
|
||||
|
@ -366,9 +385,9 @@ void next_token() {
|
|||
token_state = 0;
|
||||
return;
|
||||
}
|
||||
int ch = getchar();
|
||||
int ch = readchar();
|
||||
while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
|
||||
ch = getchar();
|
||||
ch = readchar();
|
||||
}
|
||||
if (ch == -1) {
|
||||
token_type = TOKEN_EOF;
|
||||
|
@ -385,7 +404,7 @@ void next_token() {
|
|||
} else if (ch == '}') {
|
||||
token_type = TOKEN_BRACE_RIGHT;
|
||||
} else if (ch == '+') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '+') {
|
||||
token_type = TOKEN_INC;
|
||||
} else if (ch2 == '=') {
|
||||
|
@ -395,7 +414,7 @@ void next_token() {
|
|||
token_type = TOKEN_ADD;
|
||||
}
|
||||
} else if (ch == '-') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '-') {
|
||||
token_type = TOKEN_DEC;
|
||||
} else if (ch2 == '=') {
|
||||
|
@ -405,7 +424,7 @@ void next_token() {
|
|||
token_type = TOKEN_SUB;
|
||||
}
|
||||
} else if (ch == '*') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_MUL_ASSIGN;
|
||||
} else {
|
||||
|
@ -413,22 +432,22 @@ void next_token() {
|
|||
token_type = TOKEN_MUL;
|
||||
}
|
||||
} else if (ch == '/') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_DIV_ASSIGN;
|
||||
} else if (ch2 == '/') {
|
||||
do ch = getchar(); while (ch != -1 && ch != '\n');
|
||||
do ch = readchar(); while (ch != -1 && ch != '\n');
|
||||
next_token();
|
||||
return;
|
||||
} else if (ch2 == '*') {
|
||||
while (1) {
|
||||
ch = getchar();
|
||||
ch = readchar();
|
||||
if (ch == -1) {
|
||||
fprintf(stderr, "expecting '*/'\n");
|
||||
exit(1);
|
||||
}
|
||||
if (ch == '*') {
|
||||
ch = getchar();
|
||||
ch = readchar();
|
||||
if (ch == '/') {
|
||||
break;
|
||||
}
|
||||
|
@ -441,7 +460,7 @@ void next_token() {
|
|||
token_type = TOKEN_DIV;
|
||||
}
|
||||
} else if (ch == '%') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_REM_ASSIGN;
|
||||
} else {
|
||||
|
@ -457,11 +476,11 @@ void next_token() {
|
|||
} else if (ch == ',') {
|
||||
token_type = TOKEN_COMMA;
|
||||
} else if (ch == '<') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_LE;
|
||||
} else if (ch2 == '<') {
|
||||
int ch3 = getchar();
|
||||
int ch3 = readchar();
|
||||
if (ch3 == '=') {
|
||||
token_type = TOKEN_LSHIFT_ASSIGN;
|
||||
} else {
|
||||
|
@ -473,11 +492,11 @@ void next_token() {
|
|||
token_type = TOKEN_LT;
|
||||
}
|
||||
} else if (ch == '>') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_GE;
|
||||
} else if (ch2 == '>') {
|
||||
int ch3 = getchar();
|
||||
int ch3 = readchar();
|
||||
if (ch3 == '=') {
|
||||
token_type = TOKEN_RSHIFT_ASSIGN;
|
||||
} else {
|
||||
|
@ -489,7 +508,7 @@ void next_token() {
|
|||
token_type = TOKEN_GT;
|
||||
}
|
||||
} else if (ch == '=') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_EQ;
|
||||
} else {
|
||||
|
@ -497,7 +516,7 @@ void next_token() {
|
|||
token_type = TOKEN_ASSIGN;
|
||||
}
|
||||
} else if (ch == '!') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_NE;
|
||||
} else {
|
||||
|
@ -505,7 +524,7 @@ void next_token() {
|
|||
token_type = TOKEN_NOT;
|
||||
}
|
||||
} else if (ch == '&') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_AND_ASSIGN;
|
||||
} else if (ch2 == '&') {
|
||||
|
@ -515,7 +534,7 @@ void next_token() {
|
|||
token_type = TOKEN_AND;
|
||||
}
|
||||
} else if (ch == '|') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_OR_ASSIGN;
|
||||
} else if (ch2 == '|') {
|
||||
|
@ -525,7 +544,7 @@ void next_token() {
|
|||
token_type = TOKEN_OR;
|
||||
}
|
||||
} else if (ch == '^') {
|
||||
int ch2 = getchar();
|
||||
int ch2 = readchar();
|
||||
if (ch2 == '=') {
|
||||
token_type = TOKEN_XOR_ASSIGN;
|
||||
} else {
|
||||
|
@ -536,11 +555,11 @@ void next_token() {
|
|||
token_type = TOKEN_INV;
|
||||
} else if (ch == '\'') {
|
||||
token_type = TOKEN_NUMBER;
|
||||
token_data = getchar();
|
||||
token_data = readchar();
|
||||
if (token_data == '\\') {
|
||||
token_data = get_escaped_char();
|
||||
}
|
||||
if (getchar() != '\'') {
|
||||
if (readchar() != '\'') {
|
||||
fprintf(stderr, "expecting '\n");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -550,8 +569,8 @@ void next_token() {
|
|||
dedup_string();
|
||||
} else if (ch == '.') {
|
||||
token_type = 0;
|
||||
if (getchar() == '.') {
|
||||
if (getchar() == '.') {
|
||||
if (readchar() == '.') {
|
||||
if (readchar() == '.') {
|
||||
token_type = TOKEN_ELLIPSIS;
|
||||
}
|
||||
}
|
||||
|
@ -826,7 +845,7 @@ void load(int rd, int rs) {
|
|||
}
|
||||
rs = rd;
|
||||
}
|
||||
printf(" %s %s, 0(%s) # load non-trivial register\n", op, rd_name, reg_name(rs));
|
||||
printf(" %s %s, 0(%s)\n", op, rd_name, reg_name(rs));
|
||||
}
|
||||
|
||||
// store a trivial register into a non-trivial one
|
||||
|
@ -839,7 +858,7 @@ void store(char* rs, int reg) {
|
|||
}
|
||||
reg = REG_T2;
|
||||
}
|
||||
printf(" %s %s, 0(%s) # store non-trivial register\n", op, rs, reg_name(reg));
|
||||
printf(" %s %s, 0(%s)\n", op, rs, reg_name(reg));
|
||||
}
|
||||
|
||||
int is_nontrivial(int reg) {
|
||||
|
@ -972,7 +991,7 @@ int lookup(int id) {
|
|||
char* name = id_table + id_lut[id];
|
||||
if (global_kind[id]) {
|
||||
if (global_kind[id] == KIND_FUNCTION) {
|
||||
fprintf(stderr, "function name must not appear outside function call: %s\n", name);
|
||||
fprintf(stderr, "function name can only be directly called: %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
int rd = next_reg(TYPE_VOID_PTR);
|
||||
|
@ -1974,6 +1993,7 @@ void parse_top_level() {
|
|||
}
|
||||
|
||||
void dump_string_table() {
|
||||
printf("# string table: \n");
|
||||
printf(".data\n");
|
||||
for (int i = 0; i < string_lut_size; ++i) {
|
||||
printf(".LC%d: .string \"", i);
|
||||
|
|
4
compile.sh
Normal file
4
compile.sh
Normal file
|
@ -0,0 +1,4 @@
|
|||
gcc boot.c -o boot.elf &&
|
||||
./boot.elf < $1 > $1.s
|
||||
python3 transcript.py < $1.s > $1.html
|
||||
rm boot.elf
|
9
demo/for.c
Normal file
9
demo/for.c
Normal file
|
@ -0,0 +1,9 @@
|
|||
int printf(char* format, ...);
|
||||
|
||||
int main() {
|
||||
int i;
|
||||
for (i = 0;
|
||||
i < 10;
|
||||
++i)
|
||||
printf("hello %d\n", i);
|
||||
}
|
114
transcript.py
Normal file
114
transcript.py
Normal file
|
@ -0,0 +1,114 @@
|
|||
import sys
|
||||
import html
|
||||
|
||||
src = ''
|
||||
asm = ''
|
||||
style = 0
|
||||
flip = False
|
||||
|
||||
def decorate(line):
|
||||
return f'<span class="style{style}">{html.escape(line)}</span>'
|
||||
|
||||
for line in sys.stdin:
|
||||
if line.startswith("#@"):
|
||||
line = line.removeprefix("#@")
|
||||
src += decorate(line) if flip else line
|
||||
style += 1
|
||||
style %= 5
|
||||
flip = False
|
||||
elif line.startswith("# string table: "):
|
||||
asm += line
|
||||
break
|
||||
else:
|
||||
asm += decorate(line)
|
||||
flip = True
|
||||
|
||||
for line in sys.stdin:
|
||||
asm += line
|
||||
|
||||
title = 'RVBTCC Code Gen Demo'
|
||||
|
||||
|
||||
template = '''
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><%title%></title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
header {
|
||||
background-color: #4CAF50;
|
||||
color: white;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
width: 80%;
|
||||
margin: 2em 0;
|
||||
}
|
||||
.column {
|
||||
flex: 1;
|
||||
margin: 0 1em;
|
||||
}
|
||||
pre {
|
||||
background-color: #f4f4f4;
|
||||
padding: 1em;
|
||||
border: 1px solid #ddd;
|
||||
overflow-x: auto;
|
||||
}
|
||||
code {
|
||||
font-family: 'Consolas', Consolas, monospace;
|
||||
font-size: 20px;
|
||||
}
|
||||
.style0 {
|
||||
background-color: rgba(255,129,130,0.4);
|
||||
}
|
||||
.style1 {
|
||||
background-color: rgba(212,167,44,0.4);
|
||||
}
|
||||
.style2 {
|
||||
background-color: rgba(74,194,107,0.4);
|
||||
}
|
||||
.style3 {
|
||||
background-color: rgba(84,174,255,0.4);
|
||||
}
|
||||
.style4 {
|
||||
background-color: rgba(194,151,255,0.4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1><%title%></h1>
|
||||
</header>
|
||||
<div class="container">
|
||||
<div class="column">
|
||||
<h2>Source Code</h2>
|
||||
<pre>
|
||||
<code><%src%></code>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="column">
|
||||
<h2>Assembly</h2>
|
||||
<pre>
|
||||
<code><%asm%></code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
print(template.replace("<%title%>", title).replace("<%src%>", src).replace("<%asm%>", asm))
|
Loading…
Add table
Add a link
Reference in a new issue