develop #2

Merged
cromer merged 4 commits from develop into master 2022-10-25 17:10:17 -03:00
25 changed files with 1246 additions and 0 deletions

220
.clang-format Normal file
View File

@ -0,0 +1,220 @@
---
AccessModifierOffset: 0
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: Always
IndentAccessModifiers: true
TabWidth: 4
UseTab: Never
UseCRLF: false
Language: Cpp
IndentWidth: 4
AlignAfterOpenBracket: DontAlign
AlignArrayOfStructures: Left
AlignConsecutiveAssignments: AcrossComments
AlignConsecutiveBitFields: AcrossComments
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossComments
AlignEscapedNewlines: Left
AlignOperands: AlignAfterOperator
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: false
AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: None
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: No
BinPackArguments: false
BinPackParameters: false
AttributeMacros:
- __capability
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: true
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: true
BeforeWhile: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBraces: Custom
BreakAfterJavaFieldAnnotations: false
BreakBeforeBinaryOperators: All
BreakBeforeConceptDeclarations: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakInheritanceList: AfterColon
BreakStringLiterals: false
ColumnLimit: 80
CommentPragmas: "^ IWYU pragma:"
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Regroup
IncludeCategories:
- Regex: ^<ext/.*\.h>
Priority: 2
CaseSensitive: false
SortPriority: 0
- Regex: ^<.*\.h>
Priority: 1
CaseSensitive: false
SortPriority: 0
- Regex: ^<.*
Priority: 2
CaseSensitive: false
SortPriority: 0
- Regex: .*
Priority: 0
CaseSensitive: false
SortPriority: 0
IncludeIsMainRegex: ([-_](test|unittest))?$
IncludeIsMainSourceRegex: ""
IndentCaseBlocks: true
IndentCaseLabels: true
IndentExternBlock: Indent
IndentGotoLabels: false
IndentPPDirectives: BeforeHash
IndentRequires: true
IndentWrappedFunctionNames: true
InsertTrailingCommas: None
JavaScriptQuotes: Double
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: OuterScope
MacroBlockBegin: ""
MacroBlockEnd: ""
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 4
ObjCBreakBeforeNestedBlockParam: false
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PPIndentWidth: 4
PackConstructorInitializers: Never
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
QualifierAlignment: Left
RawStringFormats:
- Language: Cpp
BasedOnStyle: google
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- c++
- C++
CanonicalDelimiter: ""
- Language: TextProto
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
- ParseTestProto
- ParsePartialTestProto
BasedOnStyle: google
Delimiters:
- pb
- PB
- proto
- PROTO
CanonicalDelimiter: pb
ReferenceAlignment: Left
ReflowComments: false
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Always
ShortNamespaceLines: 0
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: true
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: true
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Custom
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: false
AfterFunctionDeclarationName: false
AfterFunctionDefinitionName: false
AfterIfMacros: false
AfterOverloadedOperator: true
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: 1
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME

2
.gitignore vendored
View File

@ -1 +1,3 @@
*.code-workspace
.vscode
builddir

33
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,33 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-case-conflict
- id: mixed-line-ending
- id: check-added-large-files
- id: check-executables-have-shebangs
- id: check-shebang-scripts-are-executable
- id: detect-private-key
- id: no-commit-to-branch
args: [--branch, master, --branch, develop]
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v14.0.6
hooks:
- id: clang-format
types_or: [c++, c]
args: ["-style=file"]
- repo: https://github.com/Lucas-C/pre-commit-hooks
rev: v1.3.1
hooks:
- id: forbid-crlf
- id: forbid-tabs
#- repo: https://github.com/pocc/pre-commit-hooks
# rev: v1.3.5
# hooks:
# - id: clang-tidy
# args: [-checks=clang-diagnostic-return-type]
# files: src/.*\.cpp

20
compile_commands.json Normal file
View File

