Created
February 27, 2025 04:46
-
-
Save ehzawad/9992a4cd6c06692981007089db121605 to your computer and use it in GitHub Desktop.
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
#include <stdio.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#define MAX_FUNCS 10 // Maximum number of functions supported | |
#define NAME_LEN 50 // Maximum length of function names | |
#define STR_LEN 100 // Maximum length of strings to print | |
// Structure to store function definitions | |
struct Function { | |
char name[NAME_LEN]; // Function name | |
char print_string[STR_LEN]; // String to print when called | |
}; | |
// Array to hold defined functions | |
struct Function functions[MAX_FUNCS]; | |
int func_count = 0; // Number of functions defined | |
int main() { | |
char line[256]; // Buffer for reading input lines | |
// Read lines from standard input until EOF | |
while (fgets(line, sizeof(line), stdin)) { | |
// Remove trailing newline | |
line[strcspn(line, "\n")] = 0; | |
// Check for function definition | |
if (strncmp(line, "def ", 4) == 0) { | |
// Extract function name from "def name():" | |
char *name_start = line + 4; // Skip "def " | |
char *paren = strchr(name_start, '('); | |
if (paren) { | |
int name_len = paren - name_start; | |
char name[NAME_LEN]; | |
strncpy(name, name_start, name_len); | |
name[name_len] = '\0'; // Null-terminate | |
// Read the next line (function body) | |
if (fgets(line, sizeof(line), stdin)) { | |
line[strcspn(line, "\n")] = 0; | |
// Check for indented print statement (exactly 4 spaces) | |
if (strncmp(line, " print(\"", 11) == 0) { | |
char *quote_start = line + 11; // Skip " print(\"" | |
char *quote_end = strstr(quote_start, "\")"); | |
if (quote_end) { | |
int str_len = quote_end - quote_start; | |
char print_string[STR_LEN]; | |
strncpy(print_string, quote_start, str_len); | |
print_string[str_len] = '\0'; // Null-terminate | |
// Store the function | |
strcpy(functions[func_count].name, name); | |
strcpy(functions[func_count].print_string, print_string); | |
func_count++; | |
} | |
} | |
} | |
} | |
} | |
// Check for top-level print statement | |
else if (strncmp(line, "print(\"", 7) == 0) { | |
char *quote_start = line + 7; // Skip "print(\"" | |
char *quote_end = strstr(quote_start, "\")"); | |
if (quote_end) { | |
int str_len = quote_end - quote_start; | |
char print_string[STR_LEN]; | |
strncpy(print_string, quote_start, str_len); | |
print_string[str_len] = '\0'; // Null-terminate | |
printf("%s\n", print_string); // Execute immediately | |
} | |
} | |
// Check for non-indented line (could be a function call or arithmetic expression) | |
else if (line[0] != ' ' && line[0] != '\0') { | |
int a, b; | |
// Try to parse an arithmetic expression of the form "number + number" | |
// The extra %c is used to ensure no trailing characters exist. | |
if (sscanf(line, "%d + %d %*c", &a, &b) == 2) { | |
printf("%d\n", a + b); | |
} | |
else if (sscanf(line, "%d - %d %*c", &a, &b) == 2) { | |
printf("%d\n", a - b); | |
} else { | |
// If not an arithmetic expression, treat it as a function call. | |
char *paren = strchr(line, '('); | |
if (paren) { | |
int name_len = paren - line; | |
char call_name[NAME_LEN]; | |
strncpy(call_name, line, name_len); | |
call_name[name_len] = '\0'; // Null-terminate | |
// Find and execute the function if it exists | |
for (int i = 0; i < func_count; i++) { | |
if (strcmp(functions[i].name, call_name) == 0) { | |
printf("%s\n", functions[i].print_string); | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MAX_LINE 256
#define MAX_STATEMENT 2048
#define MAX_VARS 100
#define MAX_FUNCS 50
#define NAME_LEN 50
#define STR_LEN 100
#define FUNC_BODY_LEN 256
// Value type to support integers (arithmetic) and strings (print literals)
typedef enum {
VAL_INT,
VAL_STRING
} ValueType;
typedef struct {
ValueType type;
int intValue;
char stringValue[STR_LEN];
} Value;
// Variable environment (name-value pairs)
typedef struct {
char name[NAME_LEN];
Value value;
} Variable;
Variable variables[MAX_VARS];
int var_count = 0;
// Function definitions (store function name and its single-statement body)
typedef struct {
char name[NAME_LEN];
char body[FUNC_BODY_LEN]; // for simplicity, the body is a single statement
} FunctionDef;
FunctionDef functions[MAX_FUNCS];
int func_count = 0;
// Forward declaration for lookup_variable to resolve implicit declaration warning.
int lookup_variable(const char *name, Value *result);
// --- Expression Parser (Recursive Descent) ---
const char* skip_whitespace(const char *s);
int parse_expression(const char **s);
int parse_term(const char **s);
int parse_factor(const char **s);
const char* skip_whitespace(const char *s) {
while (*s && isspace(*s)) s++;
return s;
}
// parse_expression: handles addition and subtraction
int parse_expression(const char **s) {
int value = parse_term(s);
*s = skip_whitespace(*s);
while (**s == '+' || **s == '-') {
char op = **s;
(*s)++;
int rhs = parse_term(s);
if (op == '+')
value += rhs;
else
value -= rhs;
*s = skip_whitespace(*s);
}
return value;
}
// parse_term: handles multiplication and division
int parse_term(const char **s) {
int value = parse_factor(s);
*s = skip_whitespace(s);
while (**s == '' || **s == '/') {
char op = **s;
(s)++;
int rhs = parse_factor(s);
if (op == '')
value *= rhs;
else {
if (rhs == 0) {
printf("Error: Division by zero.\n");
return 0;
}
value /= rhs;
}
*s = skip_whitespace(*s);
}
return value;
}
// parse_factor: handles numbers, variables, parentheses, and unary minus.
int parse_factor(const char **s) {
*s = skip_whitespace(*s);
int sign = 1;
if (**s == '-') {
sign = -1;
(*s)++;
}
int value = 0;
if (isdigit(**s)) {
value = strtol(*s, (char **)s, 10);
} else if (isalpha(**s)) {
char ident[NAME_LEN];
int i = 0;
while ((isalnum(**s) || **s == '_') && i < NAME_LEN - 1) {
ident[i++] = **s;
(*s)++;
}
ident[i] = '\0';
Value varValue;
if (lookup_variable(ident, &varValue) && varValue.type == VAL_INT)
value = varValue.intValue;
else
printf("Undefined variable or non-integer: %s\n", ident);
} else if (**s == '(') {
(*s)++; // skip '('
value = parse_expression(s);
if (**s == ')')
(*s)++;
else
printf("Expected ')'\n");
}
return sign * value;
}
// Evaluate an arithmetic expression from a string.
int evaluate_arithmetic(const char *expr) {
const char *p = expr;
int result = parse_expression(&p);
return result;
}
// --- Variable and Function Environment Management ---
// Lookup a variable by name; returns 1 if found, and sets result.
int lookup_variable(const char *name, Value *result) {
for (int i = 0; i < var_count; i++) {
if (strcmp(variables[i].name, name) == 0) {
*result = variables[i].value;
return 1;
}
}
return 0;
}
// Set a variable (update if exists, otherwise add).
void set_variable(const char *name, Value value) {
for (int i = 0; i < var_count; i++) {
if (strcmp(variables[i].name, name) == 0) {
variables[i].value = value;
return;
}
}
if (var_count < MAX_VARS) {
strncpy(variables[var_count].name, name, NAME_LEN);
variables[var_count].value = value;
var_count++;
} else {
printf("Error: Variable table full!\n");
}
}
// --- Multi-line Statement Support ---
// Check if the accumulated statement is complete (balanced parentheses and closed quotes).
int is_statement_complete(const char *stmt) {
int paren_count = 0;
int in_quote = 0;
for (int i = 0; stmt[i] != '\0'; i++) {
char c = stmt[i];
if (c == '"') {
in_quote = !in_quote;
} else if (!in_quote) {
if (c == '(')
paren_count++;
else if (c == ')')
paren_count--;
}
}
return (paren_count == 0 && !in_quote);
}
// --- Interpreter Execution ---
// Forward declaration for executing a single statement.
void execute_line(char *line);
// Execute a function call by name.
void execute_function(const char *name) {
for (int i = 0; i < func_count; i++) {
if (strcmp(functions[i].name, name) == 0) {
// For simplicity, a function's body is a single statement.
execute_line(functions[i].body);
return;
}
}
printf("Undefined function: %s\n", name);
}
// Execute a single statement.
void execute_line(char *line) {
// Remove trailing newline.
line[strcspn(line, "\n")] = 0;
char *p = line;
p = (char *)skip_whitespace(p);
if (*p == '\0') return;
}
// --- Main REPL Loop with Multi-line Support ---
int main() {
char line[MAX_LINE];
char statement[MAX_STATEMENT] = "";
printf("Welcome to MiniPy Interpreter.\n");
printf("Type commands (arithmetic, assignment, print, function def/call).\n");
printf("Press Ctrl+D to exit.\n\n");
}