I’m stuck on Stage #TZ7.
I’ve tried .. :
IDK what even to try. I have no idea what to do now.
The story is,
In the third test, we have the following contents in the test file:
() #<|TAB|>{}
@
$
+++
// Let’s Go!
+++
so when my Scanner()
function consumes the ‘/’, it sees weather the next charecter is also ‘/’. If so, it will consider the whole line as a comment. Now it will call the skip_to_next_line()
function.
That function will skip until the ‘\n’ charecter. Since my scanner will need to detect the ‘\n’ so that it can update the line counter, I have kept the skip_to_next_line()
function like that.
But then since I did not design the skip_to_next_line()
properly, I would skip the ‘\n’ and the line counter would count the lines incorrectly.
The wrong code is here:
int skip_to_next_line(int file_iterator,char* file_contents)
{
//file_iterator points to the current charecter scanned by scanner()
//file_contents will contain the actual data from the file that we are scaning.
//thus we get the current element by file_contents[file_iterator]
while(file_contents[file_iterator] != '\n' && file_contents[file_iterator] != '\0');
{
file_iterator += 1;
}
//file_iterator += 1;
return file_iterator;
}
here the file_iterator will point to the charecter in the line next to the comment, skipping the ‘\n’. Thus I was unable to pass the 3rd test.
Now, I have changed the code. Nothing big. Just the return statement.
From this:
return file_iterator
to:
return file_iterator - 1;
Now I am struck here. The program is being timed out. What abomination have I unleashed?!?
I dont know if explaining my code flow will be usefull, but I am doing it.
→ The program starts with main()
where the read_file_contents()
is called first.
→ read_file_contents()
will read the file contents, return the contents as a array named as file_contents
. Until now , the functions I have mentioned are written in default, not by me
→ Now I call the Scanner()
from the main. This is where my code starts. Scanner will iterate through the file_contents
array, identify elements then do whatever is supposed to be done.
→ if a comment is identified, skip_to_next_line()
function is called.
Here are my logs:
remote: [tester::#TZ7] Running tests for Stage #TZ7 (Scanning: Multi-line errors)
remote: [tester::#TZ7] [test-1] Running test case: 1
remote: [tester::#TZ7] [test-1] Writing contents to ./test.lox:
remote: [tester::#TZ7] [test-1.lox] ()<|SPACE|><|TAB|>@
remote: [tester::#TZ7] [test-1] $ ./your_program.sh tokenize test.lox
remote: [your_program] LEFT_PAREN ( null
remote: [your_program] RIGHT_PAREN ) null
remote: [your_program] Logs from your program will appear here!
remote: [your_program] EOF null
remote: [your_program] [line 2] Error: Unexpected character: @
remote: [your_program] return_value : 65
remote: [tester::#TZ7] [test-1] ✓ 1 line(s) match on stderr
remote: [tester::#TZ7] [test-1] ✓ 3 line(s) match on stdout
remote: [tester::#TZ7] [test-1] ✓ Received exit code 65.
remote: [tester::#TZ7] [test-2] Running test case: 2
remote: [tester::#TZ7] [test-2] Writing contents to ./test.lox:
remote: [tester::#TZ7] [test-2.lox]
remote: [tester::#TZ7] [test-2.lox] <|TAB|> @
remote: [tester::#TZ7] [test-2] $ ./your_program.sh tokenize test.lox
remote: [your_program] Logs from your program will appear here!
remote: [your_program] [line 2] Error: Unexpected character: @
remote: [your_program] return_value : 65
remote: [your_program] EOF null
remote: [tester::#TZ7] [test-2] ✓ 1 line(s) match on stderr
remote: [tester::#TZ7] [test-2] ✓ 1 line(s) match on stdout
remote: [tester::#TZ7] [test-2] ✓ Received exit code 65.
remote: [tester::#TZ7] [test-3] Running test case: 3
remote: [tester::#TZ7] [test-3] Writing contents to ./test.lox:
remote: [tester::#TZ7] [test-3.lox] () #<|TAB|>{}
remote: [tester::#TZ7] [test-3.lox] @
remote: [tester::#TZ7] [test-3.lox] $
remote: [tester::#TZ7] [test-3.lox] +++
remote: [tester::#TZ7] [test-3.lox] // Let's Go!
remote: [tester::#TZ7] [test-3.lox] +++
remote: [tester::#TZ7] [test-3.lox] #
remote: [tester::#TZ7] [test-3] $ ./your_program.sh tokenize test.lox
remote: [your_program] Logs from your program will appear here!
remote: [your_program] LEFT_PAREN ( null
remote: [your_program] RIGHT_PAREN ) null
remote: [your_program] LEFT_BRACE { null
remote: [your_program] RIGHT_BRACE } null
remote: [your_program] PLUS + null
remote: [your_program] PLUS + null
remote: [your_program] PLUS + null
remote: [your_program] [line 1] Error: Unexpected character: #
remote: [your_program] [line 2] Error: Unexpected character: @
remote: [your_program] [line 3] Error: Unexpected character: $
remote: [tester::#TZ7] [test-3] timed out, test exceeded 10 seconds
remote: [tester::#TZ7] [test-3] Test failed
And here’s a snippet of my code:
As I do not know which snippet would have caused this, I am giving the whole code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//global variables
long GLOBAL_file_size;
int GLOBAL_error_flag;
char *read_file_contents(const char *filename);
int Scanner(char *file_contents);
int skip_to_next_line(int file_iterator,char* file_contents);
int main(int argc, char *argv[]) {
// Disable output buffering
setbuf(stdout, NULL);
setbuf(stderr, NULL);
if (argc < 3) {
fprintf(stderr, "Usage: ./your_program tokenize <filename>\n");
return 1;
}
const char *command = argv[1];
int return_value = 0;
if (strcmp(command, "tokenize") == 0) {
// You can use print statements as follows for debugging, they'll be visible when running tests.
fprintf(stderr, "Logs from your program will appear here!\n");
char *file_contents = read_file_contents(argv[2]);
//testing(file_contents);
if(strlen(file_contents) > 0)
{
int result = Scanner(file_contents);
return_value = result;
}
printf("EOF null\n");
free(file_contents);
} else {
fprintf(stderr, "Unknown command: %s\n", command);
return 1;
}
fprintf(stderr,"return_value : %d\n",return_value);
return return_value;
}
char *read_file_contents(const char *filename) {
FILE *file = fopen(filename, "r");
//fprintf(stderr,"filename : %s\n",filename);
if (file == NULL) {
fprintf(stderr, "Error reading file: %s\n", filename);
return NULL;
}
fseek(file, 0, SEEK_END);
long file_size = ftell(file);
GLOBAL_file_size = file_size;
rewind(file);
char *file_contents = malloc(file_size + 1);
if (file_contents == NULL) {
fprintf(stderr, "Memory allocation failed\n");
fclose(file);
return NULL;
}
size_t bytes_read = fread(file_contents, 1, file_size, file);
if (bytes_read < file_size) {
fprintf(stderr, "Error reading file contents\n");
free(file_contents);
fclose(file);
return NULL;
}
file_contents[file_size] = '\0';
fclose(file);
return file_contents;
}
int Scanner(char *file_contents)
{
int file_iterator = 0; //iterate through the file_content array
int line_number = 1; //current line context. Used to report warnings and errors. For now 1
int returnable_value = 0; //0 if all right, 65 if something is wrong
int comment_flag = 0; //if set true, skips line. For now, this will skip the entire file.
while(file_contents[file_iterator] != '\0')
{
switch(file_contents[file_iterator])
{
//block and line defines
case '(' :
{
printf("LEFT_PAREN ( null\n");
break;
}
case ')' :
{
printf("RIGHT_PAREN ) null\n");
break;
}
case '{' :
{
printf("LEFT_BRACE { null\n");
break;
}
case '}' :
{
printf("RIGHT_BRACE } null\n");
break;
}
case ';' :
{
printf("SEMICOLON ; null\n");
break;
}
//whatever charecters
case '.' :
{
printf("DOT . null\n");
break;
}
case '*' :
{
printf("STAR * null\n");
break;
}
case ',' :
{
printf("COMMA , null\n");
break;
}
//operators
case '+' :
{
printf("PLUS + null\n");
break;
}
case '-' :
{
printf("MINUS - null\n");
break;
}
case '/' :
{
if(file_contents[file_iterator + 1] == '/' )
{
comment_flag = 1;
file_iterator = skip_to_next_line(file_iterator,file_contents); //skip until just before '\n'
//break;
}
else
{
printf("SLASH / null\n");
}
break;
}
case '=' :
{
if(file_contents[file_iterator + 1] == '=')
{
printf("EQUAL_EQUAL == null\n");
file_iterator += 1;
}
else
{
printf("EQUAL = null\n");
}
break;
}
case '!' :
{
if(file_contents[file_iterator + 1] == '=')
{
printf("BANG_EQUAL != null\n");
file_iterator += 1;
}
else
{
printf("BANG ! null\n");
}
break;
}
case '<' :
{
if(file_contents[file_iterator + 1] == '=')
{
printf("LESS_EQUAL <= null\n");
file_iterator += 1;
}
else
{
printf("LESS < null\n");
}
break;
}
case '>' :
{
if(file_contents[file_iterator + 1] == '=')
{
printf("GREATER_EQUAL >= null\n");
file_iterator += 1;
}
else
{
printf("GREATER > null\n");
}
break;
}
//ignoring
case ' ' :
{
break;
}
case '\t' :
{
break;
}
case '\n' :
{
line_number += 1;
break;
}
//error bitching
default :
{
//for error reporting
fprintf(stderr,"[line %d] Error: Unexpected character: %c\n",line_number,file_contents[file_iterator]);
returnable_value = 65;
}
}
file_iterator += 1;
}
return returnable_value;
}
int skip_to_next_line(int file_iterator,char* file_contents)
{
//file_iterator points to the current charecter scanned by scanner()
//file_contents will contain the actual data from the file that we are scaning.
//thus we get the current element by file_contents[file_iterator]
while(file_contents[file_iterator] != '\n' && file_contents[file_iterator] != '\0');
{
file_iterator += 1;
}
//file_iterator += 1;
return file_iterator - 1;
}
Thank you.
Have a good day