@ -0,0 +1,20 @@
[
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "clang++ -Isrc/obelisk.p -Isrc -I../src -fcolor-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -O0 -g -MD -MQ src/obelisk.p/obelisk.cpp.o -MF src/obelisk.p/obelisk.cpp.o.d -o src/obelisk.p/obelisk.cpp.o -c ../src/obelisk.cpp",
"file": "../src/obelisk.cpp",
"output": "src/obelisk.p/obelisk.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "clang++ -Isrc/obelisk.p -Isrc -I../src -fcolor-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -O0 -g -MD -MQ src/obelisk.p/lexer.cpp.o -MF src/obelisk.p/lexer.cpp.o.d -o src/obelisk.p/lexer.cpp.o -c ../src/lexer.cpp",
"file": "../src/lexer.cpp",
"output": "src/obelisk.p/lexer.cpp.o"
},
{
"directory": "/mnt/data/ubb/courses/proyecto-titulo/obelisk/builddir",
"command": "clang++ -Isrc/obelisk.p -Isrc -I../src -fcolor-diagnostics -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -Wextra -Wpedantic -std=c++17 -O0 -g -MD -MQ src/obelisk.p/parser.cpp.o -MF src/obelisk.p/parser.cpp.o.d -o src/obelisk.p/parser.cpp.o -c ../src/parser.cpp",
"file": "../src/parser.cpp",
"output": "src/obelisk.p/parser.cpp.o"
}
]

11
meson.build Normal file
View File

@ -0,0 +1,11 @@
project('obelisk',
'cpp',
version : '1.0.0',
default_options : [
'warning_level=3',
'c_std=c17',
'cpp_std=c++17'
]
)
subdir('src')

View File

@ -0,0 +1,34 @@
#ifndef OBELISK_AST_CALL_EXPRESSION_AST_H
#define OBELISK_AST_CALL_EXPRESSION_AST_H
#include "ast/expression_ast.h"
#include <memory>
#include <string>
#include <vector>
namespace obelisk
{
class CallExpressionAST : public ExpressionAST
{
private:
std::string callee_;
std::vector<std::unique_ptr<ExpressionAST>> args_;
std::string getCallee();
void setCallee(std::string callee);
std::vector<std::unique_ptr<ExpressionAST>> getArgs();
void setArgs(std::vector<std::unique_ptr<ExpressionAST>> args);
public:
CallExpressionAST(const std::string &callee,
std::vector<std::unique_ptr<ExpressionAST>> args) :
callee_(callee),
args_(std::move(args))
{
}
};
} // namespace obelisk
#endif

13
src/ast/expression_ast.h Normal file
View File

@ -0,0 +1,13 @@
#ifndef OBELISK_AST_EXPRESSION_AST_H
#define OBELISK_AST_EXPRESSION_AST_H
namespace obelisk
{
class ExpressionAST
{
public:
virtual ~ExpressionAST() = default;
};
} // namespace obelisk
#endif

30
src/ast/function_ast.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef OBELISK_AST_FUNCTION_AST_H
#define OBELISK_AST_FUNCTION_AST_H
#include "ast/expression_ast.h"
#include "ast/prototype_ast.h"
#include <memory>
namespace obelisk
{
class FunctionAST
{
private:
std::unique_ptr<PrototypeAST> prototype_;
std::unique_ptr<ExpressionAST> body_;
std::unique_ptr<PrototypeAST> getPrototype();
void setPrototype(std::unique_ptr<PrototypeAST> prototype);
public:
FunctionAST(std::unique_ptr<PrototypeAST> prototype,
std::unique_ptr<ExpressionAST> body) :
prototype_(std::move(prototype)),
body_(std::move(body))
{
}
};
} // namespace obelisk
#endif

8
src/ast/meson.build Normal file
View File

@ -0,0 +1,8 @@
obelisk_ast_sources = files(
'call_expression_ast.h',
'expression_ast.h',
'function_ast.h',
'number_expression_ast.h',
'prototype_ast.h',
'variable_expression_ast.h'
)

View File

@ -0,0 +1,24 @@
#ifndef OBELISK_AST_NUMBER_EXPRESSION_AST_H
#define OBELISK_AST_NUMBER_EXPRESSION_AST_H
#include "ast/expression_ast.h"
namespace obelisk
{
class NumberExpressionAST : public ExpressionAST
{
private:
double number_;
double getNumber();
void setNumber(double number);
public:
NumberExpressionAST(double number) :
number_(number)
{
}
};
} // namespace obelisk
#endif

34
src/ast/prototype_ast.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef OBELISK_AST_PROTOTYPE_AST_H
#define OBELISK_AST_PROTOTYPE_AST_H
#include <string>
#include <vector>
namespace obelisk
{
class PrototypeAST
{
private:
std::string name_;
std::vector<std::string> args_;
void setName(const std::string& name);
std::vector<std::string> getArgs();
void setArgs(std::vector<std::string> args);
public:
PrototypeAST(const std::string& name,
std::vector<std::string> args) :
name_(name),
args_(std::move(args))
{
}
const std::string& getName() const
{
return name_;
}
};
} //namespace obelisk
#endif

