Skip to content
This repository has been archived by the owner on Jun 28, 2024. It is now read-only.

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
sghuang19 committed Oct 12, 2023
1 parent 00f692a commit 35773a9
Show file tree
Hide file tree
Showing 20 changed files with 443 additions and 182 deletions.
17 changes: 15 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
bminor: bminor.c encoder.o scanner.o lex.yy.o
bminor: bminor.c encoder.o scanner.o lex.yy.o parser.o grammar.tab.o
gcc $^ -o $@

encoder.o: encoder.c
Expand All @@ -10,7 +10,16 @@ lex.yy.c: lex.yy.l
lex.yy.o: lex.yy.c
gcc -c $^ -o $@

scanner.o: scanner.c
scanner.o: scanner.c token.h
gcc -c $< -o $@

parser.o: parser.c
gcc -c $^ -o $@

grammar.tab.c token.h: grammar.y lex.yy.c
bison -v --defines=token.h $<

grammar.tab.o: grammar.tab.c
gcc -c $^ -o $@

# Tests
Expand All @@ -20,8 +29,12 @@ test-encoder:
test-scanner:
./runtest.sh scanner

test-parser:
./runtest.sh parser

clean:
rm -f lex.yy.c
rm -f token.h grammar.tab.c grammar.output
rm -f *.o
rm -f ./test/*/*.bminor.out
rm -f bminor
93 changes: 41 additions & 52 deletions bminor.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "encoder.h"
#include "scanner.h"
#include "parser.h"

void usage(int exit_code)
{
Expand All @@ -13,61 +14,49 @@ void usage(int exit_code)

int main(int argc, char* argv[])
{
char* option, * filename;

if (argc == 1)
usage(1);
switch (argc)
{
case 1:
usage(EXIT_FAILURE);
break;
case 2:
if (strcmp(argv[1], "--help") == 0)
usage(EXIT_SUCCESS);
else usage(EXIT_FAILURE);
break;
case 3:
option = argv[1];
filename = argv[2];
break;
default:
fprintf(stderr, "Too many arguments.\n");
usage(EXIT_FAILURE);
break;
}

for (int i = 1; i < argc; i++)
if (strcmp(option, "--encode") == 0)
{
if (decode(filename) == 0)
return EXIT_SUCCESS;
}
else if (strcmp(option, "--scan") == 0)
{
if (scan(filename) == 0)
return EXIT_SUCCESS;
}
else if (strcmp(option, "--parse") == 0)
{
if (parse(filename) == 0)
return EXIT_SUCCESS;
}
else
{
if (argv[i][0] == '-')
{
if (strcmp(argv[i], "--help") == 0)
usage(0);
else if (strcmp(argv[i], "--encode") == 0)
{
const char* filename = argv[++i];
if (filename)
{
if (decode(filename) == 0)
return EXIT_SUCCESS;
else
{
fprintf(stderr, "Failed to decode file %s\n", filename);
return EXIT_FAILURE;
}
}
else
{
fprintf(stderr, "Missing filename to be encoded\n");
return EXIT_FAILURE;
}
}
else if (strcmp(argv[i], "--scan") == 0)
{
const char* filename = argv[++i];
if (filename)
{
if (scan(filename) == 0)
return EXIT_SUCCESS;
else
{
fprintf(stderr, "Failed to scan file %s\n", filename);
return EXIT_FAILURE;
}
}
else
{
fprintf(stderr, "Missing filename to be scanned\n");
return EXIT_FAILURE;
}
}
else
{
fprintf(stderr, "Unknown option '%s'\n", argv[i]);
usage(1);
}
}
fprintf(stderr, "Unknown option '%s'\n", option);
usage(EXIT_FAILURE);
}

return EXIT_SUCCESS;
fprintf(stderr, "Failed to %s file %s\n", option + 2, filename);
return EXIT_FAILURE;
}
244 changes: 244 additions & 0 deletions grammar.y
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
%{
#include <stdio.h>
#define YYDEBUG 1

extern int yylex();
extern int yylineno;
extern char *yytext;

void yyerror(const char *s) {
fprintf(stderr, "Error: %s at line %d near '%s'\n", s, yylineno, yytext);
}
%}

/* Keywords */
%token TOKEN_ARRAY
%token TOKEN_AUTO
%token TOKEN_BOOLEAN
%token TOKEN_CHAR
%token TOKEN_ELSE
%token TOKEN_FALSE
%token TOKEN_FLOAT
%token TOKEN_FOR
%token TOKEN_FUNCTION
%token TOKEN_IF
%token TOKEN_INTEGER
%token TOKEN_PRINT
%token TOKEN_RETURN
%token TOKEN_STRING
%token TOKEN_TRUE
%token TOKEN_VOID
%token TOKEN_WHILE

/* Operators */
%token TOKEN_INCREMENT
%token TOKEN_DECREMENT
%token TOKEN_EXPONENT
%token TOKEN_MULTIPLY
%token TOKEN_DIVIDE
%token TOKEN_MODULO
%token TOKEN_ADD
%token TOKEN_MINUS
%token TOKEN_LESS
%token TOKEN_LESS_OR_EQUAL
%token TOKEN_GREATER
%token TOKEN_GREATER_OR_EQUAL
%token TOKEN_EQUAL
%token TOKEN_NOT_EQUAL
%token TOKEN_LOGICAL_AND
%token TOKEN_LOGICAL_OR
%token TOKEN_LOGICAL_NOT
%token TOKEN_ASSIGN

