Add .gitignore and .gitattributes.

This commit is contained in:
Robert 2021-10-17 20:01:16 +02:00 committed by Lauchmelder
commit d07643690c
13 changed files with 560 additions and 0 deletions

63
.gitattributes vendored Normal file
View file

@ -0,0 +1,63 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
out/
.vs/
*.json

9
CMakeLists.txt Normal file
View file

@ -0,0 +1,9 @@
# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.8)
project ("ZOLparser")
# Include sub-projects.
add_subdirectory ("ZOLparser")

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# ZOL Parser
ZOL stands for zeroth order logic, so this program can parse zeroth order logic.

9
ZOLparser/CMakeLists.txt Normal file
View file

@ -0,0 +1,9 @@
# CMakeList.txt : CMake project for ZOLparser, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
# Add source to this project's executable.
add_executable (ZOLparser "main.cpp" "Token.hpp" "Parser.hpp" "Parser.cpp" "Error.hpp" "Expression.hpp" "Expression.cpp")
# TODO: Add tests and install targets if needed.

20
ZOLparser/Error.hpp Normal file
View file

@ -0,0 +1,20 @@
#pragma once
#include <stdexcept>
#include <string>
class SyntaxError : public std::runtime_error
{
public:
SyntaxError(unsigned int position) :
std::runtime_error(std::string("Syntax error at position ") + std::to_string(position)), pos(position)
{}
unsigned int where()
{
return pos;
}
private:
unsigned int pos;
};

6
ZOLparser/Expression.cpp Normal file
View file

@ -0,0 +1,6 @@
#include "Expression.hpp"
IdentifierExpression IdentifierExpression::p;
IdentifierExpression IdentifierExpression::q;
IdentifierExpression IdentifierExpression::r;
IdentifierExpression IdentifierExpression::s;

125
ZOLparser/Expression.hpp Normal file
View file

@ -0,0 +1,125 @@
#pragma once
class Expression
{
public:
virtual bool Eval() const = 0;
virtual unsigned int Size() const = 0;
virtual unsigned int VarCount() const = 0;
};
class IdentifierExpression : public Expression
{
public:
static IdentifierExpression p;
static IdentifierExpression q;
static IdentifierExpression r;
static IdentifierExpression s;
public:
void SetTruthValue(bool value)
{
truthValue = value;
}
bool Eval() const override
{
return truthValue;
}
unsigned int Size() const override { return 1; }
unsigned int VarCount() const override {return 1; }
private:
IdentifierExpression() :
truthValue(false)
{ }
private:
bool truthValue;
};
class NegationExpression : public Expression
{
public:
NegationExpression(const Expression* operand) :
operand(operand)
{
}
bool Eval() const override
{
return !(operand->Eval());
}
unsigned int Size() const override { return 1 + operand->Size(); }
unsigned int VarCount() const override { return operand->VarCount(); }
private:
const Expression* operand;
};
class BinaryExpression : public Expression
{
public:
BinaryExpression(const Expression* left, const Expression* right) :
left(left), right(right)
{
}
unsigned int Size() const override { return 1 + left->Size() + right->Size(); }
unsigned int VarCount() const override { return left->VarCount() + right->VarCount(); }
protected:
const Expression* left;
const Expression* right;
};
class ConjunctionExpression : public BinaryExpression
{
public:
using BinaryExpression::BinaryExpression;
bool Eval() const override
{
return left->Eval() && right->Eval();
}
};
class DisjunctionExpression : public BinaryExpression
{
public:
using BinaryExpression::BinaryExpression;
bool Eval() const override
{
return left->Eval() || right->Eval();
}
};
class ImplicationExpression : public BinaryExpression
{
public:
using BinaryExpression::BinaryExpression;
bool Eval() const override
{
return !(left->Eval()) || right->Eval();
}
};
class EquivalenceExpression : public BinaryExpression
{
public:
using BinaryExpression::BinaryExpression;
bool Eval() const override
{
return left->Eval() == right->Eval();
}
};

