Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate file with file name #100

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion shivyc/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ def main():
if any(not obj for obj in objs):
return 1
else:
if not link("out", objs):
# set the output ELF name
out = "out"
if arguments.output_name is not None:
out = arguments.output_name
if not link(out, objs):
err = "linker returned non-zero status"
print(CompilerError(err))
return 1
Expand Down Expand Up @@ -118,6 +122,12 @@ def get_arguments():
parser.add_argument("-z-reg-alloc-perf",
help="display register allocator performance info",
dest="show_reg_alloc_perf", action="store_true")
parser.add_argument(
"-o",
nargs="?",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am not mistaken, as written this will accept the command shivyc -o without warning or error. However, it appears GCC prints an error here, so we should do the same.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix this on new pull request #101 .Code review is required.

metavar="file",
help="Place output into <file>",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpicky: for consistency, could you make the first letter of the help string lowercase?

dest="output_name")

return parser.parse_args()

Expand Down
20 changes: 16 additions & 4 deletions shivyc/parser/declaration.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,10 +252,21 @@ def parse_parameter_list(index):
if token_is(index, token_kinds.close_paren):
return params, index

# argument is void and is not function declaration
if token_is(index, token_kinds.void_kw) \
and token_is(index + 1, token_kinds.close_paren):
if token_is(index + 2, token_kinds.open_brack):
return params, index + 1
elif token_is(index + 1, token_kinds.identifier):
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused by this code. Isn't the token at index + 1 always going to be a close parenthesis here?

I think it would be easier to implement this in the semantic stage of the compiler (i.e. in the tree/ directory) rather than in the parser, since this isn't really a parsing issue as much as it's a semantic one.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix this on new pull request #102

err = "'void' must be the only parameter"
raise_error(err, index, ParserError.AT)

while True:
# Try parsing declaration specifiers, quit if no more exist
specs, index = parse_decl_specifiers(index)
decl, index = parse_declarator(index)

# New ast root
params.append(decl_nodes.Root(specs, [decl]))

# Expect a comma, and break if there isn't one
Expand Down Expand Up @@ -357,8 +368,8 @@ def _find_decl_end(index):
greater than the last index in this declarator.
"""
if (token_is(index, token_kinds.star) or
token_is(index, token_kinds.identifier) or
token_is(index, token_kinds.const_kw)):
token_is(index, token_kinds.identifier) or
token_is(index, token_kinds.const_kw)):
return _find_decl_end(index + 1)
elif token_is(index, token_kinds.open_paren):
close = _find_pair_forward(index)
Expand Down Expand Up @@ -392,7 +403,7 @@ def _parse_declarator_raw(start, end, is_typedef):
return decl_nodes.Identifier(None)

elif (start + 1 == end and
p.tokens[start].kind == token_kinds.identifier):
p.tokens[start].kind == token_kinds.identifier):
p.symbols.add_symbol(p.tokens[start], is_typedef)
return decl_nodes.Identifier(p.tokens[start])

Expand All @@ -402,7 +413,8 @@ def _parse_declarator_raw(start, end, is_typedef):
_parse_declarator(index, end, is_typedef), const)

func_decl = _try_parse_func_decl(start, end, is_typedef)
if func_decl: return func_decl
if func_decl:
return func_decl

# First and last elements make a parenthesis pair
elif (p.tokens[start].kind == token_kinds.open_paren and
Expand Down
10 changes: 10 additions & 0 deletions shivyc/tree/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,8 @@ def _generate_array_ctype(self, decl, prev_ctype):

def _generate_func_ctype(self, decl, prev_ctype):
"""Generate a function ctype from a given a decl_node."""
# save identifiers
identifiers = []
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you do this more easily on line 546 instead?

Copy link
Author

@splasky splasky May 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean checking redefinition of identifier inside make_ctype?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix this on #104


# Prohibit storage class specifiers in parameters.
for param in decl.args:
Expand All @@ -608,6 +610,14 @@ def _generate_func_ctype(self, decl, prev_ctype):
err = "storage class specified for function parameter"
raise CompilerError(err, decl_info.range)

if decl_info.identifier:
identifier = str(decl_info.identifier)
if identifier not in identifiers:
identifiers.append(str(decl_info.identifier))
else:
err = f"redefinition of '{identifier}'"
raise CompilerError(err, decl_info.range)

# Create a new scope because if we create a new struct type inside
# the function parameters, it should be local to those parameters.
self.symbol_table.new_scope()
Expand Down
3 changes: 3 additions & 0 deletions tests/feature_tests/error_declaration.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ int var1;
// error: redeclared 'var1' with different linkage
static int var1;

// error: redefinition of 'a'
void repeat_param(int a, int a);

int main() {
// error: variable of incomplete type declared
void a;
Expand Down
7 changes: 7 additions & 0 deletions tests/feature_tests/error_function_def.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ const int func() {
return 4;
}

int func_void(void) {
return 4;
}

// error: 'void' must be the only parameter
int func_void_void(void a,void b){}

// error: redefinition of 'a'
void repeat_param(int a, int a) { }

Expand Down
1 change: 1 addition & 0 deletions tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class MockArguments:
files = test_file_names
show_reg_alloc_perf = False
variables_on_stack = False
output_name = None

shivyc.main.get_arguments = lambda: MockArguments()

Expand Down