/* Symbols */
%token TOKEN_LPAREN
%token TOKEN_RPAREN
%token TOKEN_LBRACKET
%token TOKEN_RBRACKET
%token TOKEN_LBRACE
%token TOKEN_RBRACE
%token TOKEN_SEMICOLON
%token TOKEN_COLON
%token TOKEN_COMMA

/* Identifiers and Literals */
%token TOKEN_ID
%token TOKEN_INT_LITERAL
%token TOKEN_FLOAT_LITERAL
%token TOKEN_CHAR_LITERAL
%token TOKEN_STRING_LITERAL

/* Error */
%token TOKEN_EOF
%token TOKEN_ERROR

%%
prog : decl_list TOKEN_EOF
;

/* Declarations */

decl_list : /* epsilon */
| decl_list decl
;

decl : param TOKEN_SEMICOLON
| param TOKEN_ASSIGN init
;

init : expr TOKEN_SEMICOLON
| TOKEN_LBRACE opt_stmt_list TOKEN_RBRACE /* function body */
| TOKEN_LBRACE expr_list TOKEN_RBRACE /* array */
;

/* Statements */

opt_stmt_list : /* epsilon */
| stmt_list
;

stmt_list : stmt
| stmt_list stmt
;

stmt : TOKEN_LBRACE stmt_list TOKEN_RBRACE
| for_loop
| if_cond
| print_stmt
| return_stmt
| decl
| expr TOKEN_SEMICOLON
;

for_loop : TOKEN_FOR TOKEN_LPAREN
opt_expr TOKEN_SEMICOLON opt_expr TOKEN_SEMICOLON opt_expr
TOKEN_RPAREN stmt
;

if_cond : TOKEN_IF TOKEN_LPAREN opt_expr TOKEN_RPAREN else_stmt
;

else_stmt : TOKEN_ELSE stmt
| /* epsilon */
;

print_stmt : TOKEN_PRINT opt_expr_list TOKEN_SEMICOLON
;

return_stmt : TOKEN_RETURN opt_expr TOKEN_SEMICOLON
;

/* Expressions */

opt_expr_list : /* epsilon */
| expr_list
;

expr_list : expr
| expr_list TOKEN_COMMA expr
;

opt_expr : /* epsilon */
| expr
;

expr : expr1
;

expr1 : lval TOKEN_ASSIGN expr1
| expr2
;

lval : TOKEN_ID
| TOKEN_ID index
;

expr2 : expr2 TOKEN_LOGICAL_OR expr3
| expr3
;

expr3 : expr3 TOKEN_LOGICAL_AND expr4
| expr4
;

expr4 : expr4 TOKEN_EQUAL expr5
| expr4 TOKEN_NOT_EQUAL expr5
| expr4 TOKEN_LESS expr5
| expr4 TOKEN_LESS_OR_EQUAL expr5
| expr4 TOKEN_GREATER expr5
| expr4 TOKEN_GREATER_OR_EQUAL expr5
| expr5
;

expr5 : expr5 TOKEN_ADD expr6
| expr5 TOKEN_MINUS expr6
| expr6
;

expr6 : expr6 TOKEN_MULTIPLY expr7
| expr6 TOKEN_DIVIDE expr7
| expr6 TOKEN_MODULO expr7
| expr7
;

expr7 : expr7 TOKEN_EXPONENT expr8
| expr8
;

expr8 : TOKEN_MINUS expr8
| TOKEN_LOGICAL_NOT expr8
| expr9
;

expr9 : expr9 TOKEN_INCREMENT
| expr9 TOKEN_DECREMENT
| group
;

group : TOKEN_LPAREN expr TOKEN_RPAREN
| TOKEN_ID TOKEN_LPAREN opt_expr_list TOKEN_RPAREN
| TOKEN_ID index
| factor
;

index : TOKEN_LBRACKET expr TOKEN_RBRACKET
;

factor : TOKEN_ID
| TOKEN_INT_LITERAL
| TOKEN_FLOAT_LITERAL
| TOKEN_CHAR_LITERAL
| TOKEN_STRING_LITERAL
| TOKEN_TRUE
| TOKEN_FALSE
;

/* Types */

type : TOKEN_INTEGER
| TOKEN_FLOAT
| TOKEN_BOOLEAN
| TOKEN_CHAR
| TOKEN_STRING
| TOKEN_VOID
| TOKEN_ARRAY index type
| type_func
;

type_func : TOKEN_FUNCTION type TOKEN_LPAREN opt_param_list TOKEN_RPAREN
;

opt_param_list : /* epsilon */
| param_list
;

param_list : param
| param_list TOKEN_COMMA param
;

param : TOKEN_ID TOKEN_COLON type
;

%%

// int yywrap() { return 0; }
Loading

0 comments on commit 35773a9

Please sign in to comment.