Skip to content

Commit

Permalink
Make cli parser handle unrecognized options
Browse files Browse the repository at this point in the history
  • Loading branch information
LesleyLai committed Jan 16, 2025
1 parent 9665728 commit e86807e
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 61 deletions.
7 changes: 4 additions & 3 deletions include/mcc/str.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ typedef struct StringBuffer {
Arena* allocator;
} StringBuffer;

StringView string_view_from_c_str(const char* source);
StringView string_view_from_buffer(const StringBuffer* buffer);
bool string_view_eq(StringView lhs, StringView rhs);
StringView str(const char* source); // Create a string view from c string
StringView str_from_buffer(const StringBuffer* buffer);
bool str_eq(StringView lhs, StringView rhs);
bool str_start_with(StringView s, StringView start);

StringBuffer string_buffer_new(Arena* allocator);
StringBuffer string_buffer_from_c_str(const char* source, Arena* allocator);
Expand Down
18 changes: 7 additions & 11 deletions src/frontend/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ static void parse_advance(Parser* parser)
parser->current_token_index++;
Token current = parser_current_token(parser);
if (current.type != TOKEN_ERROR) break;
parse_error_at(parser, string_view_from_c_str("unexpected character"),
current);
parse_error_at(parser, str("unexpected character"), current);
}
}

Expand All @@ -106,7 +105,7 @@ static void parse_consume(Parser* parser, TokenType type, const char* error_msg)
const Token current = parser_current_token(parser);

if (current.type != type) {
parse_error_at(parser, string_view_from_c_str(error_msg), current);
parse_error_at(parser, str(error_msg), current);
}

parse_advance(parser);
Expand Down Expand Up @@ -225,7 +224,7 @@ static Expr* parse_precedence(Parser* parser, Precedence precedence)
const PrefixParseFn prefix_rule =
get_rule(parser_previous_token(parser).type)->prefix;
if (prefix_rule == NULL) {
parse_error_at(parser, string_view_from_c_str("Expect valid expression"),
parse_error_at(parser, str("Expect valid expression"),
parser_previous_token(parser));
return NULL;
}
Expand Down Expand Up @@ -439,8 +438,7 @@ static void parse_stmt(Parser* parser, Stmt* out_stmt)
return;
}
default: {
parse_error_at(parser, string_view_from_c_str("Expect statement"),
current_token);
parse_error_at(parser, str("Expect statement"), current_token);
break;
}
}
Expand All @@ -458,8 +456,7 @@ static StringView parse_identifier(Parser* parser)
const Token current_token = parser_current_token(parser);

if (current_token.type != TOKEN_IDENTIFIER) {
parse_error_at(parser, string_view_from_c_str("Expect Identifier"),
current_token);
parse_error_at(parser, str("Expect Identifier"), current_token);
}
parse_advance(parser);
return (StringView){.start = parser->src + current_token.start,
Expand Down Expand Up @@ -522,9 +519,8 @@ ParseResult parse(const char* src_filename, const char* src, Tokens tokens,
.tokens = tokens,
.permanent_arena = permanent_arena,
.scratch_arena = scratch_arena,
.line_num_table =
get_line_num_table(src_filename, string_view_from_c_str(src),
permanent_arena, scratch_arena),
.line_num_table = get_line_num_table(src_filename, str(src),
permanent_arena, scratch_arena),
};

TranslationUnit* tu = parse_translation_unit(&parser);
Expand Down
8 changes: 4 additions & 4 deletions src/ir/ir_generator.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ static StringView create_fresh_variable_name(IRGenContext* context)
char* variable_name_buffer = allocate_printf(context->permanent_arena, "$%d",
context->fresh_variable_counter);
++context->fresh_variable_counter;
return string_view_from_c_str(variable_name_buffer);
return str(variable_name_buffer);
}

