diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 379a1dde..7a7ac47e 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -34,6 +34,7 @@ "milestone-5/cpp08": "1.1.0", "milestone-5/cpp09": "1.0.1", "milestone-5/inception": "1.0.0", + "pcc/b": "0.0.0", "pcc/libasm": "1.0.0", "rushes/hotrace": "2.1.0", "rushes/libunit": "1.0.0", diff --git a/flake.nix b/flake.nix index 5f546d87..499d2abe 100644 --- a/flake.nix +++ b/flake.nix @@ -68,6 +68,10 @@ # ASM nasm + # Compiler compilers + bison # yacc + flex # lex + # Rust pkg-config rustc diff --git a/milestone-5/cpp09/version.txt b/milestone-5/cpp09/version.txt new file mode 100644 index 00000000..77d6f4ca --- /dev/null +++ b/milestone-5/cpp09/version.txt @@ -0,0 +1 @@ +0.0.0 diff --git a/pcc/b/.gitignore b/pcc/b/.gitignore new file mode 100644 index 00000000..5d2a1e85 --- /dev/null +++ b/pcc/b/.gitignore @@ -0,0 +1,4 @@ +B +*.h +*.c + diff --git a/pcc/b/Makefile b/pcc/b/Makefile new file mode 100644 index 00000000..f821f207 --- /dev/null +++ b/pcc/b/Makefile @@ -0,0 +1,24 @@ +NAME = B +CC = gcc +CFLAGS = -Wall -Wextra -Werror + +all: $(NAME) + +$(NAME): y.tab.c lex.yy.c + $(CC) $(CFLAGS) -o $(NAME) y.tab.c lex.yy.c + +y.tab.c y.tab.h: parser.y + yacc -d parser.y + +lex.yy.c: lexer.l y.tab.h + lex lexer.l + +clean: + rm -f lex.yy.c y.tab.c y.tab.h + +fclean: clean + rm -f $(NAME) + +re: fclean all + +.PHONY: all clean fclean re diff --git a/pcc/b/lexer.l b/pcc/b/lexer.l new file mode 100644 index 00000000..f9e04709 --- /dev/null +++ b/pcc/b/lexer.l @@ -0,0 +1,40 @@ +%{ +#include "y.tab.h" // tokens generated by yacc +#include + +// The below 'option' call voids some unused functions +// Older versions of lex might not recognize this line +%} + +%option nounput noinput + +%% + +"auto" { return AUTO; } +"extrn" { return EXTERN; } + +[a-zA-Z_][a-zA-Z0-9_]* { + yylval.str = strdup(yytext); // dupe + return IDENTIFIER; + } + +[0-9]+ { + yylval.num = atoi(yytext); + return NUMBER; + } + +[ \t\n]+ { /* ignore whitespaces */ } + +"=" { return EQUALS; } +";" { return SEMICOLON; } +"," { return ','; } +"(" { return '('; } +")" { return ')'; } +"{" { return '{'; } +"}" { return '}'; } + +%% + +int yywrap() { + return 1; +} diff --git a/pcc/b/parser.y b/pcc/b/parser.y new file mode 100644 index 00000000..58002202 --- /dev/null +++ b/pcc/b/parser.y @@ -0,0 +1,138 @@ +%{ +#include +#include +#include +#include + +int yylex(void); +void yyerror(const char *s); + +typedef enum { + TYPE_AUTO, + TYPE_EXTERN +} SymbolType; + +typedef struct { + char *name; + SymbolType type; + int offset; // ebp +} Symbol; + +void *sym_table = NULL; +int current_local_offset = -4; + +// required by tsearch +int compare_symbols(const void *pa, const void *pb) { + return strcmp(((const Symbol *)pa)->name, ((const Symbol *)pb)->name); +} + +void add_symbol(char *name, SymbolType type) { + Symbol *sym = malloc(sizeof(Symbol)); + sym->name = strdup(name); + sym->type = type; + + if (type == TYPE_AUTO) { + sym->offset = current_local_offset; + // shift down 4 for next var + current_local_offset -= 4; + } else { + // extern symbols don't use edp offset + sym->offset = 0; + } + + // insertion + Symbol **found = tsearch(sym, &sym_table, compare_symbols); + if (*found != sym) { + // var was already in the tree + free(sym->name); + free(sym); + } +} + +Symbol *get_symbol(char *name) { + Symbol dummy; + dummy.name = name; + Symbol **found = tfind(&dummy, &sym_table, compare_symbols); + if (found) { + return *found; + } + return NULL; +} +%} + +%union { + int num; + char *str; +} + +%token IDENTIFIER +%token NUMBER +%token EQUALS SEMICOLON AUTO EXTERN + +%% + +program: + | program statement + | program function_definition + ; + +declarations: + | declarations declaration + ; + +declaration: + AUTO auto_list SEMICOLON + | EXTERN extrn_list SEMICOLON + ; + +auto_list: + IDENTIFIER { add_symbol($1, TYPE_AUTO); } + | auto_list ',' IDENTIFIER { add_symbol($3, TYPE_AUTO); } + ; + +extrn_list: + IDENTIFIER { add_symbol($1, TYPE_EXTERN); } + | extrn_list ',' IDENTIFIER { add_symbol($3, TYPE_EXTERN); } + ; + +statements_list: + | statements_list statement + ; + +statement: + IDENTIFIER EQUALS NUMBER SEMICOLON { + Symbol *sym = get_symbol($1); + + if (sym && sym->type == TYPE_AUTO) { + printf("\tmov eax, %d\n", $3); + printf("\tmov [ebp%d], eax ; store val in %s\n", sym->offset, $1); + } else + fprintf(stderr, "Error: Unknown or non-auto variable '%s'\n", $1); + } + ; + +function_definition: + IDENTIFIER '(' ')' '{' { + printf("%s:\n", $1); + printf("\t.long %s + 4\n", $1); + printf("\tenter 0, 0\n"); + // reset offset tracker for new func + current_local_offset = -4; + } + declarations + statements_list + '}' { + printf("\tleave\n"); + printf("\tret\n"); + } + ; + +%% + +void yyerror(const char *s) { + fprintf(stderr, "Error: %s\n", s); +} + +int main(void) { + return yyparse(); +} diff --git a/pcc/b/test1.b b/pcc/b/test1.b new file mode 100644 index 00000000..06c4f471 --- /dev/null +++ b/pcc/b/test1.b @@ -0,0 +1,4 @@ +main() { + i = 0; +} + diff --git a/pcc/b/test2.b b/pcc/b/test2.b new file mode 100644 index 00000000..907083a2 --- /dev/null +++ b/pcc/b/test2.b @@ -0,0 +1,6 @@ +main() { + auto i, s, x; + i = 0; + s = 42; + x = 100; +} diff --git a/pcc/b/test_final.b b/pcc/b/test_final.b new file mode 100644 index 00000000..a555e8b8 --- /dev/null +++ b/pcc/b/test_final.b @@ -0,0 +1,11 @@ +main() { + extrn putchar, char; + auto i, s; + i = 0; + s = "hello, world\n"; + while (char(s, i)) { + putchar(char(s, i)); + i++; + } +} + diff --git a/pcc/b/version.txt b/pcc/b/version.txt new file mode 100644 index 00000000..77d6f4ca --- /dev/null +++ b/pcc/b/version.txt @@ -0,0 +1 @@ +0.0.0 diff --git a/pcc/libasm/version.txt b/pcc/libasm/version.txt new file mode 100644 index 00000000..77d6f4ca --- /dev/null +++ b/pcc/libasm/version.txt @@ -0,0 +1 @@ +0.0.0 diff --git a/piscine-c/c00/version.txt b/piscine-c/c00/version.txt new file mode 100644 index 00000000..77d6f4ca --- /dev/null +++ b/piscine-c/c00/version.txt @@ -0,0 +1 @@ +0.0.0 diff --git a/release-please-config.json b/release-please-config.json index 549214f7..e50ad7b4 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -141,6 +141,10 @@ "release-type": "simple", "package-name": "inception" }, + "pcc/b": { + "release-type": "simple", + "package-name": "b" + }, "pcc/libasm": { "release-type": "simple", "package-name": "libasm"