Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
dcdb
dcdb
Commits
c74c2caa
Commit
c74c2caa
authored
Jan 20, 2016
by
Axel Auweter
Browse files
Added simple parser for virtual sensor expressions.
parent
67d39235
Changes
6
Hide whitespace changes
Inline
Side-by-side
DCDBLib/Makefile
View file @
c74c2caa
...
...
@@ -14,6 +14,7 @@ OBJS = src/connection.o \
src/sensorconfig.o
\
src/sensorid.o
\
src/unitconv.o
\
src/virtualsensor.o
\
src/c_api.o
# List of public header files necessary to use this libray
...
...
@@ -42,7 +43,7 @@ P = $(shell cd $(DCDBDEPLOYPATH)/lib/ && pwd)
.PHONY
:
check-target-env all clean install
# Main Library Target
$(TARGET)
:
$(OBJS)
$(TARGET)
:
$(OBJS)
.header-check
@
if
[
"
$(OS)
"
=
"Darwin"
]
;
then
\
echo
"Linking library in Mac OS style:
$(TARGET)
"
;
\
$(CXX)
$(CXXFLAGS)
$(DLFLAGS)
-o
$(TARGET)
$(OBJS)
$(LIBS)
;
\
...
...
@@ -67,6 +68,11 @@ check-target-env:
printf
"
\n
******************************************
\n
Please type the following line before running:
\n
export LD_LIBRARY_PATH=
$$
LD_LIBRARY_PATH:
$P
\n
******************************************
\n
"
;
\
fi
;
\
fi
# Header check
.header-check
:
$(PUBHEADERS) $(PRIVHEADERS)
@
touch
.header-check
@
touch
$(OBJS:.o=.cpp)
# Build the documentation
docs
:
$(PUBHEADERS) $(PRIVHEADERS) $(SRC)
...
...
@@ -75,6 +81,7 @@ docs: $(PUBHEADERS) $(PRIVHEADERS) $(SRC)
# Clean everything
clean
:
clean-docs
rm
-f
.header-check
rm
-f
$(OBJS)
$(TARGET)
# Clean the documentation
...
...
DCDBLib/include/virtualsensor.h
0 → 100644
View file @
c74c2caa
/*
* virtualsensor.h
*
* Created on: Jan 15, 2016
* Author: Axel Auweter
*/
/**
* @file
* @brief This file contains classes for handling virtual sensors.
*/
#include
<stdexcept>
#include
<string>
#ifndef DCDB_VIRTUAL_SENSOR_H
#define DCDB_VIRTUAL_SENSOR_H
namespace
DCDB
{
/**
* @brief Exception class for parsing Virtual Sensor Expressions
*
* Exceptions of this type are thrown whenever the parser for virtual
* sensor expressions encounters a syntax error. What() tries to
* provide the user with a hint on the location where the error was
* encountered while processing the expression string.
*/
class
VSExpressionParserException
:
public
std
::
runtime_error
{
public:
VSExpressionParserException
(
const
std
::
string
&
where
)
:
runtime_error
(
"Error parsing expression at: "
),
where_
(
where
)
{}
virtual
const
char
*
what
()
const
throw
();
private:
static
std
::
string
msg_
;
std
::
string
where_
;
};
/* Forward declare VirtualSensor::VSensorImpl */
namespace
VirtualSensor
{
class
VSensorImpl
;
}
/**
* @brief Class for evaluating Virtual Sensors
*
* TODO: Implement this :)
*/
class
VSensor
{
protected:
VirtualSensor
::
VSensorImpl
*
impl
;
public:
VSensor
(
std
::
string
expr
);
virtual
~
VSensor
();
};
}
/* End of namespace DCDB */
#endif
/* DCDB_VIRTUAL_SENSOR_H */
DCDBLib/include_internal/virtualsensor_internal.h
0 → 100644
View file @
c74c2caa
/*
* virtualsensor_internal.h
*
* Created on: Jan 18, 2016
* Author: Axel Auweter
*/
/**
* @file
* @brief This file contains internal classes for handling virtual sensors.
*/
#include
<boost/spirit/include/qi.hpp>
#include
<boost/variant/recursive_variant.hpp>
#include
<boost/fusion/include/adapt_struct.hpp>
#ifndef DCDB_VIRTUAL_SENSOR_INTERNAL_H
#define DCDB_VIRTUAL_SENSOR_INTERNAL_H
namespace
DCDB
{
namespace
VirtualSensor
{
namespace
qi
=
boost
::
spirit
::
qi
;
namespace
ascii
=
boost
::
spirit
::
ascii
;
/**
* @brief Definitions for objects in the Virtual Sensor expression's AST.
*/
namespace
AST
{
/**
* @brief The NIL object.
*
* The NIL object represents a no-op or empty operand in the AST.
*/
struct
Nil
{};
/**
* @brief The SIGNED object.
*
* The SIGNED object represents a positive or negative sign preceding an operand in the AST.
*/
struct
Signd
;
/**
* @brief The OPSEQ object.
*
* The OPSEQ object represents a sequence of operations in the AST.
*/
struct
Opseq
;
/**
* @brief The OP object.
*
* The OP object represents a simple operation in the AST.
*/
struct
Op
;
typedef
boost
::
variant
<
Nil
,
unsigned
int
,
boost
::
recursive_wrapper
<
Signd
>
,
boost
::
recursive_wrapper
<
Opseq
>
>
Operand
;
struct
Signd
{
char
sgn
;
Operand
oprnd
;
};
struct
Opseq
{
Operand
frst
;
std
::
list
<
Op
>
rst
;
};
struct
Op
{
char
oprtr
;
Operand
oprnd
;
};
}
/* End of namespace AST */
}
/* End of namespace VirtualSensor */
}
/* End of namespace DCDB */
/*
* Create Random Access Sequence for AST Objects.
* These must be created at the top of namespaces but obviously after defining the structs.
*/
BOOST_FUSION_ADAPT_STRUCT
(
DCDB
::
VirtualSensor
::
AST
::
Signd
,
(
char
,
sgn
)
(
DCDB
::
VirtualSensor
::
AST
::
Operand
,
oprnd
)
)
BOOST_FUSION_ADAPT_STRUCT
(
DCDB
::
VirtualSensor
::
AST
::
Opseq
,
(
DCDB
::
VirtualSensor
::
AST
::
Operand
,
frst
)
(
std
::
list
<
DCDB
::
VirtualSensor
::
AST
::
Op
>
,
rst
)
)
BOOST_FUSION_ADAPT_STRUCT
(
DCDB
::
VirtualSensor
::
AST
::
Op
,
(
char
,
oprtr
)
(
DCDB
::
VirtualSensor
::
AST
::
Operand
,
oprnd
)
)
namespace
DCDB
{
namespace
VirtualSensor
{
/**
* @brief The ExpressionGrammar struct holds the grammar definition for
* the arithmetic expressions that describe virtual sensors.
*
* Since we're using the Boost Spirit framework's Qi parser generator,
* we define the grammar using the qi syntax and built-in qi parsers
* (e.g. qi::uint_ or qi:hex).
*/
template
<
typename
Iterator
>
struct
ExpressionGrammar
:
qi
::
grammar
<
Iterator
,
AST
::
Opseq
(),
ascii
::
space_type
>
{
ExpressionGrammar
()
:
ExpressionGrammar
::
base_type
(
expression
)
{
expression
=
term
>>
*
(
(
qi
::
char_
(
'+'
)
>>
term
)
|
(
qi
::
char_
(
'-'
)
>>
term
)
)
;
term
=
factor
>>
*
(
(
qi
::
char_
(
'*'
)
>>
factor
)
|
(
qi
::
char_
(
'/'
)
>>
factor
)
)
;
factor
=
(
"0x"
>>
qi
::
hex
)
|
qi
::
uint_
|
'('
>>
expression
>>
')'
|
(
qi
::
char_
(
'-'
)
>>
factor
)
|
(
qi
::
char_
(
'+'
)
>>
factor
)
;
}
qi
::
rule
<
Iterator
,
AST
::
Opseq
(),
ascii
::
space_type
>
expression
;
qi
::
rule
<
Iterator
,
AST
::
Opseq
(),
ascii
::
space_type
>
term
;
qi
::
rule
<
Iterator
,
AST
::
Operand
(),
ascii
::
space_type
>
factor
;
};
class
VSensorImpl
{
protected:
VirtualSensor
::
AST
::
Opseq
opseq
;
void
validateExpression
(
std
::
string
expr
);
void
dumpAST
();
public:
VSensorImpl
(
std
::
string
expr
);
virtual
~
VSensorImpl
();
};
}
/* End of namesapce VirtualSensor */
}
/* End of namespace DCDB */
#endif
/* DCDB_VIRTUAL_SENSOR_INTERNAL_H */
DCDBLib/src/sensorconfig.cpp
View file @
c74c2caa
...
...
@@ -14,6 +14,7 @@
#include
"sensorconfig_internal.h"
#include
"dcdbglobals.h"
#include
"dcdbendian.h"
#include
"virtualsensor.h"
using
namespace
DCDB
;
...
...
@@ -311,7 +312,14 @@ SCError SensorConfigImpl::publishVirtualSensor(std::string publicName, std::stri
return
SC_INVALIDSESSION
;
}
/* TODO: Validate vSensorExpression */
/* Validate vSensorExpression */
try
{
VSensor
vsensor
(
vSensorExpression
);
}
catch
(
std
::
exception
&
e
)
{
std
::
cout
<<
e
.
what
();
return
SC_INVALIDEXPRESSION
;
}
/* Check if the vSensorId is valid */
SensorId
vSensor
;
...
...
DCDBLib/src/virtualsensor.cpp
0 → 100644
View file @
c74c2caa
/*
* virtualsensor.cpp
*
* Created on: Jan 15, 2016
* Author: Axel Auweter
*/
#include
"virtualsensor.h"
#include
"virtualsensor_internal.h"
namespace
DCDB
{
/*
* Implementations for VSExpressionParserException class.
*/
std
::
string
VSExpressionParserException
::
msg_
;
const
char
*
VSExpressionParserException
::
what
()
const
throw
()
{
msg_
=
runtime_error
::
what
();
msg_
+=
where_
;
msg_
+=
"
\n
"
;
return
msg_
.
c_str
();
}
/*
* Implementations for VSensor class.
*/
VSensor
::
VSensor
(
std
::
string
expr
)
{
impl
=
new
VirtualSensor
::
VSensorImpl
(
expr
);
}
VSensor
::~
VSensor
()
{
if
(
impl
)
{
delete
impl
;
}
}
namespace
VirtualSensor
{
/*
* Implementations for VSensorImpl class.
*/
void
VSensorImpl
::
validateExpression
(
std
::
string
expr
)
{
/* Try to generate AST */
typedef
std
::
string
::
const_iterator
StringIterator
;
typedef
ExpressionGrammar
<
StringIterator
>
Grammar
;
ascii
::
space_type
space
;
Grammar
grammar
;
StringIterator
it
=
expr
.
begin
();
StringIterator
end
=
expr
.
end
();
bool
success
=
phrase_parse
(
it
,
end
,
grammar
,
space
,
opseq
);
if
((
!
success
)
||
(
it
!=
end
))
{
std
::
string
rest
(
it
,
end
);
throw
VSExpressionParserException
(
rest
);
}
/* Success - opseq now represents the top level of our AST */
}
void
VSensorImpl
::
dumpAST
()
{
/* Declare a struct describing the action for each object in the AST when it comes to printing */
struct
ASTPrinter
{
typedef
void
result_type
;
void
operator
()(
AST
::
Nil
)
const
{}
void
operator
()(
unsigned
int
n
)
const
{
std
::
cout
<<
n
;
}
void
operator
()(
AST
::
Op
const
&
x
)
const
{
boost
::
apply_visitor
(
*
this
,
x
.
oprnd
);
switch
(
x
.
oprtr
)
{
case
'+'
:
std
::
cout
<<
" add"
;
break
;
case
'-'
:
std
::
cout
<<
" sub"
;
break
;
case
'*'
:
std
::
cout
<<
" mul"
;
break
;
case
'/'
:
std
::
cout
<<
" div"
;
break
;
}
}
void
operator
()(
AST
::
Signd
const
&
x
)
const
{
boost
::
apply_visitor
(
*
this
,
x
.
oprnd
);
switch
(
x
.
sgn
)
{
case
'-'
:
std
::
cout
<<
" neg"
;
break
;
case
'+'
:
std
::
cout
<<
" pos"
;
break
;
}
}
void
operator
()(
AST
::
Opseq
const
&
x
)
const
{
boost
::
apply_visitor
(
*
this
,
x
.
frst
);
BOOST_FOREACH
(
AST
::
Op
const
&
o
,
x
.
rst
)
{
std
::
cout
<<
' '
;
(
*
this
)(
o
);
}
}
};
ASTPrinter
printer
;
printer
(
opseq
);
std
::
cout
<<
std
::
endl
;
}
VSensorImpl
::
VSensorImpl
(
std
::
string
expr
)
{
/* Check if the expression is valid */
validateExpression
(
expr
);
/* Dump AST */
dumpAST
();
}
VSensorImpl
::~
VSensorImpl
()
{
}
}
/* End of namespace VirtualSensor */
}
/* End of namespace DCDB */
DCDBTools/dcdbconfig/sensoraction.cpp
View file @
c74c2caa
...
...
@@ -216,7 +216,8 @@ void SensorAction::doVCreateSensor(const char* publicName, const char* expressio
switch
(
err
)
{
case
DCDB
::
SC_INVALIDEXPRESSION
:
std
::
cout
<<
"Invalid expression: "
<<
expression
<<
std
::
endl
;
// We should get a proper error message in the exception handler.
//std::cout << "Invalid expression: " << expression << std::endl;
break
;
case
DCDB
::
SC_INVALIDVSENSORID
:
std
::
cout
<<
"Invalid vsensorid: "
<<
vSensorId
<<
std
::
endl
;
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment