Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- // Rozszerzone typy tokenów
- typedef enum {
- TOKEN_NUMBER,
- TOKEN_IDENTIFIER,
- TOKEN_STRING, // "tekst"
- TOKEN_ZMIEN, // zmien
- TOKEN_IF, // if
- TOKEN_ELSE, // else
- TOKEN_POKAZ, // pokaz (print)
- TOKEN_EQUALS, // =
- TOKEN_EQUALS_EQUALS, // ==
- TOKEN_NOT_EQUALS, // !=
- TOKEN_LESS, // <
- TOKEN_GREATER, // >
- TOKEN_LESS_EQUAL, // <=
- TOKEN_GREATER_EQUAL, // >=
- TOKEN_PLUS,
- TOKEN_MINUS,
- TOKEN_MULTIPLY,
- TOKEN_DIVIDE,
- TOKEN_LPAREN,
- TOKEN_RPAREN,
- TOKEN_LBRACE, // {
- TOKEN_RBRACE, // }
- TOKEN_SEMICOLON,
- TOKEN_EOF,
- TOKEN_INVALID
- } TokenType;
- // Struktura tokena
- typedef struct {
- TokenType type;
- double value;
- char* text;
- int position;
- } Token;
- // Struktura lexera
- typedef struct {
- char* source;
- int position;
- int length;
- char current_char;
- } Lexer;
- // Struktura zmiennej
- typedef struct {
- char* name;
- double value;
- } Variable;
- // Struktura środowiska
- typedef struct {
- Variable* variables;
- int count;
- int capacity;
- } Environment;
- // Struktura parsera
- typedef struct {
- Token* tokens;
- int current;
- int token_count;
- Environment* env;
- } Parser;
- // === FUNKCJE ŚRODOWISKA ===
- Environment* create_environment() {
- Environment* env = (Environment*)malloc(sizeof(Environment));
- env->variables = (Variable*)malloc(sizeof(Variable) * 10);
- env->count = 0;
- env->capacity = 10;
- return env;
- }
- void set_variable(Environment* env, char* name, double value) {
- for (int i = 0; i < env->count; i++) {
- if (strcmp(env->variables[i].name, name) == 0) {
- env->variables[i].value = value;
- return;
- }
- }
- if (env->count >= env->capacity) {
- env->capacity *= 2;
- env->variables = (Variable*)realloc(env->variables, sizeof(Variable) * env->capacity);
- }
- env->variables[env->count].name = (char*)malloc(strlen(name) + 1);
- strcpy(env->variables[env->count].name, name);
- env->variables[env->count].value = value;
- env->count++;
- }
- double get_variable(Environment* env, char* name) {
- for (int i = 0; i < env->count; i++) {
- if (strcmp(env->variables[i].name, name) == 0) {
- return env->variables[i].value;
- }
- }
- printf("Error: Variable '%s' not found\n", name);
- return 0;
- }
- int variable_exists(Environment* env, char* name) {
- for (int i = 0; i < env->count; i++) {
- if (strcmp(env->variables[i].name, name) == 0) {
- return 1;
- }
- }
- return 0;
- }
- // === FUNKCJE LEXERA (ROZSZERZONE) ===
- Lexer* create_lexer(char* source) {
- Lexer* lexer = (Lexer*)malloc(sizeof(Lexer));
- lexer->source = source;
- lexer->position = 0;
- lexer->length = strlen(source);
- lexer->current_char = lexer->position < lexer->length ? lexer->source[0] : '\0';
- return lexer;
- }
- void advance(Lexer* lexer) {
- lexer->position++;
- if (lexer->position >= lexer->length) {
- lexer->current_char = '\0';
- } else {
- lexer->current_char = lexer->source[lexer->position];
- }
- }
- void skip_whitespace(Lexer* lexer) {
- while (lexer->current_char != '\0' && isspace(lexer->current_char)) {
- advance(lexer);
- }
- }
- double read_number(Lexer* lexer) {
- char number_str[100];
- int index = 0;
- while (lexer->current_char != '\0' && isdigit(lexer->current_char)) {
- number_str[index++] = lexer->current_char;
- advance(lexer);
- }
- if (lexer->current_char == '.') {
- number_str[index++] = lexer->current_char;
- advance(lexer);
- while (lexer->current_char != '\0' && isdigit(lexer->current_char)) {
- number_str[index++] = lexer->current_char;
- advance(lexer);
- }
- }
- number_str[index] = '\0';
- return atof(number_str);
- }
- char* read_identifier(Lexer* lexer) {
- char* identifier = (char*)malloc(100);
- int index = 0;
- while (lexer->current_char != '\0' &&
- (isalnum(lexer->current_char) || lexer->current_char == '_')) {
- identifier[index++] = lexer->current_char;
- advance(lexer);
- }
- identifier[index] = '\0';
- return identifier;
- }
- char* read_string(Lexer* lexer) {
- char* string = (char*)malloc(100);
- int index = 0;
- advance(lexer); // pomiń początkowy "
- while (lexer->current_char != '\0' && lexer->current_char != '"') {
- string[index++] = lexer->current_char;
- advance(lexer);
- }
- if (lexer->current_char == '"') {
- advance(lexer); // pomiń końcowy "
- }
- string[index] = '\0';
- return string;
- }
- Token get_next_token(Lexer* lexer) {
- Token token;
- while (lexer->current_char != '\0') {
- if (isspace(lexer->current_char)) {
- skip_whitespace(lexer);
- continue;
- }
- // Liczby
- if (isdigit(lexer->current_char)) {
- token.type = TOKEN_NUMBER;
- token.value = read_number(lexer);
- token.position = lexer->position;
- token.text = NULL;
- return token;
- }
- // Stringi
- if (lexer->current_char == '"') {
- token.type = TOKEN_STRING;
- token.text = read_string(lexer);
- token.value = 0;
- token.position = lexer->position;
- return token;
- }
- // Identyfikatory i słowa kluczowe
- if (isalpha(lexer->current_char) || lexer->current_char == '_') {
- char* identifier = read_identifier(lexer);
- token.position = lexer->position;
- token.value = 0;
- // Sprawdź słowa kluczowe
- if (strcmp(identifier, "zmien") == 0) {
- token.type = TOKEN_ZMIEN;
- } else if (strcmp(identifier, "if") == 0) {
- token.type = TOKEN_IF;
- } else if (strcmp(identifier, "else") == 0) {
- token.type = TOKEN_ELSE;
- } else if (strcmp(identifier, "pokaz") == 0) {
- token.type = TOKEN_POKAZ;
- } else {
- token.type = TOKEN_IDENTIFIER;
- }
- token.text = identifier;
- return token;
- }
- // Operatory dwuznakowe
- if (lexer->current_char == '=' &&
- lexer->position + 1 < lexer->length &&
- lexer->source[lexer->position + 1] == '=') {
- token.type = TOKEN_EQUALS_EQUALS;
- token.value = 0;
- token.position = lexer->position;
- token.text = "==";
- advance(lexer);
- advance(lexer);
- return token;
- }
- if (lexer->current_char == '!' &&
- lexer->position + 1 < lexer->length &&
- lexer->source[lexer->position + 1] == '=') {
- token.type = TOKEN_NOT_EQUALS;
- token.value = 0;
- token.position = lexer->position;
- token.text = "!=";
- advance(lexer);
- advance(lexer);
- return token;
- }
- if (lexer->current_char == '<' &&
- lexer->position + 1 < lexer->length &&
- lexer->source[lexer->position + 1] == '=') {
- token.type = TOKEN_LESS_EQUAL;
- token.value = 0;
- token.position = lexer->position;
- token.text = "<=";
- advance(lexer);
- advance(lexer);
- return token;
- }
- if (lexer->current_char == '>' &&
- lexer->position + 1 < lexer->length &&
- lexer->source[lexer->position + 1] == '=') {
- token.type = TOKEN_GREATER_EQUAL;
- token.value = 0;
- token.position = lexer->position;
- token.text = ">=";
- advance(lexer);
- advance(lexer);
- return token;
- }
- // Pojedyncze znaki
- switch (lexer->current_char) {
- case '=':
- token.type = TOKEN_EQUALS;
- token.value = 0;
- token.position = lexer->position;
- token.text = "=";
- advance(lexer);
- return token;
- case '<':
- token.type = TOKEN_LESS;
- token.value = 0;
- token.position = lexer->position;
- token.text = "<";
- advance(lexer);
- return token;
- case '>':
- token.type = TOKEN_GREATER;
- token.value = 0;
- token.position = lexer->position;
- token.text = ">";
- advance(lexer);
- return token;
- case '+':
- token.type = TOKEN_PLUS;
- token.value = 0;
- token.position = lexer->position;
- token.text = "+";
- advance(lexer);
- return token;
- case '-':
- token.type = TOKEN_MINUS;
- token.value = 0;
- token.position = lexer->position;
- token.text = "-";
- advance(lexer);
- return token;
- case '*':
- token.type = TOKEN_MULTIPLY;
- token.value = 0;
- token.position = lexer->position;
- token.text = "*";
- advance(lexer);
- return token;
- case '/':
- token.type = TOKEN_DIVIDE;
- token.value = 0;
- token.position = lexer->position;
- token.text = "/";
- advance(lexer);
- return token;
- case '(':
- token.type = TOKEN_LPAREN;
- token.value = 0;
- token.position = lexer->position;
- token.text = "(";
- advance(lexer);
- return token;
- case ')':
- token.type = TOKEN_RPAREN;
- token.value = 0;
- token.position = lexer->position;
- token.text = ")";
- advance(lexer);
- return token;
- case '{':
- token.type = TOKEN_LBRACE;
- token.value = 0;
- token.position = lexer->position;
- token.text = "{";
- advance(lexer);
- return token;
- case '}':
- token.type = TOKEN_RBRACE;
- token.value = 0;
- token.position = lexer->position;
- token.text = "}";
- advance(lexer);
- return token;
- case ';':
- token.type = TOKEN_SEMICOLON;
- token.value = 0;
- token.position = lexer->position;
- token.text = ";";
- advance(lexer);
- return token;
- default:
- token.type = TOKEN_INVALID;
- token.value = 0;
- token.position = lexer->position;
- token.text = NULL;
- advance(lexer);
- return token;
- }
- }
- token.type = TOKEN_EOF;
- token.value = 0;
- token.position = lexer->position;
- token.text = "EOF";
- return token;
- }
- // === FUNKCJE PARSERA ===
- Parser* create_parser(Token* tokens, int token_count, Environment* env) {
- Parser* parser = (Parser*)malloc(sizeof(Parser));
- parser->tokens = tokens;
- parser->current = 0;
- parser->token_count = token_count;
- parser->env = env;
- return parser;
- }
- Token current_token(Parser* parser) {
- if (parser->current >= parser->token_count) {
- Token eof = {TOKEN_EOF, 0, "EOF", -1};
- return eof;
- }
- return parser->tokens[parser->current];
- }
- void next_token(Parser* parser) {
- if (parser->current < parser->token_count) {
- parser->current++;
- }
- }
- int expect_token(Parser* parser, TokenType expected) {
- Token token = current_token(parser);
- if (token.type == expected) {
- next_token(parser);
- return 1;
- }
- return 0;
- }
- // === FUNKCJE PARSOWANIA WYRAŻEŃ ===
- double parse_expression(Parser* parser);
- double parse_comparison(Parser* parser);
- double parse_factor(Parser* parser) {
- Token token = current_token(parser);
- if (token.type == TOKEN_NUMBER) {
- next_token(parser);
- return token.value;
- }
- if (token.type == TOKEN_IDENTIFIER) {
- next_token(parser);
- if (variable_exists(parser->env, token.text)) {
- return get_variable(parser->env, token.text);
- } else {
- printf("Error: Variable '%s' not defined\n", token.text);
- return 0;
- }
- }
- if (token.type == TOKEN_LPAREN) {
- next_token(parser);
- double result = parse_comparison(parser);
- expect_token(parser, TOKEN_RPAREN);
- return result;
- }
- if (token.type == TOKEN_MINUS) {
- next_token(parser);
- return -parse_factor(parser);
- }
- printf("Error: Unexpected token in expression\n");
- return 0;
- }
- double parse_term(Parser* parser) {
- double result = parse_factor(parser);
- while (1) {
- Token token = current_token(parser);
- if (token.type == TOKEN_MULTIPLY) {
- next_token(parser);
- result *= parse_factor(parser);
- } else if (token.type == TOKEN_DIVIDE) {
- next_token(parser);
- double divisor = parse_factor(parser);
- if (divisor == 0) {
- printf("Error: Division by zero!\n");
- return 0;
- }
- result /= divisor;
- } else {
- break;
- }
- }
- return result;
- }
- double parse_expression(Parser* parser) {
- double result = parse_term(parser);
- while (1) {
- Token token = current_token(parser);
- if (token.type == TOKEN_PLUS) {
- next_token(parser);
- result += parse_term(parser);
- } else if (token.type == TOKEN_MINUS) {
- next_token(parser);
- result -= parse_term(parser);
- } else {
- break;
- }
- }
- return result;
- }
- // NOWA FUNKCJA - parsowanie porównań
- double parse_comparison(Parser* parser) {
- double left = parse_expression(parser);
- Token token = current_token(parser);
- if (token.type == TOKEN_EQUALS_EQUALS) {
- next_token(parser);
- double right = parse_expression(parser);
- return (left == right) ? 1.0 : 0.0;
- } else if (token.type == TOKEN_NOT_EQUALS) {
- next_token(parser);
- double right = parse_expression(parser);
- return (left != right) ? 1.0 : 0.0;
- } else if (token.type == TOKEN_LESS) {
- next_token(parser);
- double right = parse_expression(parser);
- return (left < right) ? 1.0 : 0.0;
- } else if (token.type == TOKEN_GREATER) {
- next_token(parser);
- double right = parse_expression(parser);
- return (left > right) ? 1.0 : 0.0;
- } else if (token.type == TOKEN_LESS_EQUAL) {
- next_token(parser);
- double right = parse_expression(parser);
- return (left <= right) ? 1.0 : 0.0;
- } else if (token.type == TOKEN_GREATER_EQUAL) {
- next_token(parser);
- double right = parse_expression(parser);
- return (left >= right) ? 1.0 : 0.0;
- }
- return left;
- }
- // === FUNKCJE PARSOWANIA INSTRUKCJI ===
- void parse_statement(Parser* parser);
- void parse_block(Parser* parser);
- void parse_var_declaration(Parser* parser) {
- expect_token(parser, TOKEN_ZMIEN);
- Token name_token = current_token(parser);
- if (name_token.type != TOKEN_IDENTIFIER) {
- printf("Error: Expected variable name after 'zmien'\n");
- return;
- }
- next_token(parser);
- if (!expect_token(parser, TOKEN_EQUALS)) {
- printf("Error: Expected '=' after variable name\n");
- return;
- }
- double value = parse_comparison(parser);
- set_variable(parser->env, name_token.text, value);
- printf("Variable '%s' = %.6g\n", name_token.text, value);
- }
- void parse_pokaz_statement(Parser* parser) {
- expect_token(parser, TOKEN_POKAZ);
- Token token = current_token(parser);
- if (token.type == TOKEN_STRING) {
- printf("%s\n", token.text);
- next_token(parser);
- } else {
- double value = parse_comparison(parser);
- printf("%.6g\n", value);
- }
- }
- void parse_if_statement(Parser* parser) {
- expect_token(parser, TOKEN_IF);
- if (!expect_token(parser, TOKEN_LPAREN)) {
- printf("Error: Expected '(' after 'if'\n");
- return;
- }
- double condition = parse_comparison(parser);
- if (!expect_token(parser, TOKEN_RPAREN)) {
- printf("Error: Expected ')' after condition\n");
- return;
- }
- if (condition != 0.0) { // warunek prawdziwy
- if (current_token(parser).type == TOKEN_LBRACE) {
- parse_block(parser);
- } else {
- parse_statement(parser);
- }
- // Pomiń else jeśli istnieje
- if (current_token(parser).type == TOKEN_ELSE) {
- next_token(parser);
- if (current_token(parser).type == TOKEN_LBRACE) {
- // Pomiń blok else
- expect_token(parser, TOKEN_LBRACE);
- int brace_count = 1;
- while (brace_count > 0 && current_token(parser).type != TOKEN_EOF) {
- if (current_token(parser).type == TOKEN_LBRACE) brace_count++;
- if (current_token(parser).type == TOKEN_RBRACE) brace_count--;
- next_token(parser);
- }
- } else {
- // Pomiń pojedynczą instrukcję else
- while (current_token(parser).type != TOKEN_EOF &&
- current_token(parser).type != TOKEN_RBRACE) {
- next_token(parser);
- }
- }
- }
- } else { // warunek fałszywy
- // Pomiń blok if
- if (current_token(parser).type == TOKEN_LBRACE) {
- expect_token(parser, TOKEN_LBRACE);
- int brace_count = 1;
- while (brace_count > 0 && current_token(parser).type != TOKEN_EOF) {
- if (current_token(parser).type == TOKEN_LBRACE) brace_count++;
- if (current_token(parser).type == TOKEN_RBRACE) brace_count--;
- next_token(parser);
- }
- } else {
- // Pomiń pojedynczą instrukcję
- while (current_token(parser).type != TOKEN_EOF &&
- current_token(parser).type != TOKEN_RBRACE &&
- current_token(parser).type != TOKEN_ELSE) {
- next_token(parser);
- }
- }
- // Wykonaj else jeśli istnieje
- if (current_token(parser).type == TOKEN_ELSE) {
- next_token(parser);
- if (current_token(parser).type == TOKEN_LBRACE) {
- parse_block(parser);
- } else {
- parse_statement(parser);
- }
- }
- }
- }
- void parse_statement(Parser* parser) {
- Token token = current_token(parser);
- if (token.type == TOKEN_ZMIEN) {
- parse_var_declaration(parser);
- } else if (token.type == TOKEN_POKAZ) {
- parse_pokaz_statement(parser);
- } else if (token.type == TOKEN_IF) {
- parse_if_statement(parser);
- } else {
- // Wyrażenie do obliczenia
- double result = parse_comparison(parser);
- printf("Result: %.6g\n", result);
- }
- }
- void parse_block(Parser* parser) {
- expect_token(parser, TOKEN_LBRACE);
- while (current_token(parser).type != TOKEN_RBRACE &&
- current_token(parser).type != TOKEN_EOF) {
- parse_statement(parser);
- }
- expect_token(parser, TOKEN_RBRACE);
- }
- // === FUNKCJE GŁÓWNE ===
- Token* tokenize_all(char* input, int* token_count) {
- Lexer* lexer = create_lexer(input);
- Token* tokens = (Token*)malloc(sizeof(Token) * 100);
- *token_count = 0;
- Token token;
- do {
- token = get_next_token(lexer);
- tokens[*token_count] = token;
- (*token_count)++;
- } while (token.type != TOKEN_EOF && *token_count < 100);
- free(lexer);
- return tokens;
- }
- void execute_statement(char* input, Environment* env) {
- int token_count;
- Token* tokens = tokenize_all(input, &token_count);
- if (token_count == 0 || tokens[0].type == TOKEN_EOF) {
- free(tokens);
- return;
- }
- Parser* parser = create_parser(tokens, token_count, env);
- parse_statement(parser);
- free(tokens);
- free(parser);
- }
- void show_variables(Environment* env) {
- if (env->count == 0) {
- printf("No variables defined\n");
- return;
- }
- printf("Variables:\n");
- for (int i = 0; i < env->count; i++) {
- printf(" %s = %.6g\n", env->variables[i].name, env->variables[i].value);
- }
- }
- void test_conditionals() {
- printf("=== AUTOMATIC TESTS WITH CONDITIONALS ===\n");
- Environment* env = create_environment();
- execute_statement("zmien x = 10", env);
- execute_statement("zmien y = 5", env);
- printf("Testing: if (x > y) { pokaz \"x is bigger\" }\n");
- execute_statement("if (x > y) { pokaz \"x is bigger\" }", env);
- printf("Testing: if (y > x) { pokaz \"impossible\" } else { pokaz \"y is smaller\" }\n");
- execute_statement("if (y > x) { pokaz \"impossible\" } else { pokaz \"y is smaller\" }", env);
- printf("Testing: if (x == 10) { pokaz x }\n");
- execute_statement("if (x == 10) { pokaz x }", env);
- printf("Testing: if (x != y) { pokaz \"different\" }\n");
- execute_statement("if (x != y) { pokaz \"different\" }", env);
- }
- int main() {
- printf("=== CALCULATOR WITH CONDITIONALS ===\n");
- printf("Now your language supports if/else statements!\n\n");
- printf("Commands:\n");
- printf(" zmien name = expression - create variable\n");
- printf(" pokaz value - print value\n");
- printf(" pokaz \"text\" - print text\n");
- printf(" if (condition) { ... } - conditional execution\n");
- printf(" if (condition) {...} else {...} - if/else\n");
- printf(" expression - calculate\n");
- printf(" vars - show all variables\n");
- printf(" quit - exit\n\n");
- printf("Comparison operators: == != < > <= >=\n\n");
- test_conditionals();
- Environment* env = create_environment();
- char input[256];
- printf("\n=== INTERACTIVE MODE ===\n");
- while (1) {
- printf("> ");
- if (fgets(input, sizeof(input), stdin) == NULL) {
- break;
- }
- input[strcspn(input, "\n")] = 0;
- if (strcmp(input, "quit") == 0) {
- break;
- } else if (strcmp(input, "vars") == 0) {
- show_variables(env);
- } else if (strlen(input) > 0) {
- execute_statement(input, env);
- }
- }
- printf("\nCongratulations! Your language now has conditionals!\n");
- printf("Next: loops, functions, arrays...\n");
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment