Definition
An instance parser of the data type gml_graph is a parser for graphs
in GML format [42]. It is possible to extend the parser by
user defined rules. This parser is used by the
readgml of class
graph. The following is small example graph (a triangle) in GML format.
# This is a comment.
graph [ # Lists start with '['.
directed 1 # This is a directed graph (0 for undirected).
# The following is an object of type string.
# It will be ignored unless you specify a rule for graph.text.
text "This is a string object."
node [ id 1 ] # This defines a node with id 1.
node [ id 2 ]
node [ id 3 ]
edge [ # This defines an edge leading from node 1 to node 2.
source 1
target 2
]
edge [
source 2
target 3
]
edge [
source 3
target 1
]
] # Lists end with ']'.
An input in GML format is a list of GML objects. Each object consists
of a key word and a value. A value may have one out of four possible
types, an integer (type
gmlint), a double (type
gml
double),
a string (type
gml
string), or a list of GML objects (type
gml
list). Since a value can be a list of objects, we get a tree
structure on the input. We can describe a class C of objects being
in the same list and having the same key word by the so-called path.
The path is the list of key words leading to an object in the class C.
In principle, every data structure can be expressed in GML format.
This parser specializes on graphs. A graph is represented by an object
with key word graph and type
gmllist. The nodes of the graph
are objects with path
graph.node and type
gml
list. Each node
has a unique identifier, which is represented by an object of type
gml
int with path
graph.node.id. An edge is an object of type
gml
list with the path
graph.edge. Each edge has a source and
a target. These are objects of type
gml
int with path
graph.edge.source
and
graph.edge.target, respectively. The integer values of source
and target refer to node identifiers. There are some global graph
attributes, too. An object of type
gml
int with path
graph.directed
determines whether the graph is undirected (value 0) or directed
(every other integer). The type of node parameters and edge parameters
in parameterized graphs (see manual page GRAPH) can be given by
objects of type
gml
string with path
graph.nodeType and
graph.edgeType, respectively. Parameters of nodes and edges
are represented by objects of type
gml
string with path
graph.node.parameter and
graph.edge.parameter, respectively.
No list has to be in a specific order, e.g., you can freely mix node and edge objects in the graph list. If there are several objects in a class where just one object is required like graph.node.id, only the last such object is taken into account.
Objects in classes with no predefined rules are simply ignored. This means that an application A might add specific objects to a graph description in GML format and this description is still readable for another application B which simply does not care about the objects which are specific for A.
This parser supports reading user defined objects by providing
a mechanism for dealing with those objects by means of callback
functions. You can specify a rule for, e.g., objects with path
graph.node.weight and type
gmldouble like in the following
code fragment.
...
bool get_node_weight(const gml_object* gobj, graph* G, node v)
{
double w = gobj->get_double();
do something with w, the graph and the corresponding node v
return true; or false if the operation failed
}
...
main()
{
char* filename;
...
graph G;
gml_graph parser(G);
parser.add_node_rule(get_node_weight,gml_double,"weight");
bool parsing_ok = parser.parse(filename);
...
}
You can add rules for the graph, for nodes, and for edges. The difference between them is the type. The type of node rules is as in the example above bool (*gml_node_rule)(const gml_object*, graph*, node), the type for edge rules is bool (*gml_edge_rule)(const gml_object*, graph*, edge), and the type for graph rules is bool (*gml_graph_rule)(const gml_object*, graph*). A GML object is represented by an instance of class gml_object. You can get its value by using double gml_object::get_double(), int gml_object::get_int() or char* gml_object::get_string(). If one of your rules returns false during parsing, then parsing fails and the graph is cleared.
#include < LEDA/gml _graph.h >
Creation
gml_graph | parser(graph& G) | creates an instance parser of type gml_graph and initializes it for graph G. |
gml_graph | parser(graph& G, const char* filename) | |
creates an instance parser of type gml_graph and reads graph G from the file filename. | ||
gml_graph | parser(graph& G, istream& ins) | |
creates an instance parser of type gml_graph and reads graph G from the input stream ins. |
Operations
3.1 Parsing
bool | parser.parse(const char* filename) | |
parses the input taken from the file filename using the current set of rules. The graph specified in the constructor is set up accordingly. This operations returns false and clears the graph, if syntax or parse errors occur. Otherwise true is returned. | ||
bool | parser.parse(istream& ins) | |
parses the input taken from the input stream ins. | ||
bool | parser.parse_string(string s) | |
parses the input taken from string s. |
3.2 Path Manipulation
3.3 User Defined Rules
Implementation
The data type gml_graph is realized using lists and maps. It inherits from gml_parser which uses gml_object, gml_objecttree, and gml_pattern. gml_pattern uses dictionaries.