Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F81197761
algebraic_parser.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Wed, Sep 4, 17:13
Size
11 KB
Mime Type
text/x-c++
Expires
Fri, Sep 6, 17:13 (2 d)
Engine
blob
Format
Raw Data
Handle
20529688
Attached To
rLIBMULTISCALE LibMultiScale
algebraic_parser.cc
View Options
/**
* @file algebraic_parser.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Wed Mar 13 16:53:59 2013
*
* @brief The algebraic expression parser for LM config files
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale is distributed in the hope that it will be useful, but
* WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#include "algebraic_parser.hh"
#include "lm_common.hh"
#include "lm_parser.hh"
#include <limits>
/* -------------------------------------------------------------------------- */
#include <iostream>
#include <map>
#include <string>
/* -------------------------------------------------------------------------- */
#include <boost/config/warning_disable.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/version.hpp>
#if (BOOST_VERSION / 100) % 1000 <= 55
#include <boost/spirit/home/phoenix/bind/bind_function.hpp>
#include <boost/spirit/home/phoenix/bind/bind_member_function.hpp>
#else
#include <boost/phoenix/bind/bind_function.hpp>
#include <boost/phoenix/bind/bind_member_function.hpp>
#endif
/* -------------------------------------------------------------------------- */
#include <boost/mpl/bool.hpp>
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
template
<
typename
Iterator
>
struct
AlgebraicParser
:
boost
::
spirit
::
qi
::
grammar
<
Iterator
,
double
()
>
{
/* ------------------------------------------------------------------------ */
/* Constructors/Destructors */
/* ------------------------------------------------------------------------ */
public
:
AlgebraicParser
();
/* ------------------------------------------------------------------------ */
/* Methods */
/* ------------------------------------------------------------------------ */
public
:
private
:
inline
double
set_var_value
(
double
const
&
val
,
std
::
string
const
&
var_name
)
const
;
inline
double
get_env_var
(
std
::
string
const
&
var_name
)
const
;
inline
double
get_var_value
(
std
::
string
const
&
var_name
)
const
;
inline
double
get_func_result
(
double
const
&
entry
,
std
::
string
const
&
func_name
)
const
;
inline
double
debug_double
(
double
const
&
test
)
const
;
inline
std
::
string
debug_string
(
std
::
string
const
&
test
)
const
;
inline
std
::
string
get_string
(
std
::
vector
<
char
>
const
&
vec
)
const
;
inline
std
::
string
concat_string
(
std
::
vector
<
char
>
const
&
vec
,
std
::
string
const
&
str2
)
const
;
/* ------------------------------------------------------------------------ */
/* Class Members */
/* ------------------------------------------------------------------------ */
private
:
//! grammar rules
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
(),
boost
::
spirit
::
qi
::
locals
<
std
::
string
>>
set_var
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
item
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
std
::
string
(),
boost
::
spirit
::
qi
::
locals
<
std
::
string
>>
obj_name
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
(),
boost
::
spirit
::
qi
::
locals
<
std
::
string
>>
func
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
num
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
env_var
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
term
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
factor
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
start
;
boost
::
spirit
::
qi
::
rule
<
Iterator
,
double
()
>
white_space
;
public
:
//! map of functions
std
::
map
<
std
::
string
,
double
(
*
)(
double
)
>
function_maps
;
//! map of variables and values
mutable
std
::
map
<
std
::
string
,
double
>
variables
;
};
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
double
AlgebraicParser
<
Iterator
>::
debug_double
(
double
const
&
test
)
const
{
std
::
cerr
<<
"parsing "
<<
test
<<
std
::
endl
;
return
test
;
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
std
::
string
AlgebraicParser
<
Iterator
>::
debug_string
(
std
::
string
const
&
test
)
const
{
std
::
cerr
<<
"parsing "
<<
test
<<
std
::
endl
;
return
test
;
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
std
::
string
AlgebraicParser
<
Iterator
>::
get_string
(
std
::
vector
<
char
>
const
&
vec
)
const
{
std
::
string
str
=
std
::
string
(
vec
.
begin
(),
vec
.
end
());
return
str
;
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
std
::
string
AlgebraicParser
<
Iterator
>::
concat_string
(
std
::
vector
<
char
>
const
&
vec
,
std
::
string
const
&
str2
)
const
{
std
::
string
str
=
std
::
string
(
vec
.
begin
(),
vec
.
end
());
return
str2
+
str
;
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
double
AlgebraicParser
<
Iterator
>::
get_var_value
(
std
::
string
const
&
vname
)
const
{
if
(
vname
[
0
]
==
'$'
)
{
std
::
string
env_varname
=
vname
.
substr
(
1
);
char
*
var
=
getenv
(
env_varname
.
c_str
());
if
(
var
==
NULL
)
LM_THROW
(
"unknown environment variable "
<<
env_varname
);
return
(
atof
(
var
));
}
else
{
std
::
map
<
std
::
string
,
double
>::
const_iterator
it
=
variables
.
find
(
vname
);
if
(
it
==
variables
.
end
())
LM_THROW
(
"unknown variable "
<<
vname
);
return
(
*
it
).
second
;
}
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
double
AlgebraicParser
<
Iterator
>::
set_var_value
(
double
const
&
val
,
std
::
string
const
&
vname
)
const
{
DUMPFILE
(
Parser
::
fout
,
"LET "
<<
vname
<<
" = "
<<
val
);
variables
[
vname
]
=
val
;
return
val
;
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
double
AlgebraicParser
<
Iterator
>::
get_env_var
(
std
::
string
const
&
vname
)
const
{
char
*
var
=
getenv
(
vname
.
c_str
());
if
(
var
==
NULL
)
LM_THROW
(
"unknown env variable "
<<
vname
);
std
::
string
vvname
(
var
);
if
(
variables
.
count
(
var
))
return
variables
[
vvname
];
return
atof
(
var
);
}
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
inline
double
AlgebraicParser
<
Iterator
>::
get_func_result
(
double
const
&
entry
,
std
::
string
const
&
func_name
)
const
{
std
::
map
<
std
::
string
,
double
(
*
)(
double
)
>::
const_iterator
it
=
function_maps
.
find
(
func_name
);
if
(
it
==
function_maps
.
end
())
LM_THROW
(
"unknown function "
<<
func_name
);
return
(
*
(
*
it
).
second
)(
entry
);
}
/* -------------------------------------------------------------------------- */
#define _call(x) boost::phoenix::bind(&AlgebraicParser::x, this, _1)
#define _call2(x) boost::phoenix::bind(&AlgebraicParser::x, this, _1, _a)
/* -------------------------------------------------------------------------- */
template
<
typename
Iterator
>
AlgebraicParser
<
Iterator
>::
AlgebraicParser
()
:
AlgebraicParser
::
base_type
(
start
)
{
using
boost
::
spirit
::
_val
;
using
boost
::
spirit
::
lit
;
using
boost
::
spirit
::
standard
::
space
;
using
boost
::
spirit
::
standard
::
alnum
;
using
boost
::
spirit
::
standard
::
alpha
;
using
boost
::
spirit
::
double_
;
using
boost
::
spirit
::
int_
;
using
boost
::
spirit
::
eoi
;
using
boost
::
spirit
::
_1
;
using
boost
::
spirit
::
_a
;
using
boost
::
phoenix
::
ref
;
using
boost
::
phoenix
::
val
;
set_var
=
*
space
>>
obj_name
[
_a
=
_1
]
>>
*
space
>>
"="
>>
term
[
_val
=
_call2
(
set_var_value
)];
obj_name
=
(
+
alpha
)[
_a
=
_call
(
get_string
)]
>>
(
*
alnum
)[
_val
=
_call2
(
concat_string
)];
func
=
obj_name
[
_a
=
_1
]
>>
"("
>>
term
[
_val
=
_call2
(
get_func_result
)]
>>
")"
;
env_var
=
"$"
>>
obj_name
[
_val
=
_call
(
get_env_var
)];
num
=
*
space
>>
(
double_
[
_val
=
_1
]
|
"("
>>
term
[
_val
=
_1
]
>>
")"
|
func
[
_val
=
_1
]
|
obj_name
[
_val
=
_call
(
get_var_value
)]
|
env_var
[
_val
=
_1
])
>>
*
space
;
item
=
*
space
>>
"-"
>>
num
[
_val
=
val
(
-
1.
)
*
_1
]
|
num
[
_val
=
_1
];
factor
=
item
[
_val
=
_1
]
>>
*
((
"*"
>>
item
[
_val
*=
_1
])
|
(
"/"
>>
item
[
_val
/=
_1
]));
term
=
factor
[
_val
=
_1
]
>>
*
((
"+"
>>
factor
[
_val
+=
_1
])
|
(
"-"
>>
factor
[
_val
-=
_1
]));
start
=
(
set_var
[
_val
=
_1
]
|
term
[
_val
=
_1
])
>>
*
space
>>
eoi
;
// setting the default variables and functions
variables
[
"pi"
]
=
M_PI
;
variables
[
"INF"
]
=
std
::
numeric_limits
<
Real
>::
max
();
variables
[
"avogadro"
]
=
avogadro
;
variables
[
"boltzmann"
]
=
boltzmann
;
function_maps
[
"cos"
]
=
std
::
cos
;
function_maps
[
"acos"
]
=
std
::
acos
;
function_maps
[
"sin"
]
=
std
::
sin
;
function_maps
[
"sqrt"
]
=
std
::
sqrt
;
function_maps
[
"abs"
]
=
std
::
abs
;
function_maps
[
"atan"
]
=
std
::
atan
;
}
/* -------------------------------------------------------------------------- */
AlgebraicExpressionParser
::
AlgebraicExpressionParser
()
{
my_parser
=
new
AlgebraicParser
<
std
::
string
::
const_iterator
>
();
}
/* -------------------------------------------------------------------------- */
AlgebraicExpressionParser
::~
AlgebraicExpressionParser
()
{
delete
my_parser
;
}
/* -------------------------------------------------------------------------- */
bool
AlgebraicExpressionParser
::
parse
(
const
std
::
string
&
str
,
double
&
result
)
{
std
::
string
::
const_iterator
iter
=
str
.
begin
();
std
::
string
::
const_iterator
end
=
str
.
end
();
bool
parsed
=
boost
::
spirit
::
qi
::
parse
(
iter
,
end
,
*
my_parser
,
result
);
if
(
!
parsed
)
{
std
::
string
rest
(
iter
,
end
);
LM_THROW
(
"could not parse -- stopped at "
<<
rest
);
}
return
parsed
;
}
/* -------------------------------------------------------------------------- */
Real
&
AlgebraicExpressionParser
::
operator
[](
const
std
::
string
&
var_name
)
{
LM_ASSERT
(
doesExist
(
var_name
),
"Unknown variable"
);
return
my_parser
->
variables
[
var_name
];
}
/* -------------------------------------------------------------------------- */
void
AlgebraicExpressionParser
::
eraseVariable
(
const
std
::
string
&
var_name
)
{
my_parser
->
variables
.
erase
(
var_name
);
}
/* -------------------------------------------------------------------------- */
bool
AlgebraicExpressionParser
::
doesExist
(
const
std
::
string
&
var_name
)
{
if
(
my_parser
->
variables
.
count
(
var_name
))
return
true
;
return
false
;
}
/* -------------------------------------------------------------------------- */
std
::
map
<
std
::
string
,
double
>
&
AlgebraicExpressionParser
::
getVariables
()
{
return
my_parser
->
variables
;
}
__END_LIBMULTISCALE__
Event Timeline
Log In to Comment