Initial commit

This commit is contained in:
Arkaprabha Chakraborty
2024-01-20 07:34:29 +05:30
commit 49617b7822
5 changed files with 599 additions and 0 deletions

236
.clang-format Normal file
View File

@@ -0,0 +1,236 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveShortCaseStatements:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCaseColons: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Never
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: false
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
KeepEmptyLinesAtEOF: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: BinPack
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
PPIndentWidth: -1
QualifierAlignment: Leave
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParens: Never
SpacesInParensOptions:
InCStyleCasts: false
InConditionalStatements: false
InEmptyParentheses: false
Other: false
SpacesInSquareBrackets: false
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseTab: Never
VerilogBreakBetweenInstancePorts: true
WhitespaceSensitiveMacros:
- BOOST_PP_STRINGIZE
- CF_SWIFT_NAME
- NS_SWIFT_NAME
- PP_STRINGIZE
- STRINGIZE
...

32
.gitignore vendored Normal file
View File

@@ -0,0 +1,32 @@
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app

18
Makefile Normal file
View File

@@ -0,0 +1,18 @@
CXX = clang++
CXXFLAGS = -std=c++17 -Wall -Wextra
SOURCE = main.cxx
EXECUTABLE = ast.out
# Build target
all: $(EXECUTABLE)
# Rule to build the executable
$(EXECUTABLE): $(SOURCE)
@$(CXX) $(CXXFLAGS) -o $@ $<
run: $(EXECUTABLE)
@./$(EXECUTABLE)
# Clean up generated files
clean:
@rm -f $(EXECUTABLE)

89
README.md Normal file
View File

@@ -0,0 +1,89 @@
# Arithmetic AST & Evaluator
This C++ program provides a simple mathematical expression evaluator using an Abstract Syntax Tree (AST). The AST is constructed from different types of nodes, such as constants, identifiers, unary operators (plus and minus), and binary operators (addition, subtraction, multiplication, division, and power). The program allows for the evaluation of mathematical expressions involving variables and basic operations.
## Table of Contents
- [Introduction](#introduction)
- [Usage](#usage)
- [ASTNode Hierarchy](#astnode-hierarchy)
- [Example Usage](#example-usage)
- [Error Handling](#error-handling)
- [Variable Assignment](#variable-assignment)
- [Cleaning Variables](#cleaning-variables)
- [Contributing](#contributing)
- [License](#license)
## Introduction
The program defines a hierarchy of classes representing different types of AST nodes. Each node has a specific type and implements the `evaluate` method to perform the corresponding mathematical operation. The AST is utilized to evaluate complex mathematical expressions composed of constants, variables, and various operators.
## Usage
To use the expression evaluator, follow these steps:
1. **Variable Assignment:** Use the `Identifier::setVariable` method to assign values to variables.
2. **Expression Creation:** Construct the expression using the provided AST nodes and operators.
3. **Evaluation:** Call the `evaluate` method on the root node of the expression.
4. **Cleanup:** Release the allocated memory using `delete` and, if needed, clear assigned variables.
## ASTNode Hierarchy
The ASTNode hierarchy consists of the following classes:
- `Constant`: Represents a constant numerical value.
- `Identifier`: Represents a variable identified by a string.
- `Unary`: Abstract base class for unary operators.
- `UnaryPlus`: Represents the unary plus operator.
- `UnaryMinus`: Represents the unary minus operator.
- `Binary`: Abstract base class for binary operators.
- `Add`: Represents the addition operator.
- `Subtract`: Represents the subtraction operator.
- `Multiply`: Represents the multiplication operator.
- `Divide`: Represents the division operator.
- `Power`: Represents the power operator.
## Example Usage
Execute the command below in a shell to run the example.
```bash
$ make run
```
In this example, the expression `-(Num1) + 2 * (4 - Num2)` is evaluated with variables `Num1` and `Num2` assigned specific values.
```cpp
// Example usage
Identifier::setVariable("Num1", 3.0);
Identifier::setVariable("Num2", 7.0);
ASTNode *expression = new Add(new UnaryMinus(new Identifier("Num1")),
new Multiply(new Constant(2), new Subtract(new Constant(4), new Identifier("Num2"))));
double result = expression->evaluate();
std::cout << "Result: " << result << std::endl;
delete expression; // Free the memory
Identifier::clearVariables();
```
## Error Handling
The program includes basic error handling. For example, attempting to divide by zero will result in an error message printed to `std::cerr`, and the division operation will return infinity to indicate an error.
## Variable Assignment
Variables are assigned values using the `Identifier::setVariable` method. If an undefined variable is encountered during evaluation, an error message is printed, and the default value of `0.0` is returned.
## Cleaning Variables
To clean up assigned variables and release allocated memory, use the `Identifier::clearVariables` method. This ensures a clean slate for subsequent expressions.
## Contributing
Feel free to contribute to the project by opening issues, suggesting improvements, or submitting pull requests. Your contributions are highly appreciated.
## License
This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.

224
main.cxx Normal file
View File

@@ -0,0 +1,224 @@
#include <cmath>
#include <iostream>
#include <stdexcept>
#include <unordered_map>
// Abstract Syntax Tree (AST) Node base class
class ASTNode {
public:
// Enumeration defining different types of AST nodes.
enum class Type {
Constant, // Represents a constant numerical value.
Identifier, // Represents a variable identifier.
Unary, // Represents a unary operation.
UnaryPlus, // Represents a unary plus operation.
UnaryMinus, // Represents a unary minus operation.
Binary, // Represents a binary operation.
Add, // Represents an addition operation.
Subtract, // Represents a subtraction operation.
Multiply, // Represents a multiplication operation.
Divide, // Represents a division operation.
Power // Represents a power/exponentiation operation.
};
// Virtual functions for evaluation and type retrieval.
virtual double evaluate() const = 0;
virtual ASTNode::Type getType() const = 0;
virtual ~ASTNode() {}
};
// Constant Node class
class Constant : public ASTNode {
private:
double value;
public:
// Constructor for Constant node.
explicit Constant(double val) : value(val) {}
// Implementation of getType for Constant node.
ASTNode::Type getType() const override { return ASTNode::Type::Constant; }
// Implementation of evaluate for Constant node.
double evaluate() const override { return value; }
};
// Identifier Node class
class Identifier : public ASTNode {
private:
std::string identifier;
static std::unordered_map<std::string, double> variableTable;
public:
// Constructor for Identifier node.
explicit Identifier(const std::string &id) : identifier(id) {}
// Implementation of getType for Identifier node.
ASTNode::Type getType() const override { return ASTNode::Type::Identifier; }
// Implementation of evaluate for Identifier node.
double evaluate() const override {
try {
return variableTable.at(identifier);
} catch (const std::out_of_range) {
std::cerr << "Error: Undefined variable '" << identifier << ".'\n";
return 0.0;
}
}
// Static function to set a variable in the variableTable.
static void setVariable(const std::string &id, double value) { variableTable[id] = value; }
// Static function to clear all variables in the variableTable.
static void clearVariables() { variableTable.clear(); }
};
// Unary Node base class
class Unary : public ASTNode {
protected:
const ASTNode *operand;
public:
// Constructor for Unary node.
explicit Unary(const ASTNode *operand) : operand(operand) {}
// Implementation of getType for Unary node.
ASTNode::Type getType() const override { return ASTNode::Type::Unary; }
// Virtual destructor for Unary node.
virtual ~Unary() { delete operand; }
};
// UnaryPlus Node class
class UnaryPlus : public Unary {
public:
using Unary::Unary;
// Implementation of getType for UnaryPlus node.
ASTNode::Type getType() const override { return ASTNode::Type::UnaryPlus; }
// Implementation of evaluate for UnaryPlus node.
double evaluate() const override { return operand->evaluate(); }
};
// UnaryMinus Node class
class UnaryMinus : public Unary {
public:
using Unary::Unary;
// Implementation of getType for UnaryMinus node.
ASTNode::Type getType() const override { return ASTNode::Type::UnaryMinus; }
// Implementation of evaluate for UnaryMinus node.
double evaluate() const override { return -operand->evaluate(); }
};
// Binary Node base class
class Binary : public ASTNode {
protected:
const ASTNode *left;
const ASTNode *right;
public:
// Constructor for Binary node.
Binary(const ASTNode *left, const ASTNode *right) : left(left), right(right) {}
// Implementation of getType for Binary node.
ASTNode::Type getType() const override { return ASTNode::Type::Binary; }
// Virtual destructor for Binary node.
virtual ~Binary() {
delete left;
delete right;
}
};
// Add Node class
class Add : public Binary {
public:
using Binary::Binary;
// Implementation of getType for Add node.
ASTNode::Type getType() const override { return ASTNode::Type::Add; }
// Implementation of evaluate for Add node.
double evaluate() const override { return left->evaluate() + right->evaluate(); }
};
// Subtract Node class
class Subtract : public Binary {
public:
using Binary::Binary;
// Implementation of getType for Subtract node.
ASTNode::Type getType() const override { return ASTNode::Type::Subtract; }
// Implementation of evaluate for Subtract node.
double evaluate() const override { return left->evaluate() - right->evaluate(); }
};
// Multiply Node class
class Multiply : public Binary {
public:
using Binary::Binary;
// Implementation of getType for Multiply node.
ASTNode::Type getType() const override { return ASTNode::Type::Multiply; }
// Implementation of evaluate for Multiply node.
double evaluate() const override { return left->evaluate() * right->evaluate(); }
};
// Divide Node class
class Divide : public Binary {
public:
using Binary::Binary;
// Implementation of getType for Divide node.
ASTNode::Type getType() const override { return ASTNode::Type::Divide; }
// Implementation of evaluate for Divide node.
double evaluate() const override {
if (right->evaluate() == 0) {
std::cerr << "Error: Division by zero.\n";
return INFINITY;
}
return left->evaluate() / right->evaluate();
}
};
// Power Node class
class Power : public Binary {
public:
using Binary::Binary;
// Implementation of getType for Power node.
ASTNode::Type getType() const override { return ASTNode::Type::Power; }
// Implementation of evaluate for Power node.
double evaluate() const override { return std::pow(left->evaluate(), right->evaluate()); }
};
// Static initialization of variableTable in Identifier class.
std::unordered_map<std::string, double> Identifier::variableTable;
// Main function
int main() {
// Setting variables in the variableTable.
Identifier::setVariable("Num1", 3.0);
Identifier::setVariable("Num2", 7.0);
// Creating an expression tree.
ASTNode *expression = new Add(new UnaryMinus(new Identifier("Num1")),
new Multiply(new Constant(2), new Subtract(new Constant(4), new Identifier("Num2"))));
// Evaluating the expression and printing the result.
double result = expression->evaluate();
std::cout << "Result: " << result << std::endl;
// Deleting the expression and clearing variables.
delete expression;
Identifier::clearVariables();
return 0;
}