Skip to content

Commit bf82df9

Browse files
Multiline code working with arithematic and data variable assignments
1 parent f41aaa8 commit bf82df9

File tree

5 files changed

+126
-62
lines changed

5 files changed

+126
-62
lines changed

mas/lexer.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static int next_char() {
2323

2424
// Helper function to peek at next character
2525
static int peek_char() {
26-
if (current && *current) {
26+
if (current && *current != '\0') {
2727
return *current;
2828
}
2929
return EOF;
@@ -35,9 +35,16 @@ static void skip_whitespace() {
3535
while ((c = peek_char()) != EOF) {
3636
if (c == ' ' || c == '\t') {
3737
next_char();
38+
} else if (c == '\r') {
39+
// Skip \r (in case of \r\n or lone \r)
40+
next_char();
41+
// If followed by \n, we'll let lexer_next() handle the \n
3842
} else if (c == '#') {
39-
// Comment
40-
while ((c = next_char()) != EOF && c != '\n');
43+
next_char(); // consume '#'
44+
while ((c = peek_char()) != EOF && c != '\n' && c != '\r') {
45+
next_char();
46+
}
47+
// Do NOT consume \n or \r — leave for lexer_next()
4148
} else {
4249
break;
4350
}
@@ -172,11 +179,6 @@ Token* lexer_next() {
172179
skip_whitespace();
173180

174181
int c = peek_char();
175-
if (c == EOF) {
176-
eof_reached = true;
177-
return make_token(TOK_EOF, NULL, line);
178-
}
179-
180182
// Single character tokens
181183
if (c == '+') { next_char(); return make_token(TOK_PLUS, NULL, line); }
182184
if (c == '-') { next_char(); return make_token(TOK_MINUS, NULL, line); }
@@ -225,7 +227,8 @@ Token* lexer_next() {
225227
}
226228
if (c == '\n') {
227229
next_char();
228-
return make_token(TOK_NEWLINE, NULL, line);
230+
// The newline token belongs to the line we just finished.
231+
return make_token(TOK_NEWLINE, NULL, line - 1);
229232
}
230233

231234
// Multi-character tokens
@@ -239,9 +242,18 @@ Token* lexer_next() {
239242
return read_string();
240243
}
241244

245+
if (c == EOF) {
246+
eof_reached = true;
247+
return make_token(TOK_EOF, NULL, line);
248+
}
249+
242250
// Unknown character
243251
char msg[100];
244-
sprintf(msg, "Unknown character: %c", c);
252+
if (isprint(c)) {
253+
sprintf(msg, "Unknown character: '%c'", c);
254+
} else {
255+
sprintf(msg, "Unknown character: '\\x%02X'", (unsigned char)c);
256+
}
245257
next_char(); // consume it
246258
return make_token(TOK_ERROR, strdup(msg), line);
247259
}

mas/main.c

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,68 @@
11
// main.c
22
#include "mas.h"
3+
#include <stdio.h>
34

45
int main(int argc, char* argv[]) {
56
if (argc != 2) {
67
fprintf(stderr, "Usage: %s <input.mas>\n", argv[0]);
78
return 1;
89
}
910

10-
FILE* f = fopen(argv[1], "r");
11+
FILE* f = fopen(argv[1], "rb");
1112
if (!f) {
1213
perror("Failed to open file");
1314
return 1;
1415
}
1516

1617
lexer_init(f);
1718

19+
20+
21+
// Token* tok;
22+
// do {
23+
// tok = lexer_next();
24+
// switch (tok->type) {
25+
// case TOK_EOF:
26+
// printf("EOF\n");
27+
// break;
28+
// case TOK_ERROR:
29+
// printf("ERROR (line %d): %s\n", tok->line, tok->value);
30+
// break;
31+
// case TOK_NUMBER:
32+
// printf("NUMBER (line %d): %s\n", tok->line, tok->value);
33+
// break;
34+
// case TOK_STRING:
35+
// printf("STRING (line %d): \"%s\"\n", tok->line, tok->value);
36+
// break;
37+
// case TOK_ID:
38+
// printf("IDENTIFIER (line %d): %s\n", tok->line, tok->value);
39+
// break;
40+
// case TOK_NEWLINE:
41+
// printf("NEWLINE (line %d)\n", tok->line);
42+
// break;
43+
// case TOK_PLUS: printf("PLUS (line %d)\n", tok->line); break;
44+
// case TOK_ASSIGN: printf("ASSIGN '=' (line %d)\n", tok->line); break;
45+
// case TOK_EQ: printf("EQ '==' (line %d)\n", tok->line); break;
46+
// // ... add more as needed, or use a helper function ...
47+
// default:
48+
// // For brevity, just print type and value
49+
// printf("TOKEN %d (line %d): %s\n", tok->type, tok->line, tok->value ? tok->value : "");
50+
// break;
51+
// }
52+
53+
// TokenType type = tok->type;
54+
55+
// // Clean up
56+
// if (tok->value) free(tok->value);
57+
// free(tok);
58+
59+
// if (type == TOK_EOF) break;
60+
// }while(1);
61+
1862
ASTNode* ast = parse_program();
1963
fclose(f);
2064

21-
// print_ast(ast, 0); // Print the AST
22-
MASObject* result = interpret(ast);
65+
MASObject* result = interpret(ast);
2366
mas_object_decref(result);
2467

2568
return 0;

mas/mas.exe

87 Bytes
Binary file not shown.

mas/parser.c

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ ASTNode* parse_program() {
5454
continue;
5555
}
5656
statements[stmt_count++] = parse_statement();
57+
58+
// After a statement, we must have a newline or EOF.
59+
if (current_token->type != TOK_NEWLINE && current_token->type != TOK_EOF) {
60+
consume(TOK_NEWLINE, "Expected newline after statement");
61+
}
5762
}
5863

5964
program->data.list.items = statements;
@@ -238,52 +243,15 @@ ASTNode* parse_statement() {
238243
stmt->line = call->line;
239244
stmt->data.expr = call;
240245
return stmt;
246+
} else {
247+
// If it's not a keyword-led statement, it must be an expression statement.
248+
ASTNode* expr = parse_expression();
249+
ASTNode* stmt = malloc(sizeof(ASTNode));
250+
stmt->type = AST_EXPRSTMT;
251+
stmt->line = expr->line;
252+
stmt->data.expr = expr;
253+
return stmt;
241254
}
242-
else if (match(TOK_ID)) {
243-
char* id = strdup(current_token->value);
244-
advance();
245-
if (match(TOK_ASSIGN)) { // Assignment
246-
// Assignment
247-
ASTNode* value = parse_expression();
248-
ASTNode* assign = malloc(sizeof(ASTNode));
249-
assign->type = AST_ASSIGN;
250-
assign->line = current_token->line;
251-
assign->data.assign.name = id;
252-
assign->data.assign.value = value;
253-
return assign;
254-
}
255-
else if (match(TOK_LPAREN)) { // Function call
256-
// Function call
257-
ASTNode** args = malloc(sizeof(ASTNode*) * 10);
258-
int arg_count = 0;
259-
260-
if (!match(TOK_RPAREN)) {
261-
do {
262-
args[arg_count++] = parse_expression();
263-
if (match(TOK_COMMA)) {
264-
advance(); // consume comma
265-
} else break;
266-
} while (true);
267-
consume(TOK_RPAREN, "Expected ')'");
268-
}
269-
270-
ASTNode* call = malloc(sizeof(ASTNode));
271-
call->type = AST_CALL;
272-
call->line = current_token->line;
273-
call->data.call.name = id;
274-
call->data.call.args = args;
275-
call->data.call.arg_count = arg_count;
276-
return call;
277-
}
278-
}
279-
280-
// Default: parse as expression statement
281-
ASTNode* expr = parse_expression();
282-
ASTNode* stmt = malloc(sizeof(ASTNode));
283-
stmt->type = AST_EXPRSTMT;
284-
stmt->line = current_token->line;
285-
stmt->data.expr = expr;
286-
return stmt;
287255
}
288256

289257
// Parse expression (simplified - left associative)
@@ -292,7 +260,23 @@ ASTNode* parse_expression() {
292260
}
293261

294262
ASTNode* parse_comparison() {
295-
ASTNode* expr = parse_term();
263+
ASTNode* expr = parse_term(); // Parse the left-hand side
264+
265+
// Check for assignment, which has the lowest precedence
266+
if (match(TOK_ASSIGN)) {
267+
advance(); // consume '='
268+
if (expr->type != AST_VAR) {
269+
fprintf(stderr, "Parse error at line %d: Invalid assignment target.\n", expr->line);
270+
exit(1);
271+
}
272+
ASTNode* value = parse_expression();
273+
ASTNode* assign = malloc(sizeof(ASTNode));
274+
assign->type = AST_ASSIGN;
275+
assign->line = expr->line;
276+
assign->data.assign.name = expr->data.var_name;
277+
assign->data.assign.value = value;
278+
return assign;
279+
}
296280

297281
while (current_token) {
298282
if (match(TOK_EQ)) {
@@ -498,13 +482,36 @@ ASTNode* parse_primary() {
498482
return null_node;
499483
}
500484
else if (match(TOK_ID)) {
501-
char* value = strdup(current_token->value);
485+
char* id_name = strdup(current_token->value);
502486
int line = current_token->line;
503487
advance();
488+
489+
// Check if it's a function call
490+
if (match(TOK_LPAREN)) {
491+
advance(); // consume '('
492+
ASTNode** args = malloc(sizeof(ASTNode*) * 10);
493+
int arg_count = 0;
494+
if (!match(TOK_RPAREN)) {
495+
do {
496+
args[arg_count++] = parse_expression();
497+
} while (match(TOK_COMMA) && (advance(), true));
498+
}
499+
consume(TOK_RPAREN, "Expected ')'");
500+
501+
ASTNode* call = malloc(sizeof(ASTNode));
502+
call->type = AST_CALL;
503+
call->line = line;
504+
call->data.call.name = id_name;
505+
call->data.call.args = args;
506+
call->data.call.arg_count = arg_count;
507+
return call;
508+
}
509+
510+
// Otherwise, it's a variable
504511
ASTNode* var = malloc(sizeof(ASTNode));
505512
var->type = AST_VAR;
506513
var->line = line;
507-
var->data.var_name = value;
514+
var->data.var_name = id_name;
508515
return var;
509516
}
510517
else if (match(TOK_LBRACKET)) {

mas/test.mas

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
print "Idiots in the house"
1+
x = 4 - 5
2+
print "Sum is equal to ", x
3+
print "Sagnik is idiot"

0 commit comments

Comments
 (0)