View File

@ -0,0 +1,25 @@
#ifndef OBELISK_AST_VARIABLE_EXPRESSION_AST_H
#define OBELISK_AST_VARIABLE_EXPRESSION_AST_H
#include "ast/expression_ast.h"
#include <string>
namespace obelisk
{
class VariableExpressionAST : public ExpressionAST
{
private:
std::string name_;
std::string getName();
void setName(const std::string name);
public:
VariableExpressionAST(const std::string &name) :
name_(name)
{
}
};
} //namespace obelisk
#endif

59
src/knowledge_base.cpp Normal file
View File

@ -0,0 +1,59 @@
#include "knowledge_base.h"
#include <iostream>
const std::string obelisk::Sql::create_facts_table
= "CREATE TABLE fact (id INT PRIMARY KEY NOT NULL);";
obelisk::KnowledgeBase::KnowledgeBase(const char* filename)
{
KnowledgeBase(filename, DEFAULT_FLAGS);
}
obelisk::KnowledgeBase::KnowledgeBase(const char* filename, int flags)
{
filename_ = std::move(filename);
flags_ = std::move(flags);
auto result = sqlite3_open_v2(filename, &dbConnection_, flags, NULL);
if (result != SQLITE_OK)
{
logSqliteError(result);
}
char* tmp;
result = sqlite3_exec(dbConnection_,
obelisk::Sql::create_facts_table.c_str(),
NULL,
NULL,
&tmp);
if (tmp)
{
std::string errmsg(tmp);
throw obelisk::KnowledgeBaseException(errmsg);
}
}
obelisk::KnowledgeBase::~KnowledgeBase()
{
sqlite3_close_v2(dbConnection_);
}
// TODO: log files?
void obelisk::KnowledgeBase::logSqliteError(int result)
{
std::cout << sqlite3_errstr(result) << std::endl;
}
void obelisk::KnowledgeBase::getFloat(float* result1,
float* result2,
double var)
{
*result1 = (float) var;
*result2 = (float) (var - (double) *result1);
}
void obelisk::KnowledgeBase::getDouble(double* result, float var1, float var2)
{
*result = (double) ((double) var2 + (double) var1);
}

61
src/knowledge_base.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef OBELISK_KNOWLEDGE_BASE_H
#define OBELISK_KNOWLEDGE_BASE_H
#include <sqlite3.h>
#include <iostream>
#include <string>
namespace obelisk
{
class KnowledgeBase
{
private:
const int DEFAULT_FLAGS
= SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
const char* filename_;
sqlite3* dbConnection_;
int flags_;
void logSqliteError(int result);
public:
KnowledgeBase(const char* filename);
KnowledgeBase(const char* filename, int flags);
~KnowledgeBase();
template<typename T, typename U>
int addFacts(std::string verb, T leftEntities, U rightEntities);
// TODO: add parameter for fact
template<typename T, typename U>
int addRules(std::string verb, T leftEntities, U rightEntities);
template<typename T, typename U> int addActions();
void getDouble(double* result, float var1, float var2);
void getFloat(float* result1, float* result2, double var);
};
class Sql
{
public:
static const std::string create_facts_table;
};
class KnowledgeBaseException : public std::exception
{
private:
std::string errorMessage_;
public:
KnowledgeBaseException(std::string errorMessage) :
errorMessage_(errorMessage)
{
}
const char* what() const noexcept
{
return errorMessage_.c_str();
}
};
} // namespace obelisk
#endif

121
src/lexer.cpp Normal file
View File

