I’ve been trying to make a little programming language but I can’t figure out how to make my interpreter store and recall variables
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VARIABLES 10
// Structure to store variables
struct Variable {
char name[50];
char value[256];
};
// Array to store variables
struct Variable variables[MAX_VARIABLES];
int variableCount = 0;
// Function to find a variable by name
struct Variable *findVariable(const char *name) {
for (int i = 0; i < variableCount; ++i) {
if (strcmp(variables[i].name, name) == 0) {
return &variables[i];
}
}
return NULL; // Variable not found
}
// Function to interpret commands
void interpretCommand(const char *command) {
if (strncmp(command, "console:write->", 15) == 0) {
// Extract the message within double quotes
const char *messageStart = strchr(command, '"');
const char *messageEnd = strrchr(command, '"');
if (messageStart != NULL && messageEnd != NULL && messageStart < messageEnd) {
// Print the message, replacing variables if present
for (const char *p = messageStart + 1; p < messageEnd; ++p) {
if (*p == '*') {
++p; // Move past '*'
const char *varStart = p;
while (*p != '*' && p < messageEnd) {
++p;
}
char varName[50];
strncpy(varName, varStart, p - varStart);
varName[p - varStart] = '\0';
struct Variable *variable = findVariable(varName);
if (variable != NULL) {
printf("%s", variable->value);
} else {
printf("Undefined variable: %s", varName);
}
} else {
putchar(*p);
}
}
putchar('\n');
} else {
printf("Invalid message format\n");
}
} else if (strncmp(command, "console:read->", 14) == 0) {
// Extract the prompt within double quotes
const char *promptStart = strchr(command, '"');
const char *promptEnd = strrchr(command, '"');
if (promptStart != NULL && promptEnd != NULL && promptStart < promptEnd) {
// Print the prompt and read user input
printf("%.*s", (int)(promptEnd - promptStart - 1), promptStart + 1);
// Read user input
char userInput[256]; // Adjust size as needed
fgets(userInput, sizeof(userInput), stdin);
} else {
printf("Invalid prompt format\n");
}
} else {
// Check if the command starts with "variableName->"
char *arrow = strstr(command, "->");
if (arrow != NULL) {
*arrow = '\0'; // Separate variable name and value
// Find or create a variable with the given name
struct Variable *variable = findVariable(command);
if (variable == NULL) {
if (variableCount < MAX_VARIABLES) {
strcpy(variables[variableCount].name, command);
variable = &variables[variableCount++];
} else {
printf("Maximum number of variables reached\n");
return;
}
}
// Copy the value to the variable
strcpy(variable->value, arrow + 2);
} else {
printf("Unknown command\n");
}
}
}
int main() {
// Open the file
FILE *file = fopen("King.roar", "r");
if (file == NULL) {
perror("Error opening file");
return 1;
}
char line[256]; // Assuming a maximum line length of 255 characters
// Read and interpret each line from the file
while (fgets(line, sizeof(line), file) != NULL) {
// Remove newline character if present
size_t len = strlen(line);
if (len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0';
}
// Interpret the command
interpretCommand(line);
}
// Close the file
fclose(file);
return 0;
}
And this is my sample code stored in King.roar:
console:read->"Enter your name: "->name
console:read->"Enter your age: "->age
console:write->"Hello *name*!"
console:write->"You are *age* years old!"
For some reason I only get undefined variable I don’t know if the data isn’t being stored or it’s the recall that’s not working
I tried looking up on the internet but I didn’t find anything about it. Thanks for helping !
The code to store a value into a variable seems to be
variable_name->value
But in the file you seem to use a different syntax:
console:read->"Enter your name: "->name
It seems more consistent to use
value->variable_name
and use a current value that will be set by the console methods and other syntaxes.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VARIABLES 10
// Structure to store variables
struct Variable {
char name[50];
char value[256];
};
// Array to store variables
struct Variable variables[MAX_VARIABLES];
int variableCount = 0;
// Function to find a variable by name
struct Variable *findVariable(const char *name, size_t len) {
for (int i = 0; i < variableCount; ++i) {
if (memcmp(variables[i].name, name, len) == 0
&& variables[i].name[len] == '\0') {
return &variables[i];
}
}
return NULL; // Variable not found
}
void console_write(const char *s, size_t len) {
// Print the message, replacing variables if present
for (const char *p = s, *end = s + len; p < end; p++) {
if (*p == '*' && ++p < end && *p != '*') {
const char *varName = p;
while (p < end && *p != '*') {
++p;
}
size_t nameLen = p - varName;
struct Variable *variable = findVariable(varName, nameLen);
if (variable != NULL) {
printf("%s", variable->value);
} else {
fprintf(stderr, "Undefined variable: %.*s\n", (int)nameLen, varName);
}
} else {
putchar(*p);
}
}
}
// Function to interpret commands
int interpretCommand(const char *line) {
char current_value[250];
*current_value = '\0';
for (const char *command = line; *command;) {
if (strncmp(command, "console:write->", 15) == 0) {
// Extract the message within double quotes
const char *messageStart = strchr(command, '"');
const char *messageEnd = strrchr(command, '"');
if (messageStart == NULL || messageEnd == NULL || messageStart >= messageEnd) {
fprintf(stderr, "Invalid message format\n");
return 1;
}
console_write(messageStart + 1, messageEnd - messageStart - 1);
putchar('\n');
command = messageEnd + 1;
} else
if (strncmp(command, "console:read->", 14) == 0) {
// Extract the prompt within double quotes
const char *promptStart = strchr(command, '"');
const char *promptEnd = strrchr(command, '"');
if (promptStart == NULL || promptEnd == NULL || promptStart >= promptEnd) {
fprintf(stderr, "Invalid prompt format\n");
return 1;
}
// Print the prompt and read user input
console_write(promptStart + 1, promptEnd - promptStart - 1);
// Read user input
fgets(current_value, sizeof(current_value), stdin);
size_t len = strlen(current_value);
if (len > 0 && current_value[len - 1] == '\n')
current_value[--len] = '\0';
command = promptEnd + 1;
} else
if (!strncmp(command, "->", 2)) {
// ->variableName
const char *name = command + 2;
size_t len = strlen(name);
struct Variable *variable = findVariable(name, len);
if (variable == NULL) {
if (len >= sizeof(variable->name)) {
fprintf(stderr, "Variable name too long: %.*s\n", (int)len, name);
return 1;
}
if (variableCount >= MAX_VARIABLES) {
fprintf(stderr, "Maximum number of variables reached\n");
return 1;
}
memcpy(variables[variableCount].name, name, len);
variables[variableCount].name[len] = '\0';
variable = &variables[variableCount++];
}
strcpy(variable->value, current_value);
command = name + len;
} else
if (*command == '\"') {
// string value
const char *valueStart = command;
const char *valueEnd = strrchr(command, '"');
if (valueStart >= valueEnd) {
fprintf(stderr, "Unterminated value string: %s\n", command);
return 1;
}
size_t len = valueEnd - valueStart - 1;
if (len >= sizeof(current_value)) {
fprintf(stderr, "Value string too long: %.*s\n", (int)len + 1, valueStart);
return 1;
}
memcpy(current_value, valueStart + 1, len);
current_value[len] = '\0';
command = valueEnd + 1;
} else {
char *arrow = strstr(command, "->");
if (arrow != NULL) {
size_t len = arrow - command;
struct Variable *variable = findVariable(command, len);
if (variable == NULL) {
fprintf(stderr, "Unknown variable: %.*s\n", (int)len, command);
return 1;
}
strcpy(current_value, variable->value);
} else {
fprintf(stderr, "Unknown command: %s\n", command);
}
}
}
return 0;
}
int main(int argc, char *argv[]) {
// Open the file
const char *filename = argc > 1 ? argv[1] : "King.roar";
FILE *file = fopen(filename, "r");
if (file == NULL) {
fprintf(stderr, "Error opening file %s: %s", filename, strerror(errno));
return 1;
}
char line[256]; // Assuming a maximum line length of 255 characters
// Read and interpret each line from the file
while (fgets(line, sizeof(line), file) != NULL) {
// Remove newline character if present
size_t len = strlen(line);
if (len > 0 && line[len - 1] == '\n') {
line[len - 1] = '\0';
}
// Interpret the command
if (interpretCommand(line))
break;
}
// Close the file
fclose(file);
return 0;
}