static StringView create_fresh_label_name(IRGenContext* context,
Expand All @@ -122,7 +122,7 @@ static StringView create_fresh_label_name(IRGenContext* context,
char* variable_name_buffer = allocate_printf(
context->permanent_arena, "%s_%d", name, context->fresh_label_counter);
++context->fresh_label_counter;
return string_view_from_c_str(variable_name_buffer);
return str(variable_name_buffer);
}

static IRValue emit_ir_instructions_from_expr(const Expr* expr,
Expand Down Expand Up @@ -165,7 +165,7 @@ static IRValue emit_ir_instructions_from_logical_and(const Expr* expr,
const StringView false_label = create_fresh_label_name(context, "and_false");
const StringView end_label = create_fresh_label_name(context, "and_end");

const IRValue result = ir_variable(string_view_from_c_str("result"));
const IRValue result = ir_variable(str("result"));

// br lhs .and_lhs_true .and_false
push_instruction(context, ir_br(lhs, lhs_true_label, false_label));
Expand Down Expand Up @@ -208,7 +208,7 @@ static IRValue emit_ir_instructions_from_logical_or(const Expr* expr,
const StringView true_label = create_fresh_label_name(context, "or_true");
const StringView end_label = create_fresh_label_name(context, "or_end");

const IRValue result = ir_variable(string_view_from_c_str("result"));
const IRValue result = ir_variable(str("result"));

// br lhs .or_true .or_lhs_false
push_instruction(context, ir_br(lhs, true_label, lhs_false_label));
Expand Down
12 changes: 5 additions & 7 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ static void print_parse_diagnostics(ParseErrorsView errors,
for (size_t i = 0; i < errors.length; ++i) {
StringBuffer output = string_buffer_new(&diagnostics_arena);
write_diagnostics(&output, src_filename, source, errors.data[i]);
StringView output_view = string_view_from_buffer(&output);
StringView output_view = str_from_buffer(&output);
fprintf(stderr, "%*s\n", (int)output_view.size, output_view.start);
arena_reset(&diagnostics_arena);
}
Expand All @@ -101,7 +101,7 @@ static StringBuffer replace_extension(const char* filename, const char* ext,

StringBuffer output = string_buffer_new(permanent_arena);
string_buffer_append(&output, name_without_ext);
string_buffer_append(&output, string_view_from_c_str(ext));
string_buffer_append(&output, str(ext));

return output;
}
Expand Down Expand Up @@ -166,9 +166,8 @@ int main(int argc, char* argv[])

Tokens tokens = lex(source, &permanent_arena, scratch_arena);
if (args.stop_after_lexer) {
const LineNumTable* line_num_table =
get_line_num_table(src_filename, string_view_from_c_str(source),
&permanent_arena, scratch_arena);
const LineNumTable* line_num_table = get_line_num_table(
src_filename, str(source), &permanent_arena, scratch_arena);

print_tokens(source, &tokens, line_num_table);

Expand Down Expand Up @@ -216,8 +215,7 @@ int main(int argc, char* argv[])

const StringBuffer obj_filename =
replace_extension(src_filename, ".o", &permanent_arena);
assemble(string_view_from_buffer(&asm_filename),
string_view_from_buffer(&obj_filename));
assemble(str_from_buffer(&asm_filename), str_from_buffer(&obj_filename));

if (args.stop_before_linker) { return 0; }

Expand Down
26 changes: 16 additions & 10 deletions src/utils/cli_args.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <mcc/cli_args.h>
#include <mcc/str.h>

#include <mcc/prelude.h>

Expand Down Expand Up @@ -39,28 +40,33 @@ CliArgs parse_cli_args(int argc, char** argv)
CliArgs result = {0};

for (int i = 1; i < argc; ++i) {
const char* arg = argv[i];
if (!strcmp(arg, "--help") || !strcmp(arg, "-h")) {
const StringView arg = str(argv[i]);

if (str_eq(arg, str("--help")) || str_eq(arg, str("-h"))) {
print_usage(stdout);
print_options();
exit(0);
} else if (!strcmp(arg, "--lex")) {
} else if (str_eq(arg, str("--lex"))) {
result.stop_after_lexer = true;
} else if (!strcmp(arg, "--parse")) {
} else if (str_eq(arg, str("--parse"))) {
result.stop_after_parser = true;
} else if (!strcmp(arg, "-S")) {
} else if (str_eq(arg, str("-S"))) {
result.compile_only = true;
} else if (!strcmp(arg, "-c")) {
} else if (str_eq(arg, str("-c"))) {
result.stop_before_linker = true;
} else if (!strcmp(arg, "--ir") || !strcmp(arg, "--tacky")) {
} else if (str_eq(arg, str("--ir")) || str_eq(arg, str("--tacky"))) {
// The --tacky command is used for "Writing a compiler" book's test cases
result.gen_ir_only = true;
} else if (!strcmp(arg, "--codegen")) {
// The --tacky command is used for "Writing a compiler" book's test cases
} else if (str_eq(arg, str("--codegen"))) {
result.codegen_only = true;
} else if (str_start_with(arg, str("-"))) {
(void)fprintf(
stderr,
"mcc: fatal error: unrecognized command-line option: '%.*s'\n",
(int)arg.size, arg.start);
} else {
// TODO: support more than one source file
result.source_filename = arg;
result.source_filename = argv[i];
}
}

Expand Down
14 changes: 10 additions & 4 deletions src/utils/str.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,31 @@ static_assert(sizeof(StringView) == 2 * sizeof(void*),
static_assert(sizeof(StringBuffer) == 4 * sizeof(void*),
"Size of a StringView should be 4 pointer size");

StringView string_view_from_c_str(const char* source)
StringView str(const char* source)
{
return (StringView){.start = source, .size = strlen(source)};
}

bool string_view_eq(StringView lhs, StringView rhs)
bool str_eq(StringView lhs, StringView rhs)
{
if (lhs.size != rhs.size) return false;
return strncmp(lhs.start, rhs.start, lhs.size) == 0;
}

bool str_start_with(StringView s, StringView start)
{
if (s.size < start.size) { return false; }
return strncmp(s.start, start.start, start.size) == 0;
}

StringBuffer string_buffer_new(Arena* allocator)
{
return (StringBuffer){.allocator = allocator};
}

StringBuffer string_buffer_from_c_str(const char* source, Arena* allocator)
{
return string_buffer_from_view(string_view_from_c_str(source), allocator);
return string_buffer_from_view(str(source), allocator);
}

StringBuffer string_buffer_from_view(StringView source, Arena* allocator)
Expand All @@ -44,7 +50,7 @@ StringBuffer string_buffer_from_view(StringView source, Arena* allocator)
return buffer;
}

StringView string_view_from_buffer(const StringBuffer* buffer)
StringView str_from_buffer(const StringBuffer* buffer)
{
return (StringView){.start = string_buffer_c_str(buffer),
.size = string_buffer_size(*buffer)};
Expand Down
4 changes: 2 additions & 2 deletions src/x86/x86_from_ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,10 @@ X86FunctionDef x86_function_from_ir(const IRFunctionDef* ir_function,
bool skip_else = false;

if (next_instruction != nullptr && next_instruction->typ == IR_LABEL) {
if (string_view_eq(next_instruction->label, if_label)) {
if (str_eq(next_instruction->label, if_label)) {
// If the if_label is directly follow this instruction
skip_if = true;
} else if (string_view_eq(next_instruction->label, else_label)) {
} else if (str_eq(next_instruction->label, else_label)) {
// If the else_label is directly follow this instruction
skip_else = true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/x86/x86_replace_pseudos.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ static intptr_t try_find_unique_name(const struct UniqueNameMap* map,
StringView name)
{
for (intptr_t i = 0; i < map->count; ++i) {
if (string_view_eq(map->unique_names[i], name)) { return i; }
if (str_eq(map->unique_names[i], name)) { return i; }
}
return -1;
}
Expand Down
2 changes: 1 addition & 1 deletion test/unit_tests/line_numbers_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ using Catch::Matchers::RangeEquals;

TEST_CASE("Line numbers calculation", "[lexer]")
{
const StringView src = string_view_from_c_str(R"(int main(void)
const StringView src = str(R"(int main(void)
{
return 0;
}
Expand Down
47 changes: 29 additions & 18 deletions test/unit_tests/string_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ extern "C" {

using namespace std::string_view_literals;

TEST_CASE("String View")
{
SECTION("str_eq")
{
REQUIRE(not str_eq(str("0"), str("012")));
REQUIRE(str_eq(str("123"), str("123")));
REQUIRE(not str_eq(str("123"), str("124")));
}

SECTION("str_start_with")
{
REQUIRE(not str_start_with(str("0"), str("012")));
REQUIRE(str_start_with(str("2134"), str("21")));
REQUIRE(not str_start_with(str("234"), str("21")));
}
}

TEST_CASE("String Buffer")
{
constexpr auto buffer_size = 1000;
Expand All @@ -24,10 +41,8 @@ TEST_CASE("String Buffer")
string_buffer_push(&string, 'a');
REQUIRE(string_buffer_size(string) == 1);
REQUIRE(string_buffer_data(&string)[0] == 'a');
REQUIRE(string_view_eq(string_view_from_buffer(&string),
string_view_from_c_str("a")));
REQUIRE(!string_view_eq(string_view_from_buffer(&string),
string_view_from_c_str("")));
REQUIRE(str_eq(str_from_buffer(&string), str("a")));
REQUIRE(!str_eq(str_from_buffer(&string), str("")));
}

SECTION("StringBuffer can grow from small to large")
Expand All @@ -53,35 +68,31 @@ TEST_CASE("String Buffer")
SECTION("Small to small")
{
auto string = string_buffer_from_c_str("Hello, ", &arena);
string_buffer_append(&string, string_view_from_c_str("world!"));
string_buffer_append(&string, str("world!"));

REQUIRE(string_view_eq(string_view_from_buffer(&string),
string_view_from_c_str("Hello, world!")));
REQUIRE(str_eq(str_from_buffer(&string), str("Hello, world!")));
}

SECTION("Small to large")
{
auto string = string_buffer_from_c_str("Hello ", &arena);
string_buffer_append(&string,
string_view_from_c_str(
"from this really really really weird string!"));
str("from this really really really weird string!"));

REQUIRE(string_view_eq(
string_view_from_buffer(&string),
string_view_from_c_str(
"Hello from this really really really weird string!")));
REQUIRE(
str_eq(str_from_buffer(&string),
str("Hello from this really really really weird string!")));
}

SECTION("Large to large")
{
auto string = string_buffer_from_c_str(
"Hello from this really really really ", &arena);
string_buffer_append(&string, string_view_from_c_str("weird string!"));
string_buffer_append(&string, str("weird string!"));

REQUIRE(string_view_eq(
string_view_from_buffer(&string),
string_view_from_c_str(
"Hello from this really really really weird string!")));
REQUIRE(
str_eq(str_from_buffer(&string),
str("Hello from this really really really weird string!")));
}
}
}

0 comments on commit e86807e

Please sign in to comment.