├── LICENSE ├── Makefile ├── README.md ├── demo └── all_in_one ├── src ├── command.c ├── file.c ├── lib │ ├── command.h │ ├── file.h │ ├── parser.h │ └── util.h ├── main.c ├── parser.c └── util.c └── test ├── calc ├── comment ├── if ├── print ├── repeat └── variable /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Hakkı Anıl Ragıboğlu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # ANSI-C MAKEFILE # 2 | 3 | CC = gcc 4 | ansi = -std=c89 5 | 6 | file = src/file.c 7 | util = src/util.c 8 | parser = src/parser.c 9 | com = src/command.c 10 | lib = $(file) $(util) $(parser) $(com) 11 | main = src/main.c 12 | 13 | ifeq ($(OS),Windows_NT) 14 | output = acc.exe 15 | debug = debug.exe 16 | delete = del 17 | else 18 | output = acc 19 | debug = debug 20 | delete = rm 21 | endif 22 | 23 | .PHONY: run clean debug cleand 24 | 25 | run: $(main) $(lib) 26 | $(CC) $(ansi) $(main) $(lib) -o $(output) 27 | 28 | clean: $(output) 29 | $(delete) $(output) 30 | 31 | debug: $(main) $(lib) 32 | $(CC) -g $(main) $(lib) -o $(debug) 33 | 34 | cleand: $(debug) 35 | $(delete) $(debug) 36 | 37 | # MADE BY @hanilr # -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PARSER TEST 2 | Parser test project written in ansi-c. 3 | The project has a total of 656 lines. Header files are included. 4 | 5 | * [About The Project](#about-the-project) 6 | * [Purpose Of Project](#purpose-of-project) 7 | * [Features](#features) 8 | * [Build](#build) 9 | * [Guide](#guide) 10 | * [Bugs](#bugs) 11 | 12 | 13 | # About The Project 14 | While thinking about programming languages, I began to wonder how parsers work. When I started to research this subject, I had already started to prepare the project while I was thinking if I could prepare a project that would not be too complicated. As a result of my researches, many questions remained in my mind and while I was lost in my thoughts, for a moment "Can I do such a project without using any algorithms or knowledge?" I thought. Afterwards, I liked this idea, so now I could write my own programming language with my own algorithms and rules I would set myself. This is how I started doing this project. I have to admit that this was the project where I developed myself the most. In the first stages of the project, I encountered a lot of problems because I did not know about some subjects such as memory management. I decided to share it on Reddit and shared it immediately. Some of the feedback said that either my own algorithms and rules are silly or that it could be a good project so I can improve myself. I was so excited and made some decisions and plans and made a todo list showing my goals and mistakes. Thus, I started to constantly improve the project and myself. Sometimes I was able to finish the project even though my visas and some university problems came in between. I am proud of the project I have done because I have improved myself both in the C programming language and in compilers. Now I can better understand the working logic of programming languages. In fact, when I looked at the python repository, I was very interested in some of the things they did, because they did almost what I did, or even better. If I want to continue developing this project someday, I will definitely look at other algorithms and information, and even look at languages such as python and lua and develop my project. The best experience I got from this project was that I didn't have to look at other projects or information resources to achieve anything, so I can do well on my own, of course, how successful it can be is a relative thing. Thank you for looking at my project. 15 | 16 | # Purpose Of Project 17 | The aim of this project is to understand how parsers in compilers work and to make this project a programming language with the algorithms and rules I have made. In other words, no compiler or parser-related resources were used in this project. Every algorithm or working logic in the project is entirely my own. The purpose of my saying this is that if you are looking for a professional project, this project is not for you, it is more of a trial project. 18 | 19 | # Features 20 | * CLI 21 | * Print 22 | * Loop statement 23 | * If statement 24 | * Variables 25 | * Basic calculator 26 | * Comment lines 27 | * File parser (Like python or lua does) 28 | 29 | # Build 30 | ### Required tools: 31 | * ` gcc ` or ` mingw ` 32 | * ` make ` 33 | 34 | ### Building: 35 | * ` cd parser-test/ ` to enter the project folder. 36 | * ` make ` to compile the project. 37 | * ` make clean ` to delete compiled files. 38 | 39 | 40 | # Guide 41 | ### CLI (Command Line Interface) 42 | Execute the compiled file with no argument. Then just write what you want in command line. 43 | - Variables not working. 44 | 45 | ### Print (Writing in terminal) 46 | Print function need two quotation mark if you want to write a string. 47 | - Example: ` print("foo") ` 48 | 49 | Printing a variable is simple just write a defined variable. Need '$' symbol before variable name. 50 | - Example: 51 | ` $foo = "bar" ` 52 | ` print($foo) ` 53 | 54 | Note: '\0' and '\n' allowed. 55 | 56 | ### Loop Statement 57 | Loop section only has 'repeat()' function which means can only repeat with certain values. 58 | - Example: ` repeat(12) {print("foo ")} ` 59 | 60 | ### If Statement 61 | If section can only use once in a file. And also part of if else true section doesn't work. 62 | - Only works with variables. 63 | - In comparing variables doesn't need quotation marks. 64 | - Examples: ` $foo == "bar" ` 65 | * ` if($foo == bar:) {print("bar ")} ` Result: bar 66 | * ` if($foo == bar:) {print("bar "),print("false ");} ` Doesn't work! 67 | * ` if($foo == foo:) {print("bar "),print("false ");} ` Result: false 68 | 69 | ### Variable 70 | You need just defining a variable. You can use in 'print()', 'repeater()' and 'if()' functions. 71 | - Example: ` $foo = "bar" ` 72 | 73 | ### Basic Calculator 74 | Basic calculator means can't calculate 2 digit numbers. And you can calculate only addition, subtraction, multiplication and division operations. 75 | - Calculating section doesn't need 'print()' function. Because it print itself. 76 | - If result is not digit in division section then result is 0. 77 | - Example: 78 | * ` (+ 1 2) ` Result: 3 79 | * ` (- 2 1) ` Result: 1 80 | * ` (* 2 3) ` Result: 6 81 | * ` (/ 4 2) ` Result: 2 82 | * ` (/ 3 2) ` Result: 0 83 | * ` (+ 1 2 3) ` Result: 6 84 | * ` (+ 1 2 3 4) ` Result: 10 85 | 86 | ### Comment 87 | Comment section is like python does. Comment symbol is '#' 88 | - Example: ` print("foo") # This is comment line. ` 89 | 90 | ### File Parser 91 | File parser doesn't compile just executing a file like python or lua does. 92 | - No need a file extension. 93 | - Example: 94 | * ` acc.exe test/print ` 95 | * ` ./acc demo/all_in_one` 96 | 97 | ### **Note: Parser may be sensitivity to the placement of spaces!** 98 | 99 | # Bugs 100 | * If else true statement not working. 101 | * Can only use one if statement in files. 102 | * If last line of file was not empty then last line doesn't work. 103 | * In calculator section if didn't add space to last letter then last number doesn't calculating. 104 | -------------------------------------------------------------------------------- /demo/all_in_one: -------------------------------------------------------------------------------- 1 | $foo = "bar" 2 | $bar = "hanilr" 3 | 4 | if($bar == foo:) {(+ 1 2),print("Wrong variable! ");} 5 | 6 | (+ 1 2 3) # 6 7 | 8 | repeat(2) {print("Work! ")} 9 | -------------------------------------------------------------------------------- /src/command.c: -------------------------------------------------------------------------------- 1 | /* COMMANDS MAIN FILE */ 2 | 3 | /* STANDARD LIBRARY */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* DIY LIBRARY */ 10 | #include "lib/command.h" 11 | #include "lib/util.h" 12 | 13 | int calc(char operation, int x, int y) 14 | { 15 | switch((int) operation) 16 | { 17 | case '+': 18 | return x+y; 19 | case '-': 20 | return x-y; 21 | case '*': 22 | return x*y; 23 | case '/': 24 | if(x%y == 0) { return x/y; } 25 | else { return 0; } 26 | } 27 | } 28 | 29 | void print_chars(char *str) 30 | { 31 | int i = 0; 32 | while(strlen(str) > i) 33 | { 34 | if(str[i] == '\\' && str[i+1] == 'n') 35 | { 36 | printf("\n"); 37 | i+=1; 38 | } 39 | else if(str[i] == '\\' && str[i+1] == '0') { break; } 40 | else { printf("%c", str[i]); } 41 | i+=1; 42 | } 43 | } 44 | 45 | void print(char *raw_str) 46 | { 47 | if(raw_str[0] == '"' && chrepeat(raw_str, '"')%2 == 0) 48 | { 49 | char *str = (char*) malloc(strlen(raw_str)-1); 50 | int i = 0; 51 | 52 | memset(str, 0, strlen(raw_str)-1); 53 | while(strlen(raw_str)-2 > i) 54 | { 55 | str[i] = raw_str[i+1]; 56 | i+=1; 57 | } 58 | print_chars(str); 59 | free(str); 60 | } 61 | } 62 | 63 | void clrscr(void) { printf("\033[2J \033[H"); } 64 | 65 | void quit(void) { exit(EXIT_SUCCESS); } 66 | 67 | /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/file.c: -------------------------------------------------------------------------------- 1 | /* FILE MAIN FILE */ 2 | 3 | /* STANDARD LIBRARY */ 4 | #include 5 | #include 6 | #include 7 | 8 | /* DIY LIBRARY */ 9 | #include "lib/file.h" 10 | 11 | const char *read_file(char *file) 12 | { 13 | char *file_content; 14 | long file_size; 15 | 16 | FILE *rf = fopen(file, "r"); 17 | if(rf == 0) 18 | { 19 | fprintf(stderr, "\nFILE ERROR: File not exist! (Read File)"); 20 | exit(EXIT_FAILURE); 21 | } 22 | 23 | fseek(rf, 0, SEEK_END); 24 | file_size = ftell(rf); 25 | fseek(rf, 0, SEEK_SET); 26 | 27 | file_content = (char*) malloc(file_size+1); 28 | fread(file_content, file_size, 1, rf); 29 | 30 | fclose(rf); 31 | return file_content; 32 | } 33 | 34 | const char *get_line(char *file, int line) 35 | { 36 | int current_line = 0; 37 | long file_size; 38 | 39 | FILE *gl = fopen(file, "r"); 40 | if(gl == 0) 41 | { 42 | fprintf(stderr, "\nFILE ERROR: File not exist! (Get Line)"); 43 | exit(EXIT_FAILURE); 44 | } 45 | 46 | fseek(gl, 0, SEEK_END); 47 | file_size = ftell(gl); 48 | fseek(gl, 0, SEEK_SET); 49 | 50 | char *str_temp = (char*) malloc(file_size+1); 51 | while(line > current_line) 52 | { 53 | fgets(str_temp, file_size+1, gl); 54 | current_line+=1; 55 | } 56 | 57 | fclose(gl); 58 | return str_temp; 59 | } 60 | 61 | /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/lib/command.h: -------------------------------------------------------------------------------- 1 | /* COMMANDS HEADER FILE */ 2 | 3 | #ifndef _COMMAND_H 4 | #define _COMMAND_H 5 | 6 | int calc(char operation, int x, int y); 7 | 8 | void print_chars(char *str); 9 | 10 | void print(char *raw_str); 11 | 12 | void clrscr(void); /* CLEAR SCREEN */ 13 | 14 | void quit(void); 15 | 16 | #endif /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/lib/file.h: -------------------------------------------------------------------------------- 1 | /* FILE HEADER FILE */ 2 | 3 | #ifndef _FILE_H 4 | #define _FILE_H 5 | 6 | const char *read_file(char *file); 7 | 8 | const char *get_line(char *file, int line); 9 | 10 | #endif /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/lib/parser.h: -------------------------------------------------------------------------------- 1 | /* PARSER HEADER FILE */ 2 | 3 | #ifndef _PARSER_H 4 | #define _PARSER_H 5 | 6 | struct variable 7 | { 8 | char name[63]; 9 | char value[2047]; 10 | int count; 11 | }; /* VARIABLE SECTION */ 12 | 13 | void calc_parser(char *raw, int arg_count); 14 | 15 | void file_parser(char *file_name); 16 | 17 | void parser(char *str_temp, struct variable *var, int var_count); 18 | 19 | #endif /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/lib/util.h: -------------------------------------------------------------------------------- 1 | /* UTIL HEADER FILE */ 2 | 3 | #ifndef _UTIL_H 4 | #define _UTIL_H 5 | 6 | int chrepeat(const char *str, char ascii); /* REPEAT TIMES OF A CHARACTER IN A STRING */ 7 | 8 | int dislen(const char *str, int first_pos, char *chr1, char *chr2); /* DISTANCE TWO CHARACTER IN A STRING */ 9 | 10 | int subinstr(const char *str, char *chr); /* CHECK SUBSTRING IF IN THE STRING */ 11 | 12 | int lastpos(const char *str, char *chr); /* LAST POSITION OF A WORD IN A STRING */ 13 | 14 | int lastpos_line(const char *str, char *chr, int line); /* LIKE 'lastpos' BUT YOU CAN GET LINES */ 15 | 16 | #endif /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* MAIN FILE */ 2 | 3 | /* STANDARD LIBRARY */ 4 | #include 5 | #include 6 | #include 7 | 8 | /* DIY LIBRARY */ 9 | #include "lib/file.h" 10 | #include "lib/util.h" 11 | #include "lib/parser.h" 12 | #include "lib/command.h" 13 | 14 | int main(int argc, char *argv[]) 15 | { 16 | if(argc == 1) 17 | { 18 | printf("Parser-acc v1.0"); 19 | char *com = (char*) malloc(128); 20 | struct variable var[1]; 21 | while(1) 22 | { 23 | printf("\n> "); 24 | fgets(com, 128, stdin); 25 | parser(com, var, 0); 26 | memset(com, 0, 128); 27 | } 28 | free(com); 29 | } 30 | else if(argc > 2) 31 | { 32 | fprintf(stderr, "\nMISSING ARGUMENT!"); 33 | return 1; 34 | } 35 | else { file_parser(argv[1]); } 36 | return 0; 37 | } 38 | 39 | /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/parser.c: -------------------------------------------------------------------------------- 1 | /* PARSER MAIN FILE */ 2 | 3 | /* STANDARD LIBRARY */ 4 | #include 5 | #include 6 | #include 7 | 8 | /* DIY LIBRARY */ 9 | #include "lib/parser.h" 10 | #include "lib/file.h" 11 | #include "lib/util.h" 12 | #include "lib/command.h" 13 | 14 | void calc_parser(char *raw, int arg_count) 15 | { 16 | if(chrepeat(raw, '+') > 1 || chrepeat(raw, '-') > 1 || chrepeat(raw, '*') > 1 || chrepeat(raw, '/') > 1) 17 | { 18 | fprintf(stderr, "\nCALCULATOR PARSER ERROR: Too much operation symbol!"); 19 | exit(EXIT_FAILURE); 20 | } 21 | char operation = raw[0]; 22 | int result, x, y; 23 | 24 | int pos_x = lastpos_line(raw, " ", 1); 25 | int pos_y = lastpos_line(raw, " ", 2); 26 | x = raw[pos_x+1] - '0'; 27 | y = raw[pos_y+1] - '0'; 28 | result = calc(operation, x, y); 29 | 30 | if(arg_count > 2) 31 | { 32 | int i = 2; 33 | while(arg_count > i+1) 34 | { 35 | int pos = lastpos_line(raw, " ", i+1); 36 | int temp = raw[pos+1] - '0'; 37 | result = calc(operation, result, temp); 38 | i+=1; 39 | } 40 | } 41 | printf("%d ", result); 42 | } 43 | 44 | void file_parser(char *file_name) 45 | { 46 | const char *whole_file = read_file(file_name); 47 | int line_of_str = chrepeat(whole_file, '\n')+1, i = 1; 48 | if(chrepeat(whole_file, '\n') == 0) { line_of_str = 2; } /* IF ONLY ONE LINE IN A FILE */ 49 | 50 | struct variable var[128]; 51 | var[0].count = 1; 52 | 53 | while(line_of_str+1 > i) 54 | { 55 | if(i == line_of_str && whole_file[strlen(whole_file)] == '\0') { break; } /* IF LAST LINE EMPTY */ 56 | const char *str_temp = (char*) malloc(strlen(get_line(file_name, i))+1); 57 | str_temp = get_line(file_name, i); 58 | parser((char*) str_temp, var, var[0].count); 59 | free((char*) str_temp); 60 | i+=1; 61 | } 62 | } 63 | 64 | void parser(char *str_temp, struct variable *var, int var_count) 65 | { 66 | /* STATEMENTS */ 67 | if(subinstr(str_temp, "#") == 0) /* COMMENT SECTION */ 68 | { 69 | int comment_pos = lastpos(str_temp, "#"); 70 | while(strlen(str_temp)+1 > comment_pos) 71 | { 72 | str_temp[comment_pos] = '\0'; 73 | comment_pos+=1; 74 | } 75 | } 76 | if(str_temp[0] == '$') /* VARIABLE SECTION */ 77 | { 78 | if(var_count == 129) 79 | { 80 | fprintf(stderr, "\nPARSER ERROR: Too much variable!"); 81 | exit(EXIT_FAILURE); 82 | } 83 | 84 | int var_pos = lastpos(str_temp, "$")+1, x = 0, y = 0; 85 | int content_pos = lastpos(str_temp, "\"")+1; 86 | char *temp = (char*) malloc(strlen(str_temp)+1); 87 | 88 | while(strlen(str_temp) > x) 89 | { 90 | temp[x] = str_temp[var_pos+x]; 91 | if(str_temp[var_pos+x+1] == ' ' || str_temp[var_pos+x+1] == '=') 92 | { 93 | temp[x+1] = '\0'; 94 | break; 95 | } 96 | x+=1; 97 | } 98 | strcpy(var[var_count].name, temp); 99 | memset(temp, 0, strlen(temp)+1); 100 | while(strlen(str_temp) > y) 101 | { 102 | temp[y] = str_temp[content_pos+y]; 103 | if(str_temp[content_pos+y+1] == '\"') 104 | { 105 | temp[y+1] = '\0'; 106 | break; 107 | } 108 | y+=1; 109 | } 110 | strcpy(var[var_count].value, temp); 111 | free(temp); 112 | var[0].count+=1; 113 | } 114 | if(subinstr(str_temp, "repeat(") == 0) /* REPEAT LOOP SECTION */ 115 | { 116 | 117 | int command_pos = lastpos(str_temp, "repeat("), times; 118 | int times_line = dislen(str_temp, command_pos, "(", ")"); 119 | int content_pos = lastpos(str_temp, "{"); 120 | int content_line = dislen(str_temp, content_pos, "{", "}"); 121 | char *content = (char*) malloc(content_line+1); 122 | 123 | int i = 0; 124 | while(content_line > i) 125 | { 126 | content[i] = str_temp[content_pos+i+1]; 127 | i+=1; 128 | } 129 | 130 | if(times_line == 1) { times = str_temp[command_pos+1] - '0'; } 131 | else 132 | { 133 | times = str_temp[command_pos+1] - '0'; 134 | int i = 1; 135 | while(times_line > i) 136 | { 137 | times = (times * 10) + (str_temp[command_pos+i+1] - '0'); 138 | i+=1; 139 | } 140 | } 141 | 142 | while(times > 0) 143 | { 144 | parser(content, var, var_count); 145 | times-=1; 146 | } 147 | memset(str_temp, 0, strlen(str_temp)+1); 148 | free(content); 149 | } 150 | if(subinstr(str_temp, "if(") == 0) /* IF STATEMENT SECTION */ 151 | { 152 | int command_pos = lastpos(str_temp, "if("), times; 153 | int command_line = dislen(str_temp, command_pos, "(", ")"); 154 | int content_pos = lastpos(str_temp, "{"); 155 | int content_line = dislen(str_temp, content_pos, "{", "}"); 156 | char *content = (char*) malloc(content_line+1); 157 | char *command = (char*) malloc(command_line+1); 158 | 159 | int i = 0; 160 | while(command_line > i) 161 | { 162 | command[i] = str_temp[command_pos+i+1]; 163 | i+=1; 164 | } 165 | i = 0; 166 | while(content_line > i) 167 | { 168 | content[i] = str_temp[content_pos+i+1]; 169 | i+=1; 170 | } 171 | 172 | if(subinstr(command, "==") == 0) /* IF EQUAL */ 173 | { 174 | if(subinstr(command, "$") == 0) /* VARIABLE SECTION */ 175 | { 176 | int space_pos = lastpos_line(command, " ", 1), var_point; 177 | int sspace_pos = lastpos_line(command, " ", 2); /* SECOND SPACE */ 178 | char *var_buffer = (char*) malloc(space_pos); 179 | char *var_equal = (char*) malloc(command_line-(sspace_pos+1)+1); 180 | 181 | i = 0; 182 | while(space_pos > i+1) 183 | { 184 | var_buffer[i] = command[i+1]; 185 | i+=1; 186 | } 187 | i = 0; 188 | int equal_line = dislen(command, sspace_pos, " ", ":"); 189 | while(equal_line > i) 190 | { 191 | var_equal[i] = command[sspace_pos+i+1]; 192 | i+=1; 193 | } 194 | i = 0; 195 | while(127 > i) 196 | { 197 | if(subinstr(var[i].name, var_buffer) == 0) 198 | { 199 | var_point = i; 200 | break; 201 | } 202 | if(i == 126) 203 | { 204 | fprintf(stderr, "\nPARSER ERROR: No variable detected! (IF)"); 205 | exit(EXIT_FAILURE); 206 | } 207 | i+=1; 208 | } 209 | i = 0; 210 | if(subinstr(var[var_point].value, var_equal) == 0 && subinstr(content, ",") != 0) { parser(content, var, var_count); } /* TRUE */ 211 | else if(subinstr(var[var_point].value, var_equal) == 0 && subinstr(content, ",") == 0) /* IF ELSE TRUE */ 212 | { 213 | int else_pos = lastpos(content, ","); 214 | char *content_if = (char*) malloc(else_pos+1); 215 | memset(content_if, 0, content_line+1); 216 | while(else_pos > i) 217 | { 218 | content_if[i] = content[i]; 219 | i+=1; 220 | } 221 | parser(content_if, var, var_count); 222 | free(content_if); 223 | } 224 | else /* IF ELSE FALSE */ 225 | { 226 | int else_pos = lastpos(content, ","); 227 | int else_dis = dislen(content, else_pos, ",", ";"); 228 | char *content_else = (char*) malloc(else_dis+1); 229 | memset(content_else, 0, else_dis+1); 230 | while(else_dis > i) 231 | { 232 | content_else[i] = content[else_pos+i+1]; 233 | i+=1; 234 | } 235 | parser(content_else, var, var_count); 236 | free(content_else); 237 | } 238 | free(var_equal); 239 | free(var_buffer); 240 | } 241 | else { /* NONE VARIABLE SECTION */ } 242 | } 243 | else { /* OTHER LOGICAL OPERATIONS */ } 244 | memset(str_temp, 0, strlen(str_temp)+1); 245 | free(command); 246 | free(content); 247 | } 248 | 249 | /* COMMANDS */ 250 | if(str_temp[lastpos(str_temp, "(")] == '(' && (str_temp[lastpos(str_temp, "(")+1] == '+' || str_temp[lastpos(str_temp, "(")+1] == '-' || str_temp[lastpos(str_temp, "(")+1] == '*' || str_temp[lastpos(str_temp, "(")+1] == '/')) 251 | { 252 | if(subinstr(str_temp, ")") != 0) 253 | { 254 | fprintf(stderr, "\nPARSER ERROR: Uncorrect syntax! (MATH)"); 255 | exit(EXIT_FAILURE); 256 | } 257 | 258 | int content_pos = lastpos(str_temp, "("); 259 | int content_line = dislen(str_temp, content_pos, "(", ")"); 260 | int arg_count = chrepeat(str_temp, ' '), x = 0; 261 | if(str_temp[strlen(str_temp)] == ' ') { arg_count-=1; } 262 | 263 | char *content = (char*) malloc(content_line+1); 264 | while(content_line > x) 265 | { 266 | content[x] = str_temp[x+1]; 267 | x+=1; 268 | } 269 | calc_parser(content, arg_count); 270 | free(content); 271 | } /* MATH */ 272 | if(subinstr(str_temp, "print(") == 0) 273 | { 274 | /* ERRORS */ 275 | if(subinstr(str_temp, ")") != 0) 276 | { 277 | fprintf(stderr, "\nPARSER ERROR: Uncorrect syntax! (PRINT)"); 278 | exit(EXIT_FAILURE); 279 | } 280 | 281 | int command_pos = lastpos(str_temp, "print"), x = 0; 282 | int content_line = dislen(str_temp, command_pos, "(", ")"); 283 | 284 | char *content = (char*) malloc(content_line+1); 285 | memset(content, 0, content_line+1); 286 | while(content_line > x) 287 | { 288 | content[x] = str_temp[command_pos+x+2]; 289 | x+=1; 290 | } 291 | content[content_line+1] = '\0'; 292 | 293 | if(subinstr(content, "$") == 0) 294 | { 295 | if(subinstr(content, "\"") == 0) 296 | { 297 | fprintf(stderr, "\nPARSER ERROR: Uncorrect syntax! (VARIABLE)"); 298 | exit(EXIT_FAILURE); 299 | } 300 | 301 | char *var_buffer = (char*) malloc(content_line); 302 | int var_pos = lastpos(content, "$"); 303 | int var_len = dislen(content, var_pos, "$", "\0"); 304 | int var_point, y = 0, z = 0; 305 | 306 | while(var_len+1 > y) 307 | { 308 | var_buffer[y] = content[var_pos+y+1]; 309 | if(y == var_len) 310 | { 311 | var_buffer[y+1] == '\0'; 312 | break; 313 | } 314 | y+=1; 315 | } 316 | while(128 > z) 317 | { 318 | if(subinstr(var[z].name, var_buffer) == 0) 319 | { 320 | var_point = z; 321 | break; 322 | } 323 | if(z == 127) 324 | { 325 | fprintf(stderr, "\nPARSER ERROR: No variable detected! (PRINT)"); 326 | exit(EXIT_FAILURE); 327 | } 328 | z+=1; 329 | } 330 | print_chars(var[var_point].value); 331 | free(var_buffer); 332 | } /* VARIABLE SECTION */ 333 | else { print(content); } 334 | free(content); 335 | } /* PRINT */ 336 | if(subinstr(str_temp, "clrscr()") == 0) { clrscr(); } /* CLEAR SCREEN */ 337 | if(subinstr(str_temp, "quit()") == 0) { quit(); } /* QUIT */ 338 | } 339 | 340 | /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /src/util.c: -------------------------------------------------------------------------------- 1 | /* UTIL MAIN FILE */ 2 | 3 | /* STANDARD LIBRARY */ 4 | #include 5 | #include 6 | #include 7 | 8 | /* DIY LIBRARY */ 9 | #include "lib/util.h" 10 | #include "lib/file.h" 11 | 12 | int chrepeat(const char *str, char ascii) 13 | { 14 | int word_buffer = 0, i = 0; 15 | while(strlen(str) > i) 16 | { 17 | if(str[i] == ascii) { word_buffer+=1; } 18 | i+=1; 19 | } 20 | return word_buffer; 21 | } 22 | 23 | int dislen(const char *str, int pos, char *chr1, char *chr2) 24 | { 25 | int x = pos, y = pos; 26 | while(strlen(str) > pos) 27 | { 28 | if(str[x] == chr1[0]) 29 | { 30 | if(str[y] == chr2[0]) { break; } 31 | else { y+=1; } 32 | } 33 | else { x+=1; } 34 | pos+=1; 35 | } 36 | return y-x-1; 37 | } 38 | 39 | int subinstr(const char *str, char *chr) 40 | { 41 | int word_pos = 0, buffer = 0; 42 | while(strlen(str) > word_pos) 43 | { 44 | if(str[word_pos] == chr[buffer]) { buffer+=1; } 45 | else { buffer = 0; } 46 | if(strlen(chr) == buffer) { return 0; } 47 | word_pos+=1; 48 | } 49 | return 1; 50 | } 51 | 52 | int lastpos(const char *str, char *chr) 53 | { 54 | int word_pos = 0, buffer = 0; 55 | while(strlen(str) > word_pos) 56 | { 57 | if(str[word_pos] == chr[buffer]) { buffer+=1; } 58 | else { buffer = 0; } 59 | if(strlen(chr) == buffer) { break; } 60 | word_pos+=1; 61 | } 62 | return word_pos; 63 | } /* START WITH 0 */ 64 | 65 | int lastpos_line(const char *str, char *chr, int line) 66 | { 67 | int pos = lastpos(str, chr), pos_line, x = 0, y = 0; 68 | if(line == 1) { return pos; } 69 | char *temp = (char*) malloc(strlen(str)+1); 70 | 71 | while(line > x) 72 | { 73 | while(strlen(str)-pos > y) 74 | { 75 | temp[y] = str[pos+y]; 76 | y+=1; 77 | } 78 | y = 0; 79 | pos_line = lastpos(temp, chr); 80 | pos += pos_line+1; 81 | x+=1; 82 | } 83 | 84 | free(temp); 85 | return pos-1; 86 | } 87 | 88 | /* MADE BY @hanilr */ -------------------------------------------------------------------------------- /test/calc: -------------------------------------------------------------------------------- 1 | (+ 1 2) # 3 2 | (- 2 1) # 1 3 | (* 2 3) # 6 4 | (/ 4 2) # 2 5 | (/ 3 2) # 0 6 | 7 | (+ 1 2 3) # 6 8 | (- 6 1 2) # 3 9 | (* 2 3 4) # 24 10 | (/ 6 3 2) # 1 11 | -------------------------------------------------------------------------------- /test/comment: -------------------------------------------------------------------------------- 1 | # test 2 | # print("test") 3 | # \0 4 | # \n 5 | -------------------------------------------------------------------------------- /test/if: -------------------------------------------------------------------------------- 1 | $foo = "bar" 2 | 3 | # if($foo == bar:) {print("bar ")} # bar 4 | 5 | # if($foo == bar:) {print("barr "),print("none ");} # barr 6 | 7 | # if($foo == false:) {print("barrr "),print("nonee ");} # nonee 8 | -------------------------------------------------------------------------------- /test/print: -------------------------------------------------------------------------------- 1 | print(test without quotation mark) # No result 2 | print("test with quotation mark") # test with quotation mark 3 | 4 | print("\n\nnew\nline\n\n") 5 | # 6 | # 7 | # new 8 | # line 9 | # 10 | # 11 | 12 | print("end of the\0line") # end of the 13 | -------------------------------------------------------------------------------- /test/repeat: -------------------------------------------------------------------------------- 1 | repeat(2) {print("foo ")} # foo foo 2 | 3 | repeat(5) {(+ 1 2 3)} # 6 6 6 6 6 4 | 5 | repeat(11) {print("1 ")} # 1 1 1 1 1 1 1 1 1 1 1 6 | -------------------------------------------------------------------------------- /test/variable: -------------------------------------------------------------------------------- 1 | $test = "test " 2 | $foo = "bar " 3 | 4 | print($test) # test 5 | print($foo) # bar 6 | 7 | $after_line = "yep" 8 | 9 | print($after_line) # yep 10 | --------------------------------------------------------------------------------