Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F85428449
lm_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
Sun, Sep 29, 03:58
Size
16 KB
Mime Type
text/x-c
Expires
Tue, Oct 1, 03:58 (2 d)
Engine
blob
Format
Raw Data
Handle
21179924
Attached To
rLIBMULTISCALE LibMultiScale
lm_parser.cc
View Options
/**
* @file lm_parser.cc
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Wed Jul 02 16:25:38 2014
*
* @brief This is the central parser for LM
*
* @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 "lm_parser.hh"
#include "domain_multiscale.hh"
#include "factory_multiscale.hh"
#include "filter_interface.hh"
#include "lm_common.hh"
#include "lm_parsable.hh"
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
std
::
string
Parser
::
getCurrentConfigFile
()
{
return
opened_files
.
back
();
}
/* -------------------------------------------------------------------------- */
UInt
Parser
::
getCurrentLine
()
{
return
current_line
.
back
();
}
/* -------------------------------------------------------------------------- */
// void Parser::parseGeometry(GeomID & g,stringstream & line){
// parseString(g,line);
// __attribute__((unused)) Geometry * geom =
// GeometryManager::getManager().getGeometry(g);
//}
/* -------------------------------------------------------------------------- */
void
Parser
::
freeMemory
()
{
// math_parser.free_memory();
// DUMPFILE(fout,"memory cleaned");
fout
.
close
();
}
/* -------------------------------------------------------------------------- */
void
Parser
::
getLine
(
std
::
ifstream
&
file
,
std
::
string
&
line
,
UInt
&
current_line
)
{
line
=
""
;
std
::
string
tmp_line
;
getline
(
file
,
tmp_line
);
size_t
found
=
tmp_line
.
find
(
"
\\
"
);
++
current_line
;
while
(
found
!=
std
::
string
::
npos
)
{
line
+=
tmp_line
.
substr
(
0
,
found
-
1
);
getline
(
file
,
tmp_line
);
found
=
tmp_line
.
find
(
"
\\
"
);
++
current_line
;
}
line
+=
tmp_line
;
}
/* -------------------------------------------------------------------------- */
void
Parser
::
rewindToLine
(
UInt
line
)
{
DUMPFILE
(
Parser
::
fout
,
"rewind to line"
<<
line
);
std
::
ifstream
&
f
=
*
opened_ifstreams
.
back
();
f
.
seekg
(
0
,
std
::
ios_base
::
beg
);
std
::
string
buffer
;
current_line
.
back
()
=
0
;
for
(
UInt
i
=
0
;
i
<
line
-
1
;
++
i
)
{
Parser
::
getLine
(
f
,
buffer
,
current_line
.
back
());
if
(
current_line
.
back
()
==
line
-
1
)
break
;
}
}
/* -------------------------------------------------------------------------- */
void
Parser
::
parseConfigFile
(
const
std
::
string
&
file
,
const
std
::
string
&
section_name
,
const
std
::
string
&
section_id
,
Parsable
&
obj
)
{
std
::
ifstream
f
;
f
.
open
(
file
.
c_str
());
if
(
!
f
.
is_open
())
{
LM_FATAL
(
"could not open config file "
<<
file
);
}
/// put the current file to stack
opened_files
.
push_back
(
file
);
current_line
.
push_back
(
0
);
opened_ifstreams
.
push_back
(
&
f
);
DUMP
(
"parser state "
<<
Parser
::
getParserState
(),
DBG_INFO
);
std
::
string
buffer
;
bool
section_flag
=
false
;
bool
found_section
=
false
;
std
::
string
mot
;
units_converter
.
setOutUnits
(
code_unit_system
);
// section_units.push_back(real_unit_system);
while
(
f
.
good
())
{
Parser
::
getLine
(
f
,
buffer
,
current_line
.
back
());
DUMP
(
"treat line "
<<
current_line
.
back
(),
DBG_DETAIL
);
unsigned
long
found
=
buffer
.
find_first_of
(
"#"
);
std
::
string
buffer_comment_free
=
buffer
.
substr
(
0
,
found
-
1
);
buffer
=
buffer_comment_free
;
/* si il s'agit d'un commentaire on ne fait rien */
if
(
buffer
[
0
]
==
'#'
||
buffer
==
""
)
{
continue
;
}
std
::
stringstream
line
(
buffer
);
try
{
Parser
::
strNext
(
mot
,
line
);
}
catch
(
LibMultiScaleException
&
e
)
{
DUMP
(
"Parser exception "
<<
e
.
what
()
<<
std
::
endl
<<
getParserState
(),
DBG_WARNING
);
continue
;
}
if
(
!
section_flag
&&
mot
==
"Section"
)
{
Parser
::
strNext
(
mot
,
line
);
// search for ":"
size_t
pos
=
mot
.
find
(
":"
);
std
::
string
id
;
std
::
string
sec_name
;
if
(
pos
!=
std
::
string
::
npos
)
{
id
=
mot
.
substr
(
pos
+
1
);
sec_name
=
mot
.
substr
(
0
,
pos
);
}
else
sec_name
=
mot
;
if
(
section_name
==
sec_name
&&
id
==
section_id
)
{
section_flag
=
true
;
found_section
=
true
;
UnitSystem
units
;
try
{
Parser
::
parse
(
units
,
line
);
}
catch
(
LibMultiScaleException
&
e
)
{
LM_FATAL
(
"unit system was not provided for section "
<<
section_name
);
}
section_units
.
push_back
(
units
);
units_converter
.
setInUnits
(
section_units
.
back
());
units_converter
.
computeConversions
();
continue
;
}
}
if
(
section_flag
&&
mot
==
"endSection"
)
{
section_flag
=
false
;
section_units
.
pop_back
();
if
(
section_units
.
size
()
>
0
)
units_converter
.
setInUnits
(
section_units
.
back
());
units_converter
.
computeConversions
();
}
if
(
section_flag
)
{
substituteVariables
(
buffer
);
UInt
result
=
parseGenericKeywords
(
buffer
,
obj
);
if
(
!
result
)
result
=
obj
.
parseLine
(
buffer
);
if
(
!
result
)
LM_FATAL
(
"not parsed line "
<<
buffer
);
}
}
// if (section_units.back() != real_unit_system)
// LM_FATAL("problem in piling the section units");
if
(
!
found_section
)
LM_FATAL
(
"section named "
<<
section_name
<<
" with id "
<<
section_id
<<
" is missing"
);
/// pop the current file from stack
opened_files
.
pop_back
();
current_line
.
pop_back
();
if
(
section_units
.
size
()
>
0
)
units_converter
.
setInUnits
(
section_units
.
back
());
units_converter
.
computeConversions
();
opened_ifstreams
.
pop_back
();
DUMP
(
"parser state "
<<
opened_files
.
size
()
<<
" "
<<
current_line
.
size
()
<<
" "
<<
Parser
::
getParserState
(),
DBG_INFO
);
}
/* -------------------------------------------------------------------------- */
void
Parser
::
substituteVariables
(
std
::
string
&
str
)
{
size_t
pos
=
str
.
find
(
"${"
);
while
(
pos
!=
std
::
string
::
npos
)
{
size_t
pos2
=
str
.
find
(
"}"
,
pos
);
if
(
pos2
==
std
::
string
::
npos
)
LM_FATAL
(
"syntax error: unclosed ${ } sequence
\n
"
<<
Parser
::
getParserState
());
std
::
string
varname
=
str
.
substr
(
pos
+
2
,
pos2
-
pos
-
2
);
Real
res
;
try
{
math_parser
.
parse
(
varname
,
res
);
}
catch
(
std
::
string
mess
)
{
LM_FATAL
(
getParserState
()
<<
std
::
endl
<<
"
\"
"
<<
str
<<
"
\"
"
<<
std
::
endl
<<
mess
);
}
std
::
stringstream
tmp
;
tmp
<<
res
;
str
.
replace
(
pos
,
pos2
-
pos
+
1
,
tmp
.
str
());
pos
=
str
.
find
(
"${"
);
}
pos
=
str
.
find
(
"$("
);
while
(
pos
!=
std
::
string
::
npos
)
{
size_t
pos2
=
str
.
find
(
")"
,
pos
);
if
(
pos2
==
std
::
string
::
npos
)
LM_FATAL
(
"syntax error: unclosed $( ) sequence"
);
std
::
string
varname
=
str
.
substr
(
pos
+
2
,
pos2
-
pos
-
2
);
char
*
var
=
lm_getenv
(
varname
.
c_str
());
if
(
var
!=
NULL
)
str
.
replace
(
pos
,
pos2
-
pos
+
1
,
var
);
else
LM_FATAL
(
getParserState
()
<<
std
::
endl
<<
"
\"
"
<<
str
<<
"
\"
"
<<
std
::
endl
<<
"environment variable "
<<
varname
<<
" was not defined"
);
pos
=
str
.
find
(
"$("
);
}
}
/* -------------------------------------------------------------------------- */
UInt
Parser
::
parseGenericKeywords
(
std
::
string
&
linebuffer
,
Parsable
&
obj
)
{
std
::
stringstream
line
(
linebuffer
);
std
::
string
mot
;
Parser
::
strNext
(
mot
,
line
);
if
(
mot
==
"LET"
)
{
std
::
stringstream
var_buffer
;
try
{
while
(
1
)
{
std
::
string
mot
;
strNext
(
mot
,
line
);
var_buffer
<<
mot
<<
" "
;
}
}
catch
(
LibMultiScaleException
&
e
)
{
if
(
std
::
string
(
e
.
what
())
==
std
::
string
(
"unable to parse word"
))
{
}
else
{
LM_FATAL
(
e
.
what
()
<<
std
::
endl
<<
getParserState
());
}
}
try
{
Real
res
;
math_parser
.
parse
(
var_buffer
.
str
(),
res
);
}
catch
(
LibMultiScaleException
&
e
)
{
LM_FATAL
(
e
.
what
()
<<
std
::
endl
<<
" cannot parse algebraic expression "
<<
var_buffer
.
str
()
<<
getParserState
());
}
return
true
;
}
else
if
(
mot
==
"PRINT"
)
{
Real
value
;
if
(
math_parser
.
parse
(
line
.
str
().
substr
(
line
.
tellg
()),
value
))
{
std
::
string
key
;
line
>>
key
;
DUMPFILE
(
fout
,
key
<<
" = "
<<
value
);
}
else
return
false
;
return
true
;
}
else
if
(
mot
==
"INCLUDE"
)
{
Parser
::
strNext
(
mot
,
line
);
if
(
mot
==
"this"
)
{
mot
=
opened_files
.
back
();
}
std
::
string
section
;
try
{
strNext
(
section
,
line
);
}
catch
(
LibMultiScaleException
&
e
)
{
LM_FATAL
(
" Missing section name in line "
<<
current_line
.
back
()
<<
": '"
<<
line
.
str
()
<<
"'"
<<
getParserState
());
}
try
{
std
::
string
id
;
strNext
(
id
,
line
);
parseConfigFile
(
mot
,
section
,
id
,
obj
);
}
catch
(
LibMultiScaleException
&
e
)
{
parseConfigFile
(
mot
,
section
,
""
,
obj
);
}
return
true
;
}
else
if
(
mot
==
"FOR"
)
{
std
::
string
mot
;
// save starting point
for_starting_line
.
push_back
(
current_line
.
back
()
+
1
);
Parser
::
strNext
(
mot
,
line
);
// read name of the for variable
for_var
.
push_back
(
mot
);
Parser
::
strNext
(
mot
,
line
);
UInt
pos
=
line
.
tellg
();
if
(
mot
!=
"in"
||
pos
==
line
.
str
().
length
())
LM_FATAL
(
getParserState
()
<<
std
::
endl
<<
"
\"
"
<<
line
.
str
()
<<
"
\"
"
<<
std
::
endl
<<
"sytax error in for loop"
);
// construct the items to iterate
std
::
string
buffer
=
line
.
str
().
substr
(
pos
);
std
::
stringstream
items
(
buffer
);
Parser
::
strNext
(
mot
,
items
);
std
::
list
<
std
::
string
>
item_vec
;
if
(
mot
==
"range"
)
{
UInt
start
,
end
,
increment
;
parse
(
start
,
items
);
parse
(
end
,
items
);
parse
(
increment
,
items
);
for
(
UInt
i
=
start
;
i
<
end
;
i
+=
increment
)
{
std
::
stringstream
sstr
;
sstr
<<
i
;
item_vec
.
push_back
(
sstr
.
str
());
}
}
else
{
while
(
!
items
.
fail
())
{
item_vec
.
push_back
(
mot
);
try
{
Parser
::
strNext
(
mot
,
items
);
}
catch
(
LibMultiScaleException
&
e
)
{
}
}
}
for_items
.
push_back
(
item_vec
);
std
::
string
value
;
value
=
for_items
.
back
().
front
();
for_items
.
back
().
pop_front
();
// set the variable to the correct initial value
Real
res
;
math_parser
.
parse
(
for_var
.
back
()
+
" = "
+
value
,
res
);
return
true
;
}
else
if
(
mot
==
"endFOR"
)
{
UInt
nb_items_left
=
for_items
.
back
().
size
();
// set the variable to the next value
if
(
nb_items_left
==
0
)
{
// it is the end of the loop then
math_parser
.
eraseVariable
(
for_var
.
back
());
for_starting_line
.
pop_back
();
for_items
.
pop_back
();
for_var
.
pop_back
();
}
else
{
std
::
string
value
;
value
=
for_items
.
back
().
front
();
for_items
.
back
().
pop_front
();
DUMPFILE
(
Parser
::
fout
,
"inside of var loop "
<<
for_var
.
back
()
<<
" now takes the value "
<<
value
);
// set the variable to the correct initial value
Real
res
;
math_parser
.
parse
(
for_var
.
back
()
+
" = "
+
value
,
res
);
// rewind the file to the correct line
rewindToLine
(
for_starting_line
.
back
());
}
return
true
;
}
return
false
;
}
/* -------------------------------------------------------------------------- */
inline
std
::
string
Parser
::
getParserState
()
{
std
::
vector
<
std
::
string
>::
iterator
it_file
=
opened_files
.
begin
();
std
::
vector
<
std
::
string
>::
iterator
end_file
=
opened_files
.
end
();
std
::
vector
<
UInt
>::
iterator
it_line
=
current_line
.
begin
();
std
::
stringstream
res
;
while
(
it_file
!=
end_file
)
{
res
<<
std
::
endl
<<
"
\t
"
<<
*
it_file
<<
":"
<<
*
it_line
;
++
it_file
;
++
it_line
;
}
return
res
.
str
();
}
/* -------------------------------------------------------------------------- */
std
::
map
<
std
::
string
,
double
>
&
Parser
::
getAlgebraicVariables
()
{
return
math_parser
.
getVariables
();
}
/* -------------------------------------------------------------------------- */
UInt
Parser
::
strNext
(
std
::
string
&
str
,
std
::
stringstream
&
line
)
{
UInt
word_counter
=
0
;
line
>>
str
;
if
(
line
.
fail
())
LM_THROW
(
"unable to parse word"
);
++
word_counter
;
if
(
str
[
0
]
==
'"'
)
{
str
=
str
.
substr
(
1
);
unsigned
long
found
=
str
.
find_first_of
(
"
\"
"
);
while
(
found
==
std
::
string
::
npos
)
{
UInt
pos
=
line
.
tellg
();
if
(
pos
<
line
.
str
().
length
())
{
std
::
string
tmp_str
;
line
>>
tmp_str
;
if
(
line
.
fail
())
LM_THROW
(
"unable to parse word"
);
++
word_counter
;
str
+=
" "
+
tmp_str
;
found
=
str
.
find_first_of
(
"
\"
"
);
}
else
LM_FATAL
(
"unterminated quoted sequence"
);
}
if
(
found
!=
str
.
size
()
-
1
)
LM_FATAL
(
"quotes must be followed by a whitespace"
);
str
=
str
.
substr
(
0
,
found
);
}
return
word_counter
;
}
/* -------------------------------------------------------------------------- */
void
Parser
::
shiftLine
(
const
ParseResult
&
parsed
,
std
::
stringstream
&
line
)
{
std
::
string
buf
;
for
(
UInt
i
=
0
;
i
<
parsed
.
nb_word_parsed
;
++
i
)
{
line
>>
buf
;
if
(
line
.
fail
())
LM_THROW
(
"unable to shift "
<<
parsed
.
nb_word_parsed
<<
" words"
);
}
}
/* -------------------------------------------------------------------------- */
UInt
_parse
(
std
::
map
<
std
::
string
,
ArgumentContainer
*>
&
inputs
,
std
::
stringstream
&
line
,
UInt
n_entries
)
{
std
::
string
buffer
;
std
::
string
component_name
;
std
::
string
output_name
;
std
::
string
input_name
;
UInt
nb
=
Parser
::
strNext
(
buffer
,
line
);
auto
pos
=
buffer
.
find
(
"="
);
if
(
pos
!=
std
::
string
::
npos
)
{
input_name
=
buffer
.
substr
(
0
,
pos
);
component_name
=
buffer
.
substr
(
pos
+
1
);
}
else
{
input_name
=
"input1"
;
component_name
=
buffer
;
}
pos
=
component_name
.
find
(
"."
);
if
(
pos
!=
std
::
string
::
npos
)
{
output_name
=
component_name
.
substr
(
pos
+
1
);
component_name
=
component_name
.
substr
(
0
,
pos
);
}
else
{
output_name
=
"output"
;
}
DUMP
(
input_name
<<
" "
<<
component_name
<<
" "
<<
output_name
,
DBG_DETAIL
);
auto
connect
=
[
&
](
auto
&
manager
)
{
auto
&
component
=
manager
.
getObject
(
component_name
);
auto
search
=
inputs
.
find
(
input_name
);
if
(
search
==
inputs
.
end
())
{
DUMP
(
input_name
+
": input not existing"
,
DBG_MESSAGE
);
if
(
inputs
.
size
()
>
0
)
{
DUMP
(
"Possible inputs are:"
,
DBG_MESSAGE
);
for
(
auto
p
:
inputs
)
{
DUMP
(
"
\t
"
+
p
.
first
+
"
\n
"
,
DBG_MESSAGE
);
}
}
else
{
DUMP
(
"there are no possible inputs"
,
DBG_MESSAGE
);
}
LM_FATAL
(
"abort:"
+
input_name
+
": input not existing"
);
}
inputs
[
input_name
]
=
&
component
.
getOutput
(
output_name
);
};
try
{
connect
(
DomainMultiScale
::
getManager
());
}
catch
(
UnknownID
&
e
)
{
try
{
connect
(
FilterManager
::
getManager
());
}
catch
(
LibMultiScaleException
&
e
)
{
LM_THROW
(
"id "
<<
input_name
<<
" is most probably not a valid input "
<<
std
::
endl
<<
e
.
what
());
}
}
return
nb
;
}
/* -------------------------------------------------------------------------- */
/// static instanciation
/* -------------------------------------------------------------------------- */
UnitsConverter
Parser
::
units_converter
;
std
::
vector
<
UnitSystem
>
Parser
::
section_units
;
AlgebraicExpressionParser
Parser
::
math_parser
;
std
::
ofstream
Parser
::
fout
(
"log.parser"
,
std
::
ios_base
::
out
);
std
::
vector
<
std
::
string
>
Parser
::
opened_files
;
std
::
vector
<
UInt
>
Parser
::
current_line
;
std
::
vector
<
std
::
ifstream
*>
Parser
::
opened_ifstreams
;
std
::
vector
<
UInt
>
Parser
::
for_starting_line
;
std
::
vector
<
std
::
list
<
std
::
string
>>
Parser
::
for_items
;
std
::
vector
<
std
::
string
>
Parser
::
for_var
;
__END_LIBMULTISCALE__
Event Timeline
Log In to Comment