pydot
pydot copied to clipboard
Parser error for final ';'
Hi all,
Is this an error or an expected behaviour ? Using this code :
import pydot
print(pydot.graph_from_dot_data('''graph G {
A--B
}''')[0].to_string())
print(pydot.graph_from_dot_data('''graph G {
A--B;
}''')[0].to_string())
I can see :

The comma at line 8 seems to create a node "\n" in the graph ??
Thanks,
PS: windows, python3.10, pydot1.4.2, pyparsing3.0.7
I've been able to reproduce this bug locally too and it looks like it's an issue caused by the later releases of pyparsing. Using 'graph {\n0 ;\n1 ;\n2 ;\n0 -- 1 ;\n1 -- 2 ;\n2 -- 0 ;\n}\n' as a test string I was able to confirm that running with pyparsing<=3.0.1 pydot parses the string correctly but running with pyparsing>=3.0.3 the extra newline node is added to the parsed output (pyparsing 3.0.2 raised an error trying to parse the string).
I hit this same issue and did a little digging into the root cause. I think the issue is the \n after the edge is matched by the ID (node_id), alphastring_ option, of node_stmt.
Excluding '\n' from alphastring_ seems to fix the issue:
alphastring_ = OneOrMore(CharsNotIn(noncomma + " \n"))
If this is the correct fix, '\r' and '\t' should probably be excluded too.
Here is a unit test that can be added to the test suite for this issue:
def test_parse_white_space(self):
g = pydot.graph_from_dot_data('graph {\n1;\n2;\n2 -- 1;\n}')
self.assertEqual(2, len(g[0].get_node_list()))
FWIW, I think the reason this doesn't happen with a node at the end of the graph is because the node_stmt includes Optional(semi.suppress()) which matches the ';' and then the Optional(semi.suppress()) in stmt_list skips the '\n'.
just ran into the same problem with a ghost "\n" node before graph closing '}'
'name': '"\\n"',
'parent_graph': <pydot.Dot object at 0x7fe11c6eee48>,
'parent_node_list': None,
'port': None,
'sequence': 66,
'type': 'node'}],
and came up with same fix for alphastring_ to include newline. also had issues with the keywords not being registered as such instead of literals.
Fixed