188
ZOLparser/Parser.cpp Normal file
View file

@ -0,0 +1,188 @@
#include "Parser.hpp"
#include <regex>
#include <iostream>
Parser::Parser(const std::string& text)
{
unsigned int pos = 0;
for (std::string::const_iterator it = text.begin(); it != text.end(); it++)
{
TokenType type;
std::string lexeme(1, *it);
switch (*it)
{
case 'p':
case 'q':
case 'r':
case 's':
type = TokenType::Atom;
break;
case '~':
type = TokenType::Unary;
break;
case '^':
case 'v':
type = TokenType::Binary;
break;
case '-':
if (*(++it) == '>')
{
lexeme += *it;
type = TokenType::Binary;
break;
}
throw SyntaxError(std::distance(text.begin(), it));
case '<':
if (*(++it) == '-' && *(++it) == '>')
{
lexeme += "->";
type = TokenType::Binary;
break;
}
throw SyntaxError(std::distance(text.begin(), it));
case '(':
case ')':
type = TokenType::Parenthesis;
break;
default:
throw SyntaxError(std::distance(text.begin(), it));
}
tokens.emplace_back(Token{ type, lexeme, pos});
pos++;
}
tokens.emplace_back(Token{ TokenType::EOL, "", pos });
nextToken = tokens.begin();
expressionTree = ParseExpression();
if (nextToken->type != TokenType::EOL)
{
throw SyntaxError(nextToken->position);
}
}
const Token* Parser::ScanToken()
{
const Token* returnVal = &(*nextToken);
if (nextToken->type != TokenType::EOL) {
returnVal = &(*nextToken);
nextToken++;
}
return returnVal;
}
Expression* Parser::ParseExpression()
{
Expression* expr = ParseWedge();
while (nextToken->lexeme == "->" || nextToken->lexeme == "<->")
{
const Token* t = ScanToken();
Expression* right = ParseWedge();
if (t->lexeme == "->")
{
expr = new ImplicationExpression(expr, right);
}
else
{
expr = new EquivalenceExpression(expr, right);
}
}
return expr;
}
Expression* Parser::ParseWedge()
{
Expression* expr = ParseUnary();
while (nextToken->lexeme == "^" || nextToken->lexeme == "v")
{
const Token* t = ScanToken();
Expression* right = ParseUnary();
if (t->lexeme == "^")
{
expr = new ConjunctionExpression(expr, right);
}
else
{
expr = new DisjunctionExpression(expr, right);
}
}
return expr;
}
Expression* Parser::ParseUnary()
{
Expression* expr = nullptr;
if (nextToken->lexeme == "~")
{
ScanToken();
expr = new NegationExpression(ParseUnary());
}
else
{
expr = ParsePrimary();
}
return expr;
}
Expression* Parser::ParsePrimary()
{
Expression* expr = nullptr;
if (nextToken->type == TokenType::Atom)
{
const Token* t = ScanToken();
switch (t->lexeme[0])
{
case 'p': expr = &IdentifierExpression::p; break;
case 'q': expr = &IdentifierExpression::q; break;
case 'r': expr = &IdentifierExpression::r; break;
case 's': expr = &IdentifierExpression::s; break;
}
}
else if(nextToken->lexeme == "(")
{
ScanToken();
expr = ParseExpression();
if (ScanToken()->lexeme != ")")
{
throw SyntaxError(nextToken->position);
}
}
else
{
throw SyntaxError(nextToken->position);
}
return expr;
}
bool Parser::Evaluate() const
{
return expressionTree->Eval();
}
unsigned Parser::Size() const
{
return expressionTree->Size();
}
unsigned Parser::VarCount() const
{
return expressionTree->VarCount();
}

30
ZOLparser/Parser.hpp Normal file
View file

@ -0,0 +1,30 @@
#pragma once
#include <vector>
#include "Token.hpp"
#include "Expression.hpp"
#include "Error.hpp"
class Parser
{
public:
Parser(const std::string& text);
const Token* ScanToken();
Expression* ParseExpression();
Expression* ParseWedge();
Expression* ParseUnary();
Expression* ParsePrimary();
bool Evaluate() const;
unsigned Size() const;
unsigned VarCount() const;
private:
std::vector<Token> tokens;
std::vector<Token>::const_iterator nextToken;
Expression* expressionTree = nullptr;
};

19
ZOLparser/Token.hpp Normal file
View file

@ -0,0 +1,19 @@
#pragma once
#include <string>
enum class TokenType
{
Atom,
Parenthesis,
Unary,
Binary,
EOL
};
struct Token
{
TokenType type;
std::string lexeme;
unsigned int position;
};

5
ZOLparser/grammar.txt Normal file
View file

@ -0,0 +1,5 @@
expression -> wedge ( ( "->" | "<->" ) wedge)*
wedge -> unary ( ( "^" | "v" ) unary)*;
unary -> "~" unary | primary;
primary -> atom | "(" expression ")" ;
atom -> [pqrs] ;

80
ZOLparser/main.cpp Normal file
View file

@ -0,0 +1,80 @@
#include <iostream>
#include "Parser.hpp"
void PrintHelp();
int main(int argc, char** argv)
{
std::string text;
Parser* parser;
std::cout << "Zeroth order logic evaluator" << std::endl;
std::cout << "Enter expression or ?: ";
std::cin >> text;
if (text == "?")
{
PrintHelp();
return 0;
}
try
{
parser = new Parser(text);
}
catch (SyntaxError err)
{
std::cerr << err.what() << std::endl;
std::cerr << text << std::endl;
for (int i = 0; i < err.where(); i++)
std::cerr << " ";
std::cerr << "^" << std::endl;
return 1;
}
unsigned int tableLength = sizeof("| p | q | r | s || ") + text.length() + 2;
// Print table header
std::cout << "+---+---+---+---++-" << std::string(text.length(), '-') << "-+" << std::endl;
std::cout << "| p | q | r | s || " << text << " |" << std::endl;
std::cout << "+---+---+---+---++-" << std::string(text.length(), '-') << "-+" << std::endl;
for (int p = 0; p != 2; p++)
{
IdentifierExpression::p.SetTruthValue(p);
for (int q = 0; q != 2; q++)
{
IdentifierExpression::q.SetTruthValue(q);
for (int r = 0; r != 2; r++)
{
IdentifierExpression::r.SetTruthValue(r);
for (int s = 0; s != 2; s++)
{
IdentifierExpression::s.SetTruthValue(s);
std::cout << "| " << p << " | " << q << " | " << r << " | " << s << " || " << std::string(text.length() / 2, ' ') << parser->Evaluate() << std::string(text.length() - text.length() / 2, ' ') << "|" << std::endl;
}
}
}
}
std::cout << "+---+---+---+---++-" << std::string(text.length(), '-') << "-+" << std::endl;
std::cout << "Size = " << parser->Size() << std::endl;
std::cout << "VarCount = " << parser->VarCount() << std::endl;
return 0;
}
void PrintHelp()
{
std::cout << "This program creates truth value tables for zeroth order logic expressions with up to four atoms." << std::endl;
std::cout << "Syntax:" << std::endl;
std::cout << " p,q,r,s - Atom" << std::endl;
std::cout << " ~ - Negation (unary)" << std::endl;
std::cout << " ^ - Conjunction (binary)" << std::endl;
std::cout << " v - Disjunction (binary)" << std::endl;
std::cout << " -> - Implication (binary)" << std::endl;
std::cout << " <-> - Implication (binary)" << std::endl;
std::cout << std::endl << "~ binds stronger than (^, v) which bind stronger than (->, <->)" << std::endl;
}