@ -0,0 +1,121 @@
#include "lexer.h"
#include <iostream>
int obelisk::Lexer::getToken()
{
static int lastChar = ' ';
while (isspace(lastChar))
{
lastChar = getchar();
}
if (isalpha(lastChar))
{
eraseIdentifier();
appendIdentifier(lastChar);
while (isalnum((lastChar = getchar())))
{
appendIdentifier(lastChar);
}
if (getIdentifier() == "def")
{
return Token::kTokenDef;
}
if (getIdentifier() == "extern")
{
return kTokenExtern;
}
return kTokenIdentifier;
}
if (isdigit(lastChar) || lastChar == '.')
{
std::string numberStr;
do
{
numberStr += lastChar;
lastChar = getchar();
}
while (isdigit(lastChar) || lastChar == '.');
setNumberValue(strtod(numberStr.c_str(), nullptr));
return kTokenNumber;
}
if (lastChar == '#')
{
commentLine(&lastChar);
if (lastChar != EOF)
{
return getToken();
}
}
else if (lastChar == '/')
{
lastChar = getchar();
if (lastChar == '/')
{
commentLine(&lastChar);
if (lastChar != EOF)
{
return getToken();
}
}
}
if (lastChar == EOF)
{
return kTokenEof;
}
int thisChar = lastChar;
lastChar = getchar();
return thisChar;
}
void obelisk::Lexer::commentLine(int* lastChar)
{
do
{
*lastChar = getchar();
}
while (*lastChar != EOF && *lastChar != '\n' && *lastChar != '\r');
}
std::string obelisk::Lexer::getIdentifier()
{
return identifier_;
}
void obelisk::Lexer::setIdentifier(const std::string identifier)
{
identifier_ = identifier;
}
void obelisk::Lexer::eraseIdentifier()
{
identifier_ = "";
}
void obelisk::Lexer::appendIdentifier(int lastChar)
{
identifier_ += lastChar;
}
double obelisk::Lexer::getNumberValue()
{
return numberValue_;
}
void obelisk::Lexer::setNumberValue(double numberValue)
{
numberValue_ = numberValue;
}

46
src/lexer.h Normal file
View File

@ -0,0 +1,46 @@
#ifndef OBELISK_LEXER_H
#define OBELISK_LEXER_H
#include <string>
namespace obelisk
{
class Lexer
{
private:
std::string identifier_;
double numberValue_;
void setIdentifier(const std::string identifier);
void eraseIdentifier();
void appendIdentifier(int lastChar);
void setNumberValue(double numberValue);
void commentLine(int* lastChar);
public:
enum Token
{
kTokenInvalid = -1,
kTokenEof = -2,
// commands
kTokenFact = -3,
kTokenRule = -4,
kTokenDef = -5,
kTokenExtern = -6,
// primary
kTokenIdentifier = -7,
kTokenNumber = -8,
kTokenString = -9
};
int getToken();
std::string getIdentifier();
double getNumberValue();
};
} // namespace obelisk
#endif

17
src/meson.build Normal file
View File

@ -0,0 +1,17 @@
obelisk_sources = files(
'obelisk.cpp',
'lexer.cpp',
'parser.cpp',
'knowledge_base.cpp'
)
sqlite3 = dependency('sqlite3')
subdir('ast')
obelisk_sources += obelisk_ast_sources
executable('obelisk',
obelisk_sources,
dependencies : [sqlite3],
install : true
)

30
src/models/entity.cpp Normal file
View File

@ -0,0 +1,30 @@
#include "models/entity.h"
obelisk::Entity::Entity()
{
}
obelisk::Entity::Entity(std::string name)
{
name = name;
}
int obelisk::Entity::getId()
{
return id_;
}
void obelisk::Entity::setId(int id)
{
id_ = id;
}
std::string obelisk::Entity::getName()
{
return name_;
}
void obelisk::Entity::setName(std::string name)
{
name_ = name_;
}

26
src/models/entity.h Normal file
View File

@ -0,0 +1,26 @@
#ifndef OBELISK_MODELS_ENTITY_H
#define OBELISK_MODELS_ENTITY_H
#include <string>
namespace obelisk
{
class Entity
{
private:
int id_;
std::string name_;
public:
Entity();
Entity(std::string name);
int getId();
void setId(int id);
std::string getName();
void setName(std::string name);
};
} // namespace obelisk
#endif

36
src/models/verb.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "models/verb.h"
obelisk::Verb::Verb()
{
}
obelisk::Verb::Verb(std::string verb)
{
verb_ = verb;
}
obelisk::Verb::Verb(int id, std::string verb)
{
id_ = id;
verb_ = verb;
}
int obelisk::Verb::getId()
{
return id_;
}
void obelisk::Verb::setId(int id)
{
id_ = id;
}
std::string obelisk::Verb::getVerb()
{
return verb_;
}
void obelisk::Verb::setVerb(std::string verb)
{
verb_ = verb;
}

27
src/models/verb.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef OBELISK_MODELS_VERB_H
#define OBELISK_MODELS_VERB_H
#include <string>
namespace obelisk
{
class Verb
{
private:
int id_;
std::string verb_;
public:
Verb();
Verb(std::string verb);
Verb(int id, std::string verb);
int getId();
void setId(int id);
std::string getVerb();
void setVerb(std::string verb);
};
} // namespace obelisk
#endif

90
src/obelisk.cpp Normal file
View File

