-
Notifications
You must be signed in to change notification settings - Fork 131
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add to allow use comments in other scopes that is not from a fu…
…nction (#454) * feat: add to allow use comments in other scopes that is not from a function * feat: add tests for comments in diff scopes * fix: add errors that appeared in 'test_comments.c' after merge
- Loading branch information
Showing
7 changed files
with
150 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,56 @@ | ||
from norminette.rules import Rule | ||
|
||
allowed_on_comment = ["COMMENT", "MULT_COMMENT", "SPACE", "TAB"] | ||
|
||
|
||
class CheckComment(Rule): | ||
def __init__(self): | ||
super().__init__() | ||
self.depends_on = [] | ||
|
||
def run(self, context): | ||
""" | ||
Comments are only allowed in GlobalScope. | ||
Comments are forbidden inside functions and in the middle of instructions. | ||
""" | ||
i = context.skip_ws(0) | ||
has_comment = False | ||
while ( | ||
context.peek_token(i) is not None | ||
and context.check_token(i, "NEWLINE") is False | ||
): | ||
if context.check_token(i, allowed_on_comment) is False: | ||
if has_comment is True: | ||
context.new_error("COMMENT_ON_INSTR", context.peek_token(i)) | ||
return True, i | ||
elif context.check_token(i, ["COMMENT", "MULT_COMMENT"]) is True: | ||
if ( | ||
context.scope.name != "GlobalScope" | ||
or context.history[-1] == "IsFuncDeclaration" | ||
): | ||
context.new_error("WRONG_SCOPE_COMMENT", context.peek_token(i)) | ||
has_comment = True | ||
|
||
tokens = [] | ||
while context.peek_token(i) and not context.check_token(i, "NEWLINE"): | ||
token = context.peek_token(i) | ||
tokens.append(token) | ||
i += 1 | ||
i = context.skip_ws(0) | ||
return False, 0 | ||
|
||
for index, token in enumerate(tokens): | ||
if token.type in ("COMMENT", "MULT_COMMENT"): | ||
if self.is_inside_a_function(context): | ||
context.new_error("WRONG_SCOPE_COMMENT", token) | ||
if index == 0 or self.is_last_token(token, tokens[index+1:]): | ||
continue | ||
context.new_error("COMMENT_ON_INSTR", token) | ||
|
||
def is_inside_a_function(self, context): | ||
if context.history[-2:] == ["IsFuncDeclaration", "IsBlockStart"]: | ||
return True | ||
if context.scope.__class__.__name__.lower() == "function": | ||
return True | ||
# Sometimes the context scope is a `ControlStructure` scope instead of | ||
# `Function` scope, so, to outsmart this bug, we need check manually | ||
# the `context.history`. | ||
last = None | ||
for index, record in enumerate(reversed(context.history)): | ||
if record == "IsFuncDeclaration" and last == "IsBlockStart": | ||
# Since the limited history API, we can't say if we're in a | ||
# nested function to reach the first enclosing function, so, | ||
# we'll consider that the user just declared a normal function | ||
# in global scope. | ||
stack = 1 | ||
index -= 1 # Jumps to next record after `IsBlockStart` | ||
while index > 0 and stack > 0: | ||
record = context.history[-index] | ||
index -= 1 | ||
if record not in ("IsBlockStart", "IsBlockEnd"): | ||
continue | ||
stack = stack + (1, -1)[record == "IsBlockEnd"] | ||
return bool(stack) | ||
last = record | ||
return False | ||
|
||
def is_last_token(self, token, foward): | ||
expected = ("SPACE", "TAB") | ||
if token.type == "MULT_COMMENT": | ||
expected += ("COMMENT", "MULT_COMMENT") | ||
return all(it.type in ("SPACE", "TAB", "COMMENT", "MULT_COMMENT") for it in foward) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
struct { | ||
// points is to something | ||
int points; // is an int :D | ||
}; | ||
|
||
typedef /* oopss */ bool bool; | ||
|
||
enum test { | ||
// blaboe | ||
hello, // it works | ||
/* error*/ error | ||
}; | ||
|
||
void hello(/* nothing */ void) // error because comment is in middle of the line | ||
{ | ||
// error because scope is from a function | ||
{ | ||
// are you trying to cheat? | ||
// error because scope is from a function | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
[36mtest_comments.c[0m - [32mIsUserDefinedType[0m In "GlobalScope" from "None" line 1": | ||
<STRUCT> <SPACE> <LBRACE> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "UserDefinedType" from "GlobalScope" line 2": | ||
<TAB> <COMMENT=// points is to something> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsVarDeclaration[0m In "UserDefinedType" from "GlobalScope" line 3": | ||
<TAB> <INT> <TAB> <IDENTIFIER=points> <SEMI_COLON> <SPACE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "UserDefinedType" from "GlobalScope" line 3": | ||
<COMMENT=// is an int :D> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsBlockEnd[0m In "UserDefinedType" from "GlobalScope" line 4": | ||
<RBRACE> <SEMI_COLON> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsEmptyLine[0m In "GlobalScope" from "None" line 5": | ||
<NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsUserDefinedType[0m In "GlobalScope" from "None" line 6": | ||
<TYPEDEF> <SPACE> <MULT_COMMENT=/* oopss */> <SPACE> <IDENTIFIER=bool> <SPACE> <IDENTIFIER=bool> <SEMI_COLON> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsEmptyLine[0m In "GlobalScope" from "None" line 7": | ||
<NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsUserDefinedType[0m In "GlobalScope" from "None" line 8": | ||
<ENUM> <SPACE> <IDENTIFIER=test> <SPACE> <LBRACE> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "UserDefinedEnum" from "GlobalScope" line 9": | ||
<SPACE> <SPACE> <SPACE> <SPACE> <COMMENT=// blaboe> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsEnumVarDecl[0m In "UserDefinedEnum" from "GlobalScope" line 10": | ||
<SPACE> <SPACE> <SPACE> <SPACE> <IDENTIFIER=hello> <COMMA> <SPACE> <SPACE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "UserDefinedEnum" from "GlobalScope" line 10": | ||
<COMMENT=// it works> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "UserDefinedEnum" from "GlobalScope" line 11": | ||
<SPACE> <SPACE> <SPACE> <SPACE> <MULT_COMMENT=/* error*/> <SPACE> | ||
[36mtest_comments.c[0m - [32mIsEnumVarDecl[0m In "UserDefinedEnum" from "GlobalScope" line 11": | ||
<IDENTIFIER=error> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsBlockEnd[0m In "UserDefinedEnum" from "GlobalScope" line 12": | ||
<RBRACE> <SEMI_COLON> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsEmptyLine[0m In "GlobalScope" from "None" line 13": | ||
<NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsFuncDeclaration[0m In "GlobalScope" from "None" line 14": | ||
<VOID> <SPACE> <IDENTIFIER=hello> <LPARENTHESIS> <MULT_COMMENT=/* nothing */> <SPACE> <VOID> <RPARENTHESIS> <SPACE> <COMMENT=// error because comment is in middle of the line> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsBlockStart[0m In "Function" from "GlobalScope" line 15": | ||
<LBRACE> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "Function" from "GlobalScope" line 16": | ||
<SPACE> <SPACE> <SPACE> <COMMENT=// error because scope is from a function> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsBlockStart[0m In "Function" from "GlobalScope" line 17": | ||
<SPACE> <SPACE> <SPACE> <LBRACE> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "ControlStructure" from "Function" line 18": | ||
<SPACE> <SPACE> <SPACE> <SPACE> <SPACE> <SPACE> <COMMENT=// are you trying to cheat?> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsComment[0m In "ControlStructure" from "Function" line 19": | ||
<SPACE> <SPACE> <SPACE> <SPACE> <SPACE> <SPACE> <COMMENT=// error because scope is from a function> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsBlockEnd[0m In "ControlStructure" from "Function" line 20": | ||
<SPACE> <SPACE> <SPACE> <RBRACE> <NEWLINE> | ||
[36mtest_comments.c[0m - [32mIsBlockEnd[0m In "Function" from "GlobalScope" line 21": | ||
<RBRACE> <NEWLINE> | ||
test_comments.c: Error! | ||
Error: INVALID_HEADER (line: 1, col: 1): Missing or invalid 42 header | ||
Error: BRACE_NEWLINE (line: 1, col: 8): Expected newline before brace | ||
Error: COMMENT_ON_INSTR (line: 6, col: 9): Comment must be on its own line or at end of a line | ||
Error: SPACE_REPLACE_TAB (line: 6, col: 25): Found space when expecting tab | ||
Error: USER_DEFINED_TYPEDEF (line: 6, col: 26): User defined typedef must start with t_ | ||
Error: ENUM_TYPE_NAMING (line: 8, col: 6): Enum name must start with e_ | ||
Error: BRACE_NEWLINE (line: 8, col: 11): Expected newline before brace | ||
Error: SPACE_EMPTY_LINE (line: 9, col: 5): Space on empty line | ||
Error: TOO_FEW_TAB (line: 10, col: 1): Missing tabs for indent level | ||
Error: SPACE_REPLACE_TAB (line: 10, col: 5): Found space when expecting tab | ||
Error: CONSECUTIVE_SPC (line: 10, col: 11): Two or more consecutives spaces | ||
Error: SPACE_REPLACE_TAB (line: 11, col: 5): Found space when expecting tab | ||
Error: TOO_FEW_TAB (line: 11, col: 16): Missing tabs for indent level | ||
Error: SPACE_BEFORE_FUNC (line: 14, col: 5): space before function name | ||
Error: COMMENT_ON_INSTR (line: 14, col: 12): Comment must be on its own line or at end of a line | ||
Error: MISSING_IDENTIFIER (line: 14, col: 25): missing type qualifier or identifier in function arguments | ||
Error: SPACE_EMPTY_LINE (line: 16, col: 4): Space on empty line | ||
Error: WRONG_SCOPE_COMMENT (line: 16, col: 4): Comment is invalid in this scope | ||
Error: TOO_FEW_TAB (line: 17, col: 1): Missing tabs for indent level | ||
Error: SPACE_EMPTY_LINE (line: 17, col: 4): Space on empty line | ||
Error: SPACE_EMPTY_LINE (line: 18, col: 7): Space on empty line | ||
Error: WRONG_SCOPE_COMMENT (line: 18, col: 7): Comment is invalid in this scope | ||
Error: SPACE_EMPTY_LINE (line: 19, col: 7): Space on empty line | ||
Error: WRONG_SCOPE_COMMENT (line: 19, col: 7): Comment is invalid in this scope | ||
Error: TOO_FEW_TAB (line: 20, col: 1): Missing tabs for indent level | ||
Error: SPACE_EMPTY_LINE (line: 20, col: 4): Space on empty line |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters