Compare commits

...

9 Commits

14 changed files with 507 additions and 0 deletions

3
tprcc/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.o
build/*
.cache/*

46
tprcc/CMakeLists.txt Normal file
View File

@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.8)
project(tprcc LANGUAGES CXX)
set (CMAKE_CXX_STANDARD 17)
add_compile_options(-Wall -Wextra)
aux_source_directory("src" SRC_DIR)
aux_source_directory("src/tpr" SRC_TPR_DIR)
set(TPR_PARSER_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated-tpr")
set (SRC_GENERATED "${TPR_PARSER_DIR}/tpr-parser.cpp" "${TPR_PARSER_DIR}/tpr-scanner.cpp")
set (SOURCES
${SRC_DIR}
${SRC_TPR_DIR}
${SRC_GENERATED}
)
add_custom_command(
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/parser/tpr.l
OUTPUT
${TPR_PARSER_DIR}/tpr-scanner.cpp
COMMAND
mkdir -p "${TPR_PARSER_DIR}" && flex -+ -o "${TPR_PARSER_DIR}/tpr-scanner.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/parser/tpr.l"
)
add_custom_command(
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/parser/tpr.ypp
OUTPUT
${TPR_PARSER_DIR}/tpr-parser.cpp
COMMAND
mkdir -p "${TPR_PARSER_DIR}/include/tpr-parser" && ${CMAKE_CURRENT_SOURCE_DIR}/bison-wrapper.sh "${TPR_PARSER_DIR}/tpr-parser.cpp" "${TPR_PARSER_DIR}/include/tpr-parser/tpr-parser.hpp" "${TPR_PARSER_DIR}/include/tpr-parser/location.hh" --header=tpr-parser.hpp ${CMAKE_CURRENT_SOURCE_DIR}/parser/tpr.ypp
)
SET_SOURCE_FILES_PROPERTIES(${SRC_GENERATED} PROPERTIES GENERATED 1)
add_executable(${PROJECT_NAME} ${SOURCES})
target_include_directories(${PROJECT_NAME} PRIVATE "${TPR_PARSER_DIR}/include" "${TPR_PARSER_DIR}/include/tpr-parser")
target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include")
# TEMPORARY FIx:
#target_include_directories(${PROJECT_NAME} PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")

31
tprcc/bison-wrapper.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/bash
set -e
# Usage: bison-wrapper.sh <c-file> <include-file> <location.hh> <bison_file> <bison-parameters>
if [[ $# -lt 4 ]]; then
echo "Error. Not enough parameters"
exit -1
fi
cfile=$1
shift
include=$1
shift
location=$1
shift
tmpdir=`mktemp -d`
cd $tmpdir
echo "Using $tmpdir"
echo cp *.tab.cpp "$cfile"
echo cp *.hpp "$include"
echo cp location.hh "$location"
bison $@
cp *.tab.cpp "$cfile"
cp *.hpp "$include"
cp location.hh "$location"
rm -rfv "$tmpdir"

View File

@ -0,0 +1,31 @@
#ifndef _TEMP_LANG_FRONTEND_HPP_
#define _TEMP_LANG_FRONTEND_HPP_
#include <string>
#include <iostream>
#include <fstream>
#include <istream>
#include <streambuf>
class TempLangFrontend {
public:
TempLangFrontend(const std::string &source_file)
{
m_source_file = source_file;
}
virtual int analyze() = 0;
const std::string &get_src_file()
{
return m_source_file;
}
protected:
std::string m_source_file;
};
#endif /* _TEMP_LANG_FRONTEND_HPP_ */

View File

@ -0,0 +1,20 @@
#ifndef _TPR_FRONTEND_HPP_
#define _TPR_FRONTEND_HPP_
#include <string>
#include <lang/temp-lang-frontend.hpp>
#include <tpr/tpr-scanner.hpp>
namespace tpr {
class TprFrontend : public TempLangFrontend {
private:
public:
TprFrontend(const std::string &source_file);
int analyze() override;
};
}
#endif /* _TPR_FRONTEND_HPP_ */

View File

@ -0,0 +1,38 @@
#ifndef _TPR_SCANNER_HPP_
#define _TPR_SCANNER_HPP_
#if ! defined(yyFlexLexerOnce)
#include <FlexLexer.h>
#endif
#include <tpr-parser/tpr-parser.hpp>
#include <tpr-parser/location.hh>
namespace tpr {
class TempProfileScanner : public yyFlexLexer{
public:
TempProfileScanner(std::istream *in) : yyFlexLexer(in) {
};
virtual ~TempProfileScanner() {};
//get rid of override virtual function warning
using FlexLexer::yylex;
virtual
int yylex( tpr::TempProfileParser::semantic_type * const lval,
tpr::TempProfileParser::location_type *loc );
// YY_DECL defined in mc_lexer.l
// Method body created by flex in mc_lexer.yy.cc
private:
/* yyval ptr */
tpr::TempProfileParser::semantic_type *yylval = nullptr;
};
} /* end namespace MC */
#endif /* _TPR_SCANNER_HPP_ */

View File

@ -0,0 +1,38 @@
#ifndef _TPR_TYPES_HPP_
#define _TPR_TYPES_HPP_
#include <vector>
namespace tpr {
enum class CommandType {
pid_conf,
temp_set,
wait_temp,
wait_time,
temp_ramp,
beep,
temp_off,
clear_flags,
digio_conf,
digio_set,
digio_wait,
};
class TprCommand {
private:
CommandType m_type;
std::vector<float> m_parameters;
public:
TprCommand(CommandType type);
TprCommand(CommandType type, const std::vector<float> &params);
TprCommand(CommandType type, const std::vector<float> &&params);
};
}
#endif /* _TPR_TYPES_HPP_ */

View File

@ -0,0 +1,31 @@
#ifndef _LOGGER_HPP_
#define _LOGGER_HPP_
#include <string>
enum class LogLevel {
DEBUG,
INFO,
WARNING,
ERROR,
};
class Logger {
public:
Logger(Logger &other) = delete;
void operator=(const Logger &) = delete;
void log(LogLevel lvl, const std::string &message) const;
static Logger *get_logger();
protected:
/* Create a proteceted instructure, to prevent construction outside of this class */
Logger();
static Logger *logger_inst;
};
#endif /* _LOGGER_HPP_ */

54
tprcc/parser/tpr.l Normal file
View File

@ -0,0 +1,54 @@
%{
#include <tpr/tpr-scanner.hpp>
#include <string>
#undef YY_DECL
#define YY_DECL int tpr::TempProfileScanner::yylex(tpr::TempProfileParser::semantic_type * const lval, tpr::TempProfileParser::location_type *loc )
#define YY_USER_ACTION loc->step(); loc->columns(yyleng);
using token = tpr::TempProfileParser::token;
%}
%option yyclass="tpr::TempProfileScanner"
%option noyywrap
%option never-interactive
%option c++
/* Predefined rules */
NEWLINE "\n"|"\r\n"
COMMENT_LINE "#".*\n
SPACE "\t"|" "
NUM_INT [-+]?([0-9]+)
NUM_FLOAT [-+]?([0-9]*\.[0-9]+)
%%
%{
yylval = lval;
%}
<*>{SPACE} { /*Ignore spaces */}
{COMMENT_LINE} {loc->lines(); return token::lineend;}
{NEWLINE} {loc->lines(); return token::lineend;}
{NUM_FLOAT} {yylval->build<float>(std::stof(std::string(yytext))); return token::number_float;}
{NUM_INT} {yylval->build<float>(std::stof(std::string(yytext))); return token::number_int;}
pid_conf { return token::kw_pid_conf; }
temp_set { return token::kw_temp_set; }
wait_temp { return token::kw_wait_temp; }
wait_time { return token::kw_wait_time; }
temp_ramp { return token::kw_temp_ramp; }
beep { return token::kw_beep; }
temp_off { return token::kw_temp_off; }
clear_flags { return token::kw_clear_flags; }
digio_conf { return token::kw_digio_conf; }
digio_set { return token::kw_digio_set; }
digio_wait { return token::kw_digio_wait; }
. {
std::cerr << "[ERR] Failed to parse: " << yytext << " @ " << *loc << std::endl;
return token::unexpected_input;
}
%%

115
tprcc/parser/tpr.ypp Normal file
View File

@ -0,0 +1,115 @@
%language "c++"
%require "3.2"
%defines
%define api.namespace {tpr}
%define api.parser.class {TempProfileParser}
%define parse.error verbose
%code requires{
namespace tpr {
class TempProfileScanner;
}
}
%parse-param { TempProfileScanner &scanner }
%code {
#include <iostream>
#include <cstdlib>
#include <fstream>
#include <utility>
#include <tuple>
#include <tpr/tpr-scanner.hpp>
#include <tpr/tpr-types.hpp>
#undef yylex
#define yylex scanner.yylex
}
%define api.value.type variant
%locations
%start tpr_file
%token<float> number_float
%token<float> number_int
%token lineend
%token kw_pid_conf
%token kw_temp_set
%token kw_wait_temp
%token kw_wait_time
%token kw_temp_ramp
%token kw_beep
%token kw_temp_off
%token kw_clear_flags
%token kw_digio_conf
%token kw_digio_set
%token kw_digio_wait
%token unexpected_input
%type<float>number number_truncated
%%
tpr_file: tpr_command
| tpr_file tpr_command
;
tpr_command: tpr_command_inner lineend
| lineend
;
tpr_command_inner: cmd_pid_conf;
| cmd_temp_set
| cmd_wait_temp
| cmd_wait_time
| cmd_temp_ramp
| cmd_beep
| cmd_temp_off
| cmd_clear_flags
| cmd_digio_conf
| cmd_digio_set
| cmd_digio_wait
;
cmd_pid_conf: kw_pid_conf number number number number number number;
cmd_temp_set: kw_temp_set number {std::cout << "Set Temperature" << $2 << std::endl;}
;
cmd_wait_temp: kw_wait_temp number;
cmd_wait_time: kw_wait_time number;
cmd_temp_ramp: kw_temp_ramp number number;
cmd_beep: kw_beep number_truncated;
cmd_temp_off: kw_temp_off;
cmd_clear_flags: kw_clear_flags;
cmd_digio_conf: kw_digio_conf number_truncated number_truncated;
cmd_digio_set: kw_digio_set number_truncated number_truncated;
cmd_digio_wait: kw_digio_wait number_truncated number_truncated;
number_truncated: number_float {$$ = $1; std::cerr << "[WARN] Floating point number " << $1 << " will be truncated to an integer (" << (int)$1 << ") at location (" << @1 << ")" << std::endl;}
| number_int {$$ = $1;}
;
number: number_float {$$ = $1;}
| number_int {$$ = $1;}
;
%%
void tpr::TempProfileParser::error(const location_type &l, const std::string &err_message)
{
std::cerr << "[ERR] Parser Error: '" << err_message << "' at " << l << std::endl;
std::abort();
}

32
tprcc/src/logger.cpp Normal file
View File

@ -0,0 +1,32 @@
#include <tprcc/logger.hpp>
#include <iostream>
Logger *Logger::logger_inst = nullptr;
Logger::Logger()
{
}
Logger *Logger::get_logger() {
if (logger_inst == nullptr) {
logger_inst = new Logger();
}
return logger_inst;
}
void Logger::log(LogLevel lvl, const std::string &message) const
{
switch (lvl) {
case LogLevel::ERROR:
std::cerr << "[ERR]" << message << std::endl;
break;
case LogLevel::WARNING:
std::cerr << "[WARN]" << message << std::endl;
break;
default:
std::cout << message << std::endl;
break;
}
}

15
tprcc/src/main.cpp Normal file
View File

@ -0,0 +1,15 @@
#include <iostream>
#include <tpr/tpr-frontend.hpp>
int main(int argc, char **argv)
{
std::cout << "Hello world" << std::endl;
if (argc > 1) {
auto fe = tpr::TprFrontend(std::string(argv[1]));
fe.analyze();
}
return 0;
}

View File

@ -0,0 +1,27 @@
#include <tprcc/logger.hpp>
#include <tpr/tpr-frontend.hpp>
namespace tpr {
TprFrontend::TprFrontend(const std::string &source_file) : TempLangFrontend(source_file)
{
}
int TprFrontend::analyze()
{
std::ifstream input_stream(m_source_file);
if (!input_stream.good()) {
Logger::get_logger()->log(LogLevel::ERROR, "Cannot read input file " + m_source_file);
return -1;
}
auto scanner = TempProfileScanner(&input_stream);
auto parser = TempProfileParser(scanner);
parser.parse();
return 0;
}
}

View File

@ -0,0 +1,26 @@
#include "tprcc/logger.hpp"
#include <cstdlib>
#include <tpr/tpr-types.hpp>
#include <cmath>
#include <iostream>
namespace tpr {
TprCommand::TprCommand(CommandType type)
{
m_type = type;
}
TprCommand::TprCommand(CommandType type, const std::vector<float> &params) : TprCommand(type)
{
m_parameters = params;
}
TprCommand::TprCommand(CommandType type, const std::vector<float> &&params) : TprCommand(type)
{
m_parameters = std::move(params);
}
}