diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b0ac6ad --- /dev/null +++ b/Makefile @@ -0,0 +1,12 @@ +default : parser + +parser : parser.c + gcc -o parser.exe parser.c + + +parser.c : main.py + chmod +x main.py + python3 main.py > parser.c + +clean : + rm -f parser.c parser.exe diff --git a/grammar.txt b/grammar.txt new file mode 100644 index 0000000..8191ca8 --- /dev/null +++ b/grammar.txt @@ -0,0 +1,9 @@ +S : a S b +S : int +S : " string " +S : { Assoc } +Assoc : KeyVal AssocBis +Assoc : +AssocBis : , KeyVal AssocBis +AssocBis : +KeyVal : id = S \ No newline at end of file diff --git a/main.py b/main.py old mode 100644 new mode 100755 index 198b495..f15cf93 --- a/main.py +++ b/main.py @@ -162,5 +162,5 @@ int parse_{code}(char* word, int pos) {{ if __name__ == '__main__': - with open("sample.txt", "r") as f: + with open("grammar.txt", "r") as f: parse(f.readlines()) diff --git a/parser.c b/parser.c new file mode 100644 index 0000000..41fa6a8 --- /dev/null +++ b/parser.c @@ -0,0 +1,474 @@ +#include +#include + +void print_with_indent(int indent, char * string) { + printf("%*s%s", indent, "", string); +} + +int parse_S(char* word, int pos); +int parse_Assoc(char* word, int pos); +int parse_AssocBis(char* word, int pos); +int parse_KeyVal(char* word, int pos); + +// ---- Functions to parse terminals ---- +int parse_string(char* word, int pos) { + // Extract the next 6 chars of the word + char substr[7]; + substr[0] = '\0'; + strncat(substr, &word[pos], 6); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "string") == 0 && (word[pos+6] == ' ' || word[pos+6] == '\0')) { + print_with_indent(pos, "string\n"); + return 7; + } else { + return -1; + } +} + +int parse_a(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "a") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, "a\n"); + return 2; + } else { + return -1; + } +} + +int parse_44(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, ",") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, ",\n"); + return 2; + } else { + return -1; + } +} + +int parse_b(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "b") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, "b\n"); + return 2; + } else { + return -1; + } +} + +int parse_125(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "}") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, "}\n"); + return 2; + } else { + return -1; + } +} + +int parse_id(char* word, int pos) { + // Extract the next 2 chars of the word + char substr[3]; + substr[0] = '\0'; + strncat(substr, &word[pos], 2); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "id") == 0 && (word[pos+2] == ' ' || word[pos+2] == '\0')) { + print_with_indent(pos, "id\n"); + return 3; + } else { + return -1; + } +} + +int parse_123(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "{") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, "{\n"); + return 2; + } else { + return -1; + } +} + +int parse_34(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "\"") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, "\"\n"); + return 2; + } else { + return -1; + } +} + +int parse_int(char* word, int pos) { + // Extract the next 3 chars of the word + char substr[4]; + substr[0] = '\0'; + strncat(substr, &word[pos], 3); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "int") == 0 && (word[pos+3] == ' ' || word[pos+3] == '\0')) { + print_with_indent(pos, "int\n"); + return 4; + } else { + return -1; + } +} + +int parse_61(char* word, int pos) { + // Extract the next 1 chars of the word + char substr[2]; + substr[0] = '\0'; + strncat(substr, &word[pos], 1); + + // Compare this extracted string to the terminal, + // and check if the next char is a space or the end of the string + if (strcmp(substr, "=") == 0 && (word[pos+1] == ' ' || word[pos+1] == '\0')) { + print_with_indent(pos, "=\n"); + return 2; + } else { + return -1; + } +} + +// ---- Functions to parse a non-terminal according to a rule ---- +int parse_S1(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering S1\n"); + + nbCharParsed = parse_a(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail a in S1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_S(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail S in S1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_b(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail b in S1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success S1\n"); + return totalCharParsed; +} + +int parse_S2(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering S2\n"); + + nbCharParsed = parse_int(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail int in S2\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success S2\n"); + return totalCharParsed; +} + +int parse_S3(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering S3\n"); + + nbCharParsed = parse_34(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail 34 in S3\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_string(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail string in S3\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_34(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail 34 in S3\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success S3\n"); + return totalCharParsed; +} + +int parse_S4(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering S4\n"); + + nbCharParsed = parse_123(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail 123 in S4\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_Assoc(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail Assoc in S4\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_125(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail 125 in S4\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success S4\n"); + return totalCharParsed; +} + +int parse_Assoc1(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering Assoc1\n"); + + nbCharParsed = parse_KeyVal(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail KeyVal in Assoc1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_AssocBis(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail AssocBis in Assoc1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success Assoc1\n"); + return totalCharParsed; +} + +int parse_Assoc2(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering Assoc2\n"); + + printf("Epsilon! -> Success\n"); + + printf("Success Assoc2\n"); + return totalCharParsed; +} + +int parse_AssocBis1(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering AssocBis1\n"); + + nbCharParsed = parse_44(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail 44 in AssocBis1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_KeyVal(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail KeyVal in AssocBis1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_AssocBis(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail AssocBis in AssocBis1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success AssocBis1\n"); + return totalCharParsed; +} + +int parse_AssocBis2(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering AssocBis2\n"); + + printf("Epsilon! -> Success\n"); + + printf("Success AssocBis2\n"); + return totalCharParsed; +} + +int parse_KeyVal1(char* word, int pos) { + int totalCharParsed = 0; + int nbCharParsed; + printf("Entering KeyVal1\n"); + + nbCharParsed = parse_id(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail id in KeyVal1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_61(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail 61 in KeyVal1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + nbCharParsed = parse_S(word, pos + totalCharParsed); + if (nbCharParsed == -1) { + printf("Fail S in KeyVal1\n"); + return -1; + } + totalCharParsed += nbCharParsed; + + printf("Success KeyVal1\n"); + return totalCharParsed; +} + +// ---- Functions to parse a non-terminal by testing all rules ---- +int parse_S(char* word, int pos) { + int nbCharParsed; + printf("Entering S\n"); + + nbCharParsed = parse_S1(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + nbCharParsed = parse_S2(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + nbCharParsed = parse_S3(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + nbCharParsed = parse_S4(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + return -1; +} + +int parse_Assoc(char* word, int pos) { + int nbCharParsed; + printf("Entering Assoc\n"); + + nbCharParsed = parse_Assoc1(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + nbCharParsed = parse_Assoc2(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + return -1; +} + +int parse_AssocBis(char* word, int pos) { + int nbCharParsed; + printf("Entering AssocBis\n"); + + nbCharParsed = parse_AssocBis1(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + nbCharParsed = parse_AssocBis2(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + return -1; +} + +int parse_KeyVal(char* word, int pos) { + int nbCharParsed; + printf("Entering KeyVal\n"); + + nbCharParsed = parse_KeyVal1(word, pos); + if (nbCharParsed != -1) { + return nbCharParsed; + } + + return -1; +} + +int main(int argc, char* argv[]) { + char* word; + if (argc >= 2) + word = argv[1]; + else + word = ""; + int value = parse_S(word, 0); + printf("%d\n", value); + if (value == strlen(word) + 1) { + printf("OK\n"); + } else { + printf("KO\n"); + } +} +