-
Notifications
You must be signed in to change notification settings - Fork 0
Interactive mode for working with the parse tree #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 16 commits
531d1f9
ee27bff
0d36fbd
378356e
918278c
66ff87e
8780d7e
e1c6faa
41a7a49
2986452
42479cd
761ccf5
0215130
9e88d89
014c909
1b46e0f
fe132ff
51a7b22
d1eb0d2
30f11f0
48984d1
2216d55
4c9585b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| | ||
| Microsoft Visual Studio Solution File, Format Version 12.00 | ||
| # Visual Studio Version 16 | ||
| VisualStudioVersion = 16.0.31410.357 | ||
| MinimumVisualStudioVersion = 10.0.40219.1 | ||
| Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ParsingTree", "ParsingTree\ParsingTree.vcxproj", "{AEA90FA6-F26C-4B74-9508-AD999204C4FA}" | ||
| EndProject | ||
| Global | ||
| GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||
| Debug|x64 = Debug|x64 | ||
| Debug|x86 = Debug|x86 | ||
| Release|x64 = Release|x64 | ||
| Release|x86 = Release|x86 | ||
| EndGlobalSection | ||
| GlobalSection(ProjectConfigurationPlatforms) = postSolution | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Debug|x64.ActiveCfg = Debug|x64 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Debug|x64.Build.0 = Debug|x64 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Debug|x86.ActiveCfg = Debug|Win32 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Debug|x86.Build.0 = Debug|Win32 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Release|x64.ActiveCfg = Release|x64 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Release|x64.Build.0 = Release|x64 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Release|x86.ActiveCfg = Release|Win32 | ||
| {AEA90FA6-F26C-4B74-9508-AD999204C4FA}.Release|x86.Build.0 = Release|Win32 | ||
| EndGlobalSection | ||
| GlobalSection(SolutionProperties) = preSolution | ||
| HideSolutionNode = FALSE | ||
| EndGlobalSection | ||
| GlobalSection(ExtensibilityGlobals) = postSolution | ||
| SolutionGuid = {65329AED-E765-4723-93C5-B2671094F619} | ||
| EndGlobalSection | ||
| EndGlobal |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| #include "TestParsingTree.h" | ||
|
|
||
| int main() | ||
| { | ||
| if (!testFindAnswer()) | ||
| { | ||
| return -1; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,224 @@ | ||
| #include "ParsingTree.h" | ||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
| #include <stdbool.h> | ||
|
|
||
| typedef enum VisitedNode | ||
| { | ||
| nodeVisited, | ||
| nodeNotVisited | ||
| } VisitedNode; | ||
|
|
||
| typedef struct Node | ||
| { | ||
| struct Node* leftSon; | ||
| struct Node* rightSon; | ||
| struct Node* parent; | ||
| char symbol; | ||
| int expressionValues; | ||
| VisitedNode isVisitedNode; | ||
| } Node; | ||
|
|
||
| typedef enum Direction | ||
| { | ||
| left, | ||
| right | ||
| } Direction; | ||
|
|
||
| Node* createTree() | ||
| { | ||
| return NULL; | ||
| } | ||
|
|
||
| void deleteTreeRecursive(Node* root) | ||
| { | ||
| if (root == NULL) | ||
| { | ||
| return; | ||
| } | ||
| deleteTreeRecursive(root->leftSon); | ||
| deleteTreeRecursive(root->rightSon); | ||
| free(root); | ||
| } | ||
|
|
||
| void deleteTree(Node** root) | ||
| { | ||
| deleteTreeRecursive(*root); | ||
| *root = NULL; | ||
| } | ||
|
|
||
| Node* returnHead(Node* root) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. У дерева нет головы, у него есть корень. Но если бы мы назвали эту функцию returnRoot, было бы не очень, потому что параметр у неё называется root. Это плохо. |
||
| { | ||
| if (root == NULL) | ||
| { | ||
| return root; | ||
| } | ||
| while (root->parent != NULL) | ||
| { | ||
| root = root->parent; | ||
| } | ||
| return root; | ||
| } | ||
|
|
||
| bool isOperator(char symbol) | ||
| { | ||
| return symbol == '+' || symbol == '-' | ||
| || symbol == '*' || symbol == '/'; | ||
| } | ||
|
|
||
| void attach(Node* parent, Node* child, Direction direction) | ||
| { | ||
| if (parent == NULL) | ||
| { | ||
| return; | ||
| } | ||
| if (direction == left) | ||
| { | ||
| parent->leftSon = child; | ||
| } | ||
| else | ||
| { | ||
| parent->rightSon = child; | ||
| } | ||
| if (child != NULL) | ||
| { | ||
| child->parent = parent; | ||
| } | ||
| } | ||
|
|
||
| Node* createNode(char symbol) | ||
| { | ||
| Node* newRoot = (Node*)calloc(1, sizeof(Node)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Вот, например, тут — это же не корень, это узел |
||
| if (newRoot == NULL) | ||
| { | ||
| return NULL; | ||
| } | ||
| newRoot->symbol = symbol; | ||
| newRoot->isVisitedNode = isOperator(symbol) ? nodeNotVisited : nodeVisited; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Эта строка — самое нелогичное, что я видел сегодня. Если оператор, то узел не посещён, иначе посещён, что? |
||
| newRoot->expressionValues = isOperator(symbol) ? 0 : symbol - '0'; | ||
| return newRoot; | ||
| } | ||
|
|
||
| Node* addNode(const char* array, int* counter, Node* node) | ||
| { | ||
| if (*counter > 0 && node == NULL) | ||
| { | ||
| return NULL; | ||
| } | ||
| while (array[*counter] == '(' || array[*counter] == ')' | ||
| || array[*counter] == ' ') | ||
| { | ||
| (*counter)++; | ||
| } | ||
| if (isOperator(array[*counter])) | ||
| { | ||
| Node* temporary = createNode(array[*counter]); | ||
| if (temporary == NULL) | ||
| { | ||
| node = returnHead(node); | ||
| deleteTree(&node); | ||
| return NULL; | ||
| } | ||
| Node* operator = temporary; | ||
| (*counter)++; | ||
| attach(operator, addNode(array, counter, operator), left); | ||
| attach(operator, addNode(array, counter, operator), right); | ||
| return operator; | ||
| } | ||
| else | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Тут можно уже без else, выше ветка на return заканчивается. Это сэкономит уровень отступа. |
||
| { | ||
| Node* operand = createNode(array[*counter]); | ||
| if (operand == NULL) | ||
| { | ||
| node = returnHead(node); | ||
| deleteTree(&node); | ||
| return NULL; | ||
| } | ||
| (*counter)++; | ||
| return operand; | ||
| } | ||
| } | ||
|
|
||
| Node* buildTree(const char* array) | ||
| { | ||
| int counter = 0; | ||
| Node* node = NULL; | ||
| return addNode(array, &counter, node); | ||
| } | ||
|
|
||
| void restoreField(Node* root) | ||
| { | ||
| if (root == NULL) | ||
| { | ||
| return; | ||
| } | ||
| restoreField(root->leftSon); | ||
| restoreField(root->rightSon); | ||
| root->isVisitedNode = isOperator(root->symbol) ? nodeNotVisited : nodeVisited; | ||
| } | ||
|
|
||
| int findAnswer(Node* root, int* error) | ||
| { | ||
| if (*error != 0) | ||
| { | ||
| return 0; | ||
| } | ||
| if (root == NULL) | ||
| { | ||
| *error = 1; | ||
| return 0; | ||
| } | ||
| if (root->parent == NULL && root->rightSon == NULL && root->leftSon == NULL) | ||
| { | ||
| return root->expressionValues; | ||
| } | ||
| if (root->leftSon != NULL && root->rightSon != NULL && root->rightSon->isVisitedNode == nodeVisited && root->leftSon->isVisitedNode == nodeVisited && root->isVisitedNode == nodeNotVisited) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Очень длинная строчка, надо перенести на несколько |
||
| { | ||
| root->isVisitedNode = nodeVisited; | ||
| if (root->symbol == '+') | ||
| { | ||
| root->expressionValues = root->leftSon->expressionValues + root->rightSon->expressionValues; | ||
| } | ||
| if (root->symbol == '-') | ||
| { | ||
| root->expressionValues = root->leftSon->expressionValues - root->rightSon->expressionValues; | ||
| } | ||
| if (root->symbol == '*') | ||
| { | ||
| root->expressionValues = root->leftSon->expressionValues * root->rightSon->expressionValues; | ||
| } | ||
| if (root->symbol == '/') | ||
| { | ||
| root->expressionValues = root->leftSon->expressionValues / root->rightSon->expressionValues; | ||
| } | ||
| if (root->parent != NULL) | ||
| { | ||
| return findAnswer(root->parent, error); | ||
| } | ||
| else | ||
| { | ||
| restoreField(root); | ||
| return root->expressionValues; | ||
| } | ||
| } | ||
| else if (root->leftSon != NULL && isOperator(root->leftSon->symbol) && root->leftSon->isVisitedNode == nodeNotVisited) | ||
| { | ||
| return findAnswer(root->leftSon, error); | ||
| } | ||
| else if (root->rightSon != NULL && isOperator(root->rightSon->symbol) && root->rightSon->isVisitedNode == nodeNotVisited) | ||
| { | ||
| return findAnswer(root->rightSon, error); | ||
| } | ||
| return findAnswer(root, error); | ||
| } | ||
|
|
||
| void printTree(Node* root) | ||
| { | ||
| if (root == NULL) | ||
| { | ||
| return; | ||
| } | ||
| printTree(root->leftSon); | ||
| printTree(root->rightSon); | ||
| printf("%c ", root->symbol); | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лучше было выводить в строку, потому что иначе эту функцию не протестировать, но ладно, пусть так |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| #pragma once | ||
|
|
||
| // Structure representing a tree | ||
| typedef struct Node Node; | ||
|
|
||
| // Function for deleting a tree | ||
| void deleteTree(Node** root); | ||
|
|
||
| // Function for building a tree | ||
| Node* buildTree(const char* array); | ||
|
|
||
| // Function for calculating the value of an expression | ||
| int findAnswer(Node* root, int* error); | ||
|
|
||
| // Function for tree output | ||
| void printTree(Node* root); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
На самом деле, был ли узел посещён — это состояние обхода, а не свойство узла, потому что если мы два обхода параллельно запустим, всё сломается. Да даже если два последовательно, сбросится ли статус isVisitedNode? Но если хотите так, то можно не править.