@ -0,0 +1,90 @@
#include "knowledge_base.h"
#include "lexer.h"
#include "obelisk.h"
#include "parser.h"
#include <iomanip>
#include <iostream>
#include <limits>
static void mainLoop()
{
obelisk::Parser* parser = new obelisk::Parser();
// Prime the first token.
fprintf(stderr, "ready> ");
parser->getNextToken();
while (true)
{
fprintf(stderr, "ready> ");
switch (parser->getCurrentToken())
{
case obelisk::Lexer::kTokenEof :
return;
case obelisk::Lexer::kTokenInvalid :
std::cerr << "Invalid token!\n";
parser->getNextToken();
return;
case ';' : // ignore top-level semicolons.
std::cout << "Identifier: "
<< parser->getLexer()->getIdentifier() << std::endl;
std::cout << "Num: " << parser->getLexer()->getNumberValue()
<< std::endl;
parser->getNextToken();
break;
default :
parser->getNextToken();
break;
}
}
}
int main(int argc, char** argv)
{
for (int i = 1; i < argc; i++)
{
std::cout << argv[i] << std::endl;
}
try
{
obelisk::KnowledgeBase* kb = new obelisk::KnowledgeBase("cromer.kb");
/*std::vector<std::string> leftObjects;
std::vector<std::string> rightObjects;
leftObjects.push_back("chris");
leftObjects.push_back("martin");
rightObjects.push_back("happy");
rightObjects.push_back("smart");
kb->addFacts("is", leftObjects, rightObjects);*/
}
catch (obelisk::KnowledgeBaseException& exception)
{
std::cout << exception.what() << std::endl;
return EXIT_FAILURE;
}
// This can be used to store a double as 2 floats in the database, then restore it back to a double.
// Inspired by Godot's double precision on the GPU to render large worlds.
/*float first;
float second;
double var = 0.123456789012345;
kb->getFloat(&first, &second, var);
std::cout << std::setprecision(std::numeric_limits<double>::digits10)
<< "Double: " << var << std::endl
<< "First: " << first << std::endl
<< "Second: " << second << std::endl;
var = 0.0;
kb->getDouble(&var, first, second);
std::cout << std::setprecision(std::numeric_limits<double>::digits10)
<< "Double: " << var << std::endl
<< "First: " << first << std::endl
<< "Second: " << second << std::endl;*/
mainLoop();
return EXIT_SUCCESS;
}

1
src/obelisk.h Normal file
View File

@ -0,0 +1 @@
static void mainLoop();

225
src/parser.cpp Normal file
View File

@ -0,0 +1,225 @@
#include "ast/call_expression_ast.h"
#include "ast/number_expression_ast.h"
#include "ast/variable_expression_ast.h"
#include "parser.h"
obelisk::Parser::Parser()
{
lexer_ = new obelisk::Lexer();
}
obelisk::Parser::Parser(obelisk::Lexer* lexer)
{
if (lexer != nullptr)
{
lexer_ = lexer;
}
else
{
Parser();
}
}
obelisk::Parser::~Parser()
{
delete lexer_;
}
obelisk::Lexer* obelisk::Parser::getLexer()
{
return lexer_;
}
int obelisk::Parser::getNextToken()
{
setCurrentToken(getLexer()->getToken());
return getCurrentToken();
}
int obelisk::Parser::getCurrentToken()
{
return currentToken_;
}
void obelisk::Parser::setCurrentToken(int currentToken)
{
currentToken_ = currentToken;
}
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::logError(
const char* str)
{
fprintf(stderr, "Error: %s\n", str);
return nullptr;
}
std::unique_ptr<obelisk::PrototypeAST> obelisk::Parser::logErrorPrototype(
const char* str)
{
logError(str);
return nullptr;
}
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseExpression()
{
auto LHS = parsePrimary();
if (!LHS)
{
return nullptr;
}
return LHS;
}
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parsePrimary()
{
switch (getCurrentToken())
{
case obelisk::Lexer::kTokenIdentifier :
return parseIdentifierExpression();
case obelisk::Lexer::kTokenNumber :
return parseNumberExpression();
case '(' :
return parseParenthesisExpression();
default :
return logError("unknown token when expecting and expression");
}
}
std::unique_ptr<obelisk::ExpressionAST> obelisk::Parser::parseNumberExpression()
{
auto result = std::make_unique<obelisk::NumberExpressionAST>(
getLexer()->getNumberValue());
getNextToken();
return std::move(result);
}
std::unique_ptr<obelisk::ExpressionAST>
obelisk::Parser::parseParenthesisExpression()
{
getNextToken();
auto v = parseExpression();
if (!v)
{
return nullptr;
}
if (getCurrentToken() != ')')
{
return logError("expected ')'");
}
getNextToken();
return v;
}
std::unique_ptr<obelisk::ExpressionAST>
obelisk::Parser::parseIdentifierExpression()
{
std::string idName = getLexer()->getIdentifier();
getNextToken();
if (getCurrentToken() != '(')
{
return std::make_unique<obelisk::VariableExpressionAST>(idName);
}
getNextToken();
std::vector<std::unique_ptr<obelisk::ExpressionAST>> args;
if (getCurrentToken() != ')')
{
while (true)
{
if (auto arg = parseExpression())
{
args.push_back(std::move(arg));
}
else
{
return nullptr;
}
if (getCurrentToken() == ')')
{
break;
}
if (getCurrentToken() != ',')
{
return logError("Expected ')' or ',' in argument list");
}
getNextToken();
}
}
getNextToken();
return std::make_unique<CallExpressionAST>(idName, std::move(args));
}
std::unique_ptr<obelisk::PrototypeAST> obelisk::Parser::parsePrototype()
{
if (getCurrentToken() != obelisk::Lexer::kTokenIdentifier)
{
return logErrorPrototype("Expected function name in prototype");
}
std::string functionName = getLexer()->getIdentifier();
getNextToken();
if (getCurrentToken() != '(')
{
return logErrorPrototype("Expected '(' in prototype");
}
std::vector<std::string> argNames;
while (getNextToken() == obelisk::Lexer::kTokenIdentifier)
{
argNames.push_back(getLexer()->getIdentifier());
}
if (getCurrentToken() != ')')
{
return logErrorPrototype("Expected ')' in prototype");
}
getNextToken();
return std::make_unique<obelisk::PrototypeAST>(functionName,
std::move(argNames));
}
std::unique_ptr<obelisk::FunctionAST> obelisk::Parser::parseDefinition()
{
getNextToken();
auto prototype = parsePrototype();
if (!prototype)
{
return nullptr;
}
if (auto expression = parseExpression())
{
return std::make_unique<FunctionAST>(std::move(prototype),
std::move(expression));
}
return nullptr;
}
std::unique_ptr<obelisk::FunctionAST> obelisk::Parser::parseTopLevelExpression()
{
if (auto expression = parseExpression())
{
// Make an anonymous prototype
auto prototype = std::make_unique<obelisk::PrototypeAST>("__anon_expr",
std::vector<std::string>());
return std::make_unique<obelisk::FunctionAST>(std::move(prototype),
std::move(expression));
}
return nullptr;
}
std::unique_ptr<obelisk::PrototypeAST> obelisk::Parser::parseExtern()
{
getNextToken();
return parsePrototype();
}

53
src/parser.h Normal file
View File

@ -0,0 +1,53 @@
#ifndef OBELISK_PARSER_H
#define OBELISK_PARSER_H
#include "ast/expression_ast.h"
#include "ast/function_ast.h"
#include "ast/prototype_ast.h"
#include "lexer.h"
#include <memory>
namespace obelisk
{
class Parser
{
private:
obelisk::Lexer* lexer_;
int currentToken_;
void setCurrentToken(int currentToken);
std::unique_ptr<obelisk::ExpressionAST> logError(const char* str);
std::unique_ptr<obelisk::PrototypeAST> logErrorPrototype(
const char* str);
std::unique_ptr<obelisk::ExpressionAST> parseExpression();
std::unique_ptr<obelisk::ExpressionAST> parseNumberExpression();
std::unique_ptr<obelisk::ExpressionAST>
parseParenthesisExpression();
std::unique_ptr<obelisk::ExpressionAST> parseIdentifierExpression();
std::unique_ptr<obelisk::ExpressionAST> parsePrimary();
std::unique_ptr<obelisk::PrototypeAST> parsePrototype();
std::unique_ptr<obelisk::FunctionAST> parseDefinition();
std::unique_ptr<obelisk::FunctionAST> parseTopLevelExpression();
std::unique_ptr<obelisk::PrototypeAST> parseExtern();
public:
Parser();
Parser(obelisk::Lexer* lexer);
~Parser();
obelisk::Lexer* getLexer();
int getCurrentToken();
int getNextToken();
void handleDefinition();
void handleExtern();
void handleTopLevelExpression();
};
} // namespace obelisk
#endif