-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 7c37fa1
Showing
13 changed files
with
440 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
CC = gcc | ||
CFLAGS = -Wall -Wextra -std=c99 | ||
SRCS = src/main.c src/lexer.c src/parser.c src/interpreter.c | ||
OBJS = $(SRCS:.c=.o) | ||
EXEC = uzbeklang | ||
|
||
all: $(EXEC) | ||
|
||
$(EXEC): $(OBJS) | ||
$(CC) $(CFLAGS) -o $(EXEC) $(OBJS) | ||
|
||
clean: | ||
rm -f $(OBJS) $(EXEC) | ||
|
||
.PHONY: all clean |
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,3 @@ | ||
Yoz "Mening ismim" | ||
Yoz 14 | ||
Qosh 14 53; |
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,38 @@ | ||
#include <stdio.h> | ||
#include "interpreter.h" | ||
|
||
void interpret(ASTNode *node) { | ||
if (!node) return; | ||
|
||
switch (node->type) { | ||
case AST_PRINT: | ||
interpret(node->left); | ||
break; | ||
case AST_ADD: { | ||
ASTNode *left = node->left; | ||
ASTNode *right = node->right; | ||
if (left->type == AST_NUMBER && right->type == AST_NUMBER) { | ||
int result = atoi(left->value) + atoi(right->value); | ||
printf("%d\n", result); | ||
} | ||
break; | ||
} | ||
case AST_SUB: { | ||
ASTNode *left = node->left; | ||
ASTNode *right = node->right; | ||
if (left->type == AST_NUMBER && right->type == AST_NUMBER) { | ||
int result = atoi(left->value) - atoi(right->value); | ||
printf("%d\n", result); | ||
} | ||
break; | ||
} | ||
case AST_NUMBER: | ||
printf("%s\n", node->value); | ||
break; | ||
case AST_STRING: | ||
printf("%s\n", node->value); | ||
break; | ||
default: | ||
break; | ||
} | ||
} |
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,8 @@ | ||
#ifndef INTERPRETER_H | ||
#define INTERPRETER_H | ||
|
||
#include "parser.h" | ||
|
||
void interpret(ASTNode *node); | ||
|
||
#endif |
Binary file not shown.
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,118 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <ctype.h> | ||
#include <string.h> | ||
#include "lexer.h" | ||
|
||
Lexer *init_lexer(char *source) { | ||
Lexer *lexer = (Lexer *)malloc(sizeof(Lexer)); | ||
lexer->source = source; | ||
lexer->length = strlen(source); | ||
lexer->pos = 0; | ||
return lexer; | ||
} | ||
|
||
void free_lexer(Lexer *lexer) { | ||
free(lexer); | ||
} | ||
|
||
Token *create_token(TokenType type, char *value) { | ||
Token *token = (Token *)malloc(sizeof(Token)); | ||
token->type = type; | ||
token->value = value; | ||
return token; | ||
} | ||
|
||
void free_token(Token *token) { | ||
if (token->value) free(token->value); | ||
free(token); | ||
} | ||
|
||
char peek(Lexer *lexer) { | ||
if (lexer->pos < lexer->length) { | ||
return lexer->source[lexer->pos]; | ||
} | ||
return '\0'; | ||
} | ||
|
||
char advance(Lexer *lexer) { | ||
lexer->pos++; | ||
return peek(lexer); | ||
} | ||
|
||
void skip_whitespace(Lexer *lexer) { | ||
while (isspace(peek(lexer))) { | ||
advance(lexer); | ||
} | ||
} | ||
|
||
Token *get_next_token(Lexer *lexer) { | ||
skip_whitespace(lexer); | ||
|
||
char current = peek(lexer); | ||
|
||
if (current == '\0') { | ||
return create_token(TOKEN_EOF, NULL); | ||
} | ||
|
||
if (isalpha(current)) { | ||
size_t start = lexer->pos; | ||
while (isalpha(peek(lexer))) advance(lexer); | ||
|
||
size_t length = lexer->pos - start; | ||
char *value = (char *)malloc(length + 1); | ||
strncpy(value, lexer->source + start, length); | ||
value[length] = '\0'; | ||
|
||
if (strcmp(value, "Yoz") == 0) return create_token(TOKEN_PRINT, value); | ||
if (strcmp(value, "Qosh") == 0) return create_token(TOKEN_ADD, value); | ||
if (strcmp(value, "Ayir") == 0) return create_token(TOKEN_SUB, value); | ||
|
||
return create_token(TOKEN_ID, value); | ||
} | ||
|
||
if (isdigit(current)) { | ||
size_t start = lexer->pos; | ||
while (isdigit(peek(lexer))) advance(lexer); | ||
|
||
size_t length = lexer->pos - start; | ||
char *value = (char *)malloc(length + 1); | ||
strncpy(value, lexer->source + start, length); | ||
value[length] = '\0'; | ||
|
||
return create_token(TOKEN_NUMBER, value); | ||
} | ||
|
||
if (current == '\"') { | ||
advance(lexer); // Skip the opening quote | ||
size_t start = lexer->pos; | ||
|
||
while (peek(lexer) != '\"' && peek(lexer) != '\0') advance(lexer); | ||
|
||
size_t length = lexer->pos - start; | ||
char *value = (char *)malloc(length + 1); | ||
strncpy(value, lexer->source + start, length); | ||
value[length] = '\0'; | ||
|
||
advance(lexer); // Skip the closing quote | ||
|
||
return create_token(TOKEN_STRING, value); | ||
} | ||
|
||
if (current == '(') { | ||
advance(lexer); | ||
return create_token(TOKEN_LPAREN, strdup("(")); | ||
} | ||
|
||
if (current == ')') { | ||
advance(lexer); | ||
return create_token(TOKEN_RPAREN, strdup(")")); | ||
} | ||
|
||
if (current == ';') { | ||
advance(lexer); | ||
return create_token(TOKEN_SEMICOLON, strdup(";")); | ||
} | ||
|
||
return create_token(TOKEN_ERROR, NULL); | ||
} |
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,34 @@ | ||
#ifndef LEXER_H | ||
#define LEXER_H | ||
|
||
typedef enum { | ||
TOKEN_EOF, | ||
TOKEN_ID, | ||
TOKEN_STRING, | ||
TOKEN_NUMBER, | ||
TOKEN_PRINT, | ||
TOKEN_ADD, | ||
TOKEN_SUB, | ||
TOKEN_LPAREN, | ||
TOKEN_RPAREN, | ||
TOKEN_SEMICOLON, | ||
TOKEN_ERROR | ||
} TokenType; | ||
|
||
typedef struct { | ||
TokenType type; | ||
char *value; | ||
} Token; | ||
|
||
typedef struct { | ||
char *source; | ||
size_t length; | ||
size_t pos; | ||
} Lexer; | ||
|
||
Lexer *init_lexer(char *source); | ||
Token *get_next_token(Lexer *lexer); | ||
void free_lexer(Lexer *lexer); | ||
void free_token(Token *token); | ||
|
||
#endif |
Binary file not shown.
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,70 @@ | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include "lexer.h" | ||
#include "parser.h" | ||
#include "interpreter.h" | ||
|
||
void run_repl() { | ||
char input[256]; | ||
|
||
printf("UzbekLang dasturiga xush kelibsiz!\n"); | ||
|
||
while (1) { | ||
printf(">> "); | ||
if (!fgets(input, sizeof(input), stdin)) break; | ||
if (strncmp(input, "exit", 4) == 0) break; | ||
|
||
Lexer *lexer = init_lexer(input); | ||
Parser *parser = init_parser(lexer); | ||
ASTNode *root = parse(parser); | ||
|
||
interpret(root); | ||
|
||
free_ast(root); | ||
free_parser(parser); | ||
free_lexer(lexer); | ||
} | ||
} | ||
|
||
void run_file(const char *filename) { | ||
FILE *file = fopen(filename, "r"); | ||
if (!file) { | ||
fprintf(stderr, "Faylni ochib bo'lmadi: %s\n", filename); | ||
exit(1); | ||
} | ||
|
||
fseek(file, 0, SEEK_END); | ||
long length = ftell(file); | ||
fseek(file, 0, SEEK_SET); | ||
|
||
char *input = (char *)malloc(length + 1); | ||
if (!input) { | ||
fprintf(stderr, "Xotirani ajratib bo'lmadi\n"); | ||
exit(1); | ||
} | ||
|
||
fread(input, 1, length, file); | ||
input[length] = '\0'; | ||
fclose(file); | ||
|
||
Lexer *lexer = init_lexer(input); | ||
Parser *parser = init_parser(lexer); | ||
ASTNode *root = parse(parser); | ||
|
||
interpret(root); | ||
|
||
free_ast(root); | ||
free_parser(parser); | ||
free_lexer(lexer); | ||
free(input); | ||
} | ||
|
||
int main(int argc, char **argv) { | ||
if (argc == 2) { | ||
run_file(argv[1]); | ||
} else { | ||
run_repl(); | ||
} | ||
|
||
return 0; | ||
} |
Binary file not shown.
Oops, something went wrong.