diff options
author | Michael Milton <ttmigueltt@gmail.com> | 2020-06-25 08:13:17 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-06-24 17:13:17 -0500 |
commit | efb796099fd77d003dcd49df6a75d1dcc19cefb1 (patch) | |
tree | dd7b862691bfbad2f2ef7d0ef6c2f17908755cc5 | |
parent | e91acdf0d3e405ce4b02d2c4f27c51e223a01b59 (diff) | |
download | pyparsing-git-efb796099fd77d003dcd49df6a75d1dcc19cefb1.tar.gz |
Diagram improvements IV (#225)
* Add diagram documentation, add more diagram tests, allow more
customization of diagrams
* Remove accidental edit of unrelated documentation
* Add diagram package
* Add jinja file to manifest
* Add to bdist also
* package_data
* Railroad improvements
* Partial rewrite
* Update
* Use partials everywhere so we can edit the tree before it's constructed
* Rewrite the diagram generator to not duplicate any content; use
monospaced font for titles
* Small documentation change
* Revert back to Python 3.5 type hints, fix a small bug
* More diagram fixes
* Even more pruning; update docs to use SQL example
* Don't check the string value of names now that we don't have to
-rw-r--r-- | docs/HowToUsePyparsing.rst | 2 | ||||
-rw-r--r-- | docs/_static/json.html | 231 | ||||
-rw-r--r-- | docs/_static/sql_railroad.html | 503 | ||||
-rw-r--r-- | pyparsing/diagram/__init__.py | 281 | ||||
-rw-r--r-- | tests/test_diagram.py | 18 |
5 files changed, 668 insertions, 367 deletions
diff --git a/docs/HowToUsePyparsing.rst b/docs/HowToUsePyparsing.rst index 9af6862..218aa58 100644 --- a/docs/HowToUsePyparsing.rst +++ b/docs/HowToUsePyparsing.rst @@ -1069,7 +1069,7 @@ This will result in the railroad diagram being written to ``output.html`` Example ------- -You can view an example railroad diagram generated from a pyparsing grammar `here <_static/json.html>`_. +You can view an example railroad diagram generated from a pyparsing grammar for SQL ``SELECT`` statements `here <_static/sql_railroad.html>`_. Customization ------------- diff --git a/docs/_static/json.html b/docs/_static/json.html deleted file mode 100644 index 7067e5e..0000000 --- a/docs/_static/json.html +++ /dev/null @@ -1,231 +0,0 @@ -<!DOCTYPE html> -<html> -<head> - - <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300&display=swap" rel="stylesheet"> - <style type="text/css"> - .railroad-heading { - font-family: 'Roboto', sans-serif; - } - </style> - -</head> -<body> - - - <div class="railroad-group"> - <h1 class="railroad-heading">Grammar</h1> - <div class="railroad-description"></div> - <div class="railroad-svg"> - <svg class="railroad-diagram" height="62" viewBox="0 0 179.5 62" width="179.5" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(.5 .5)"> -<style>/* <![CDATA[ */ - svg.railroad-diagram { - background-color:hsl(30,20%,95%); - } - svg.railroad-diagram path { - stroke-width:3; - stroke:black; - fill:rgba(0,0,0,0); - } - svg.railroad-diagram text { - font:bold 14px monospace; - text-anchor:middle; - } - svg.railroad-diagram text.label{ - text-anchor:start; - } - svg.railroad-diagram text.comment{ - font:italic 12px monospace; - } - svg.railroad-diagram rect{ - stroke-width:3; - stroke:black; - fill:hsl(120,100%,90%); - } - svg.railroad-diagram rect.group-box { - stroke: gray; - stroke-dasharray: 10 5; - fill: none; - } - -/* ]]> */ -</style><g> -<path d="M20 21v20m10 -20v20m-10 -10h20"></path></g><path d="M40 31h10"></path><g class="non-terminal"> -<path d="M50 31h0.0"></path><path d="M129.5 31h0.0"></path><rect height="22" width="79.5" x="50.0" y="20"></rect><text x="89.75" y="35">Group 1</text></g><path d="M129.5 31h10"></path><path d="M 139.5 31 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> - </div> - </div> - - <div class="railroad-group"> - <h1 class="railroad-heading">Group 1</h1> - <div class="railroad-description"></div> - <div class="railroad-svg"> - <svg class="railroad-diagram" height="166" viewBox="0 0 2205.0 166" width="2205.0" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(.5 .5)"> -<style>/* <![CDATA[ */ - svg.railroad-diagram { - background-color:hsl(30,20%,95%); - } - svg.railroad-diagram path { - stroke-width:3; - stroke:black; - fill:rgba(0,0,0,0); - } - svg.railroad-diagram text { - font:bold 14px monospace; - text-anchor:middle; - } - svg.railroad-diagram text.label{ - text-anchor:start; - } - svg.railroad-diagram text.comment{ - font:italic 12px monospace; - } - svg.railroad-diagram rect{ - stroke-width:3; - stroke:black; - fill:hsl(120,100%,90%); - } - svg.railroad-diagram rect.group-box { - stroke: gray; - stroke-dasharray: 10 5; - fill: none; - } - -/* ]]> */ -</style><g> -<path d="M20 93v20m10 -20v20m-10 -10h20"></path></g><path d="M40 103h10"></path><g> -<path d="M50 103h0.0"></path><path d="M2155.0 103h0.0"></path><rect class="group-box" height="110" rx="10" ry="10" width="2105.0" x="50.0" y="36"></rect><g> -<path d="M50.0 103h10.0"></path><path d="M2145.0 103h10.0"></path><g> -<path d="M60.0 103h0.0"></path><path d="M2059.0 103h0.0"></path><g> -<path d="M60.0 103h0.0"></path><path d="M126.0 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="60.0" y="84"></rect><g class="terminal"> -<path d="M60.0 103h10.25"></path><path d="M115.75 103h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="70.25" y="92"></rect><text x="93.0" y="107">"{"</text></g><g> -<path d="M60.0 76h0.0"></path><path d="M126.0 76h0.0"></path><text class="comment" x="93.0" y="81">Suppress</text></g></g><path d="M126.0 103h10"></path><g> -<path d="M136.0 103h0.0"></path><path d="M2059.0 103h0.0"></path><path d="M136.0 103a10 10 0 0 0 10 -10v-39a10 10 0 0 1 10 -10"></path><g> -<path d="M156.0 44h1883.0"></path></g><path d="M2039.0 44a10 10 0 0 1 10 10v39a10 10 0 0 0 10 10"></path><path d="M136.0 103h20"></path><g> -<path d="M156.0 103h0.0"></path><path d="M2039.0 103h0.0"></path><g> -<path d="M156.0 103h0.0"></path><path d="M1019.5 103h0.0"></path><rect class="group-box" height="70" rx="10" ry="10" width="863.5" x="156.0" y="60"></rect><g> -<path d="M156.0 103h10.0"></path><path d="M1009.5 103h10.0"></path><g> -<path d="M166.0 103h0.0"></path><path d="M910.0 103h0.0"></path><g> -<path d="M166.0 103h0.0"></path><path d="M824.0 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="658.0" x="166.0" y="84"></rect><g> -<path d="M166.0 103h10.0"></path><path d="M814.0 103h10.0"></path><g class="terminal"> -<path d="M176.0 103h0.0"></path><path d="M748.5 103h0.0"></path><rect height="22" rx="10" ry="10" width="572.5" x="176.0" y="92"></rect><text x="462.25" y="107">Re:('"(?:[^"\\n\\r\\\\]|(?:"")|(?:\\\\(?:[^x]|x[0-9a-fA-F]+)))*')</text></g><path d="M748.5 103h10"></path><path d="M758.5 103h10"></path><g class="terminal"> -<path d="M768.5 103h0.0"></path><path d="M814.0 103h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="768.5" y="92"></rect><text x="791.25" y="107">"""</text></g></g><g> -<path d="M166.0 76h0.0"></path><path d="M400.0 76h0.0"></path><text class="comment" x="283.0" y="81">string enclosed in double quotes</text></g></g><path d="M824.0 103h10"></path><path d="M834.0 103h10"></path><g> -<path d="M844.0 103h0.0"></path><path d="M910.0 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="844.0" y="84"></rect><g class="terminal"> -<path d="M844.0 103h10.25"></path><path d="M899.75 103h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="854.25" y="92"></rect><text x="877.0" y="107">":"</text></g><g> -<path d="M844.0 76h0.0"></path><path d="M910.0 76h0.0"></path><text class="comment" x="877.0" y="81">Suppress</text></g></g></g><path d="M910.0 103h10"></path><path d="M920.0 103h10"></path><g class="non-terminal"> -<path d="M930.0 103h0.0"></path><path d="M1009.5 103h0.0"></path><rect height="22" width="79.5" x="930.0" y="92"></rect><text x="969.75" y="107">Group 2</text></g></g></g><path d="M1019.5 103h10"></path><g> -<path d="M1029.5 103h0.0"></path><path d="M2039.0 103h0.0"></path><path d="M1029.5 103a10 10 0 0 0 10 -10v-31a10 10 0 0 1 10 -10"></path><g> -<path d="M1049.5 52h969.5"></path></g><path d="M2019.0 52a10 10 0 0 1 10 10v31a10 10 0 0 0 10 10"></path><path d="M1029.5 103h20"></path><g> -<path d="M1049.5 103h0.0"></path><path d="M2019.0 103h0.0"></path><path d="M1049.5 103h10"></path><g> -<path d="M1059.5 103h0.0"></path><path d="M2009.0 103h0.0"></path><g> -<path d="M1059.5 103h0.0"></path><path d="M1125.5 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="1059.5" y="84"></rect><g class="terminal"> -<path d="M1059.5 103h10.25"></path><path d="M1115.25 103h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="1069.75" y="92"></rect><text x="1092.5" y="107">","</text></g><g> -<path d="M1059.5 76h0.0"></path><path d="M1125.5 76h0.0"></path><text class="comment" x="1092.5" y="81">Suppress</text></g></g><path d="M1125.5 103h10"></path><path d="M1135.5 103h10"></path><g> -<path d="M1145.5 103h0.0"></path><path d="M2009.0 103h0.0"></path><rect class="group-box" height="70" rx="10" ry="10" width="863.5" x="1145.5" y="60"></rect><g> -<path d="M1145.5 103h10.0"></path><path d="M1999.0 103h10.0"></path><g> -<path d="M1155.5 103h0.0"></path><path d="M1899.5 103h0.0"></path><g> -<path d="M1155.5 103h0.0"></path><path d="M1813.5 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="658.0" x="1155.5" y="84"></rect><g> -<path d="M1155.5 103h10.0"></path><path d="M1803.5 103h10.0"></path><g class="terminal"> -<path d="M1165.5 103h0.0"></path><path d="M1738.0 103h0.0"></path><rect height="22" rx="10" ry="10" width="572.5" x="1165.5" y="92"></rect><text x="1451.75" y="107">Re:('"(?:[^"\\n\\r\\\\]|(?:"")|(?:\\\\(?:[^x]|x[0-9a-fA-F]+)))*')</text></g><path d="M1738.0 103h10"></path><path d="M1748.0 103h10"></path><g class="terminal"> -<path d="M1758.0 103h0.0"></path><path d="M1803.5 103h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="1758.0" y="92"></rect><text x="1780.75" y="107">"""</text></g></g><g> -<path d="M1155.5 76h0.0"></path><path d="M1389.5 76h0.0"></path><text class="comment" x="1272.5" y="81">string enclosed in double quotes</text></g></g><path d="M1813.5 103h10"></path><path d="M1823.5 103h10"></path><g> -<path d="M1833.5 103h0.0"></path><path d="M1899.5 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="1833.5" y="84"></rect><g class="terminal"> -<path d="M1833.5 103h10.25"></path><path d="M1889.25 103h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="1843.75" y="92"></rect><text x="1866.5" y="107">":"</text></g><g> -<path d="M1833.5 76h0.0"></path><path d="M1899.5 76h0.0"></path><text class="comment" x="1866.5" y="81">Suppress</text></g></g></g><path d="M1899.5 103h10"></path><path d="M1909.5 103h10"></path><g class="non-terminal"> -<path d="M1919.5 103h0.0"></path><path d="M1999.0 103h0.0"></path><rect height="22" width="79.5" x="1919.5" y="92"></rect><text x="1959.25" y="107">Group 2</text></g></g></g></g><path d="M2009.0 103h10"></path><path d="M1059.5 103a10 10 0 0 0 -10 10v15a10 10 0 0 0 10 10"></path><g> -<path d="M1059.5 138h949.5"></path></g><path d="M2009.0 138a10 10 0 0 0 10 -10v-15a10 10 0 0 0 -10 -10"></path></g><path d="M2019.0 103h20"></path></g></g><path d="M2039.0 103h20"></path></g></g><path d="M2059.0 103h10"></path><path d="M2069.0 103h10"></path><g> -<path d="M2079.0 103h0.0"></path><path d="M2145.0 103h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="2079.0" y="84"></rect><g class="terminal"> -<path d="M2079.0 103h10.25"></path><path d="M2134.75 103h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="2089.25" y="92"></rect><text x="2112.0" y="107">"}"</text></g><g> -<path d="M2079.0 76h0.0"></path><path d="M2145.0 76h0.0"></path><text class="comment" x="2112.0" y="81">Suppress</text></g></g></g><g> -<path d="M50.0 28h0.0"></path><path d="M88.0 28h0.0"></path><text class="comment" x="69.0" y="33">Dict</text></g></g><path d="M2155.0 103h10"></path><path d="M 2165.0 103 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> - </div> - </div> - - <div class="railroad-group"> - <h1 class="railroad-heading">Group 2</h1> - <div class="railroad-description"></div> - <div class="railroad-svg"> - <svg class="railroad-diagram" height="422" viewBox="0 0 978.0 422" width="978.0" xmlns="http://www.w3.org/2000/svg"> -<g transform="translate(.5 .5)"> -<style>/* <![CDATA[ */ - svg.railroad-diagram { - background-color:hsl(30,20%,95%); - } - svg.railroad-diagram path { - stroke-width:3; - stroke:black; - fill:rgba(0,0,0,0); - } - svg.railroad-diagram text { - font:bold 14px monospace; - text-anchor:middle; - } - svg.railroad-diagram text.label{ - text-anchor:start; - } - svg.railroad-diagram text.comment{ - font:italic 12px monospace; - } - svg.railroad-diagram rect{ - stroke-width:3; - stroke:black; - fill:hsl(120,100%,90%); - } - svg.railroad-diagram rect.group-box { - stroke: gray; - stroke-dasharray: 10 5; - fill: none; - } - -/* ]]> */ -</style><g> -<path d="M20 45v20m10 -20v20m-10 -10h20"></path></g><g> -<path d="M40 55h0.0"></path><path d="M938.0 55h0.0"></path><path d="M40.0 55h20"></path><g> -<path d="M60.0 55h0.0"></path><path d="M918.0 55h0.0"></path><path d="M60.0 55h20"></path><g> -<path d="M80.0 55h0.0"></path><path d="M898.0 55h0.0"></path><path d="M80.0 55h20"></path><g> -<path d="M100.0 55h0.0"></path><path d="M878.0 55h0.0"></path><path d="M100.0 55h20"></path><g> -<path d="M120.0 55h0.0"></path><path d="M858.0 55h0.0"></path><path d="M120.0 55h20"></path><g> -<path d="M140.0 55h0.0"></path><path d="M838.0 55h0.0"></path><path d="M140.0 55h20"></path><g> -<path d="M160.0 55h0.0"></path><path d="M818.0 55h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="658.0" x="160.0" y="36"></rect><g> -<path d="M160.0 55h10.0"></path><path d="M808.0 55h10.0"></path><g class="terminal"> -<path d="M170.0 55h0.0"></path><path d="M742.5 55h0.0"></path><rect height="22" rx="10" ry="10" width="572.5" x="170.0" y="44"></rect><text x="456.25" y="59">Re:('"(?:[^"\\n\\r\\\\]|(?:"")|(?:\\\\(?:[^x]|x[0-9a-fA-F]+)))*')</text></g><path d="M742.5 55h10"></path><path d="M752.5 55h10"></path><g class="terminal"> -<path d="M762.5 55h0.0"></path><path d="M808.0 55h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="762.5" y="44"></rect><text x="785.25" y="59">"""</text></g></g><g> -<path d="M160.0 28h0.0"></path><path d="M394.0 28h0.0"></path><text class="comment" x="277.0" y="33">string enclosed in double quotes</text></g></g><path d="M818.0 55h20"></path><path d="M140.0 55a10 10 0 0 1 10 10v18a10 10 0 0 0 10 10"></path><g> -<path d="M160.0 93h146.0"></path><path d="M672.0 93h146.0"></path><path d="M306.0 93h20"></path><g class="terminal"> -<path d="M326.0 93h0.0"></path><path d="M652.0 93h0.0"></path><rect height="22" rx="10" ry="10" width="326.0" x="326.0" y="82"></rect><text x="489.0" y="97">real number with scientific notation</text></g><path d="M652.0 93h20"></path><path d="M306.0 93a10 10 0 0 1 10 10v10a10 10 0 0 0 10 10"></path><g class="terminal"> -<path d="M326.0 123h106.25"></path><path d="M545.75 123h106.25"></path><rect height="22" rx="10" ry="10" width="113.5" x="432.25" y="112"></rect><text x="489.0" y="127">real number</text></g><path d="M652.0 123a10 10 0 0 0 10 -10v-10a10 10 0 0 1 10 -10"></path><path d="M306.0 93a10 10 0 0 1 10 10v40a10 10 0 0 0 10 10"></path><g class="terminal"> -<path d="M326.0 153h93.5"></path><path d="M558.5 153h93.5"></path><rect height="22" rx="10" ry="10" width="139.0" x="419.5" y="142"></rect><text x="489.0" y="157">signed integer</text></g><path d="M652.0 153a10 10 0 0 0 10 -10v-40a10 10 0 0 1 10 -10"></path></g><path d="M818.0 93a10 10 0 0 0 10 -10v-18a10 10 0 0 1 10 -10"></path></g><path d="M838.0 55h20"></path><path d="M120.0 55a10 10 0 0 1 10 10v116a10 10 0 0 0 10 10"></path><g> -<path d="M140.0 191h299.25"></path><path d="M538.75 191h299.25"></path><rect class="group-box" height="38" rx="10" ry="10" width="99.5" x="439.25" y="172"></rect><g class="non-terminal"> -<path d="M439.25 191h10.0"></path><path d="M528.75 191h10.0"></path><rect height="22" width="79.5" x="449.25" y="180"></rect><text x="489.0" y="195">Group 1</text></g></g><path d="M838.0 191a10 10 0 0 0 10 -10v-116a10 10 0 0 1 10 -10"></path></g><path d="M858.0 55h20"></path><path d="M100.0 55a10 10 0 0 1 10 10v202a10 10 0 0 0 10 10"></path><g> -<path d="M120.0 277h100.5"></path><path d="M757.5 277h100.5"></path><rect class="group-box" height="94" rx="10" ry="10" width="537.0" x="220.5" y="218"></rect><g> -<path d="M220.5 277h10.0"></path><path d="M747.5 277h10.0"></path><g> -<path d="M230.5 277h0.0"></path><path d="M661.5 277h0.0"></path><g> -<path d="M230.5 277h0.0"></path><path d="M296.5 277h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="230.5" y="258"></rect><g class="terminal"> -<path d="M230.5 277h10.25"></path><path d="M286.25 277h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="240.75" y="266"></rect><text x="263.5" y="281">"["</text></g><g> -<path d="M230.5 250h0.0"></path><path d="M296.5 250h0.0"></path><text class="comment" x="263.5" y="255">Suppress</text></g></g><path d="M296.5 277h10"></path><g> -<path d="M306.5 277h0.0"></path><path d="M661.5 277h0.0"></path><path d="M306.5 277a10 10 0 0 0 10 -10v-31a10 10 0 0 1 10 -10"></path><g> -<path d="M326.5 226h315.0"></path></g><path d="M641.5 226a10 10 0 0 1 10 10v31a10 10 0 0 0 10 10"></path><path d="M306.5 277h20"></path><g> -<path d="M326.5 277h0.0"></path><path d="M641.5 277h0.0"></path><g class="non-terminal"> -<path d="M326.5 277h0.0"></path><path d="M406.0 277h0.0"></path><rect height="22" width="79.5" x="326.5" y="266"></rect><text x="366.25" y="281">Group 2</text></g><path d="M406.0 277h10"></path><g> -<path d="M416.0 277h0.0"></path><path d="M641.5 277h0.0"></path><path d="M416.0 277a10 10 0 0 0 10 -10v-23a10 10 0 0 1 10 -10"></path><g> -<path d="M436.0 234h185.5"></path></g><path d="M621.5 234a10 10 0 0 1 10 10v23a10 10 0 0 0 10 10"></path><path d="M416.0 277h20"></path><g> -<path d="M436.0 277h0.0"></path><path d="M621.5 277h0.0"></path><path d="M436.0 277h10"></path><g> -<path d="M446.0 277h0.0"></path><path d="M611.5 277h0.0"></path><g> -<path d="M446.0 277h0.0"></path><path d="M512.0 277h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="446.0" y="258"></rect><g class="terminal"> -<path d="M446.0 277h10.25"></path><path d="M501.75 277h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="456.25" y="266"></rect><text x="479.0" y="281">","</text></g><g> -<path d="M446.0 250h0.0"></path><path d="M512.0 250h0.0"></path><text class="comment" x="479.0" y="255">Suppress</text></g></g><path d="M512.0 277h10"></path><path d="M522.0 277h10"></path><g class="non-terminal"> -<path d="M532.0 277h0.0"></path><path d="M611.5 277h0.0"></path><rect height="22" width="79.5" x="532.0" y="266"></rect><text x="571.75" y="281">Group 2</text></g></g><path d="M611.5 277h10"></path><path d="M446.0 277a10 10 0 0 0 -10 10v7a10 10 0 0 0 10 10"></path><g> -<path d="M446.0 304h165.5"></path></g><path d="M611.5 304a10 10 0 0 0 10 -10v-7a10 10 0 0 0 -10 -10"></path></g><path d="M621.5 277h20"></path></g></g><path d="M641.5 277h20"></path></g></g><path d="M661.5 277h10"></path><path d="M671.5 277h10"></path><g> -<path d="M681.5 277h0.0"></path><path d="M747.5 277h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="681.5" y="258"></rect><g class="terminal"> -<path d="M681.5 277h10.25"></path><path d="M737.25 277h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="691.75" y="266"></rect><text x="714.5" y="281">"]"</text></g><g> -<path d="M681.5 250h0.0"></path><path d="M747.5 250h0.0"></path><text class="comment" x="714.5" y="255">Suppress</text></g></g></g></g><path d="M858.0 277a10 10 0 0 0 10 -10v-202a10 10 0 0 1 10 -10"></path></g><path d="M878.0 55h20"></path><path d="M80.0 55a10 10 0 0 1 10 10v256a10 10 0 0 0 10 10"></path><g class="terminal"> -<path d="M100.0 331h353.5"></path><path d="M524.5 331h353.5"></path><rect height="22" rx="10" ry="10" width="71.0" x="453.5" y="320"></rect><text x="489.0" y="335">"true"</text></g><path d="M878.0 331a10 10 0 0 0 10 -10v-256a10 10 0 0 1 10 -10"></path></g><path d="M898.0 55h20"></path><path d="M60.0 55a10 10 0 0 1 10 10v286a10 10 0 0 0 10 10"></path><g class="terminal"> -<path d="M80.0 361h369.25"></path><path d="M528.75 361h369.25"></path><rect height="22" rx="10" ry="10" width="79.5" x="449.25" y="350"></rect><text x="489.0" y="365">"false"</text></g><path d="M898.0 361a10 10 0 0 0 10 -10v-286a10 10 0 0 1 10 -10"></path></g><path d="M918.0 55h20"></path><path d="M40.0 55a10 10 0 0 1 10 10v316a10 10 0 0 0 10 10"></path><g class="terminal"> -<path d="M60.0 391h393.5"></path><path d="M524.5 391h393.5"></path><rect height="22" rx="10" ry="10" width="71.0" x="453.5" y="380"></rect><text x="489.0" y="395">"null"</text></g><path d="M918.0 391a10 10 0 0 0 10 -10v-316a10 10 0 0 1 10 -10"></path></g><path d="M 938.0 55 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> - </div> - </div> - -</body> -</html>
\ No newline at end of file diff --git a/docs/_static/sql_railroad.html b/docs/_static/sql_railroad.html new file mode 100644 index 0000000..0393349 --- /dev/null +++ b/docs/_static/sql_railroad.html @@ -0,0 +1,503 @@ +<!DOCTYPE html> +<html> +<head> + + <style type="text/css"> + .railroad-heading { + font-family: monospace; + } + </style> + +</head> +<body> + + + <div class="railroad-group"> + <h1 class="railroad-heading">Forward</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="172" viewBox="0 0 1344.0 172" width="1344.0" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 53v20m10 -20v20m-10 -10h20"></path></g><path d="M40 63h10"></path><g> +<path d="M50 63h0.0"></path><path d="M1294.0 63h0.0"></path><g> +<path d="M50.0 63h0.0"></path><path d="M1048.0 63h0.0"></path><g> +<path d="M50.0 63h0.0"></path><path d="M662.0 63h0.0"></path><g> +<path d="M50.0 63h0.0"></path><path d="M571.0 63h0.0"></path><g class="terminal"> +<path d="M50.0 63h0.0"></path><path d="M138.0 63h0.0"></path><rect height="22" rx="10" ry="10" width="88.0" x="50.0" y="52"></rect><text x="94.0" y="67">'select'</text></g><path d="M138.0 63h10"></path><g> +<path d="M148.0 63h0.0"></path><path d="M571.0 63h0.0"></path><path d="M148.0 63h20"></path><g class="terminal"> +<path d="M168.0 63h168.75"></path><path d="M382.25 63h168.75"></path><rect height="22" rx="10" ry="10" width="45.5" x="336.75" y="52"></rect><text x="359.5" y="67">'*'</text></g><path d="M551.0 63h20"></path><path d="M148.0 63a10 10 0 0 1 10 10v42a10 10 0 0 0 10 10"></path><g> +<path d="M168.0 125h0.0"></path><path d="M551.0 125h0.0"></path><g class="non-terminal"> +<path d="M168.0 125h0.0"></path><path d="M281.5 125h0.0"></path><rect height="22" width="113.5" x="168.0" y="114"></rect><text x="224.75" y="129">column name</text></g><path d="M281.5 125h10"></path><g> +<path d="M291.5 125h0.0"></path><path d="M551.0 125h0.0"></path><path d="M291.5 125a10 10 0 0 0 10 -10v-23a10 10 0 0 1 10 -10"></path><g> +<path d="M311.5 82h219.5"></path></g><path d="M531.0 82a10 10 0 0 1 10 10v23a10 10 0 0 0 10 10"></path><path d="M291.5 125h20"></path><g> +<path d="M311.5 125h0.0"></path><path d="M531.0 125h0.0"></path><path d="M311.5 125h10"></path><g> +<path d="M321.5 125h0.0"></path><path d="M521.0 125h0.0"></path><g> +<path d="M321.5 125h0.0"></path><path d="M387.5 125h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="321.5" y="106"></rect><g class="terminal"> +<path d="M321.5 125h10.25"></path><path d="M377.25 125h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="331.75" y="114"></rect><text x="354.5" y="129">','</text></g><g> +<path d="M321.5 98h0.0"></path><path d="M387.5 98h0.0"></path><text class="comment" x="354.5" y="103">Suppress</text></g></g><path d="M387.5 125h10"></path><path d="M397.5 125h10"></path><g class="non-terminal"> +<path d="M407.5 125h0.0"></path><path d="M521.0 125h0.0"></path><rect height="22" width="113.5" x="407.5" y="114"></rect><text x="464.25" y="129">column name</text></g></g><path d="M521.0 125h10"></path><path d="M321.5 125a10 10 0 0 0 -10 10v7a10 10 0 0 0 10 10"></path><g> +<path d="M321.5 152h199.5"></path></g><path d="M521.0 152a10 10 0 0 0 10 -10v-7a10 10 0 0 0 -10 -10"></path></g><path d="M531.0 125h20"></path></g></g><path d="M551.0 125a10 10 0 0 0 10 -10v-42a10 10 0 0 1 10 -10"></path></g></g><path d="M571.0 63h10"></path><path d="M581.0 63h10"></path><g class="terminal"> +<path d="M591.0 63h0.0"></path><path d="M662.0 63h0.0"></path><rect height="22" rx="10" ry="10" width="71.0" x="591.0" y="52"></rect><text x="626.5" y="67">'from'</text></g></g><path d="M662.0 63h10"></path><path d="M672.0 63h10"></path><g> +<path d="M682.0 63h0.0"></path><path d="M1048.0 63h0.0"></path><g class="non-terminal"> +<path d="M682.0 63h0.0"></path><path d="M787.0 63h0.0"></path><rect height="22" width="105.0" x="682.0" y="52"></rect><text x="734.5" y="67">table name</text></g><path d="M787.0 63h10"></path><g> +<path d="M797.0 63h0.0"></path><path d="M1048.0 63h0.0"></path><path d="M797.0 63a10 10 0 0 0 10 -10v-23a10 10 0 0 1 10 -10"></path><g> +<path d="M817.0 20h211.0"></path></g><path d="M1028.0 20a10 10 0 0 1 10 10v23a10 10 0 0 0 10 10"></path><path d="M797.0 63h20"></path><g> +<path d="M817.0 63h0.0"></path><path d="M1028.0 63h0.0"></path><path d="M817.0 63h10"></path><g> +<path d="M827.0 63h0.0"></path><path d="M1018.0 63h0.0"></path><g> +<path d="M827.0 63h0.0"></path><path d="M893.0 63h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="827.0" y="44"></rect><g class="terminal"> +<path d="M827.0 63h10.25"></path><path d="M882.75 63h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="837.25" y="52"></rect><text x="860.0" y="67">','</text></g><g> +<path d="M827.0 36h0.0"></path><path d="M893.0 36h0.0"></path><text class="comment" x="860.0" y="41">Suppress</text></g></g><path d="M893.0 63h10"></path><path d="M903.0 63h10"></path><g class="non-terminal"> +<path d="M913.0 63h0.0"></path><path d="M1018.0 63h0.0"></path><rect height="22" width="105.0" x="913.0" y="52"></rect><text x="965.5" y="67">table name</text></g></g><path d="M1018.0 63h10"></path><path d="M827.0 63a10 10 0 0 0 -10 10v7a10 10 0 0 0 10 10"></path><g> +<path d="M827.0 90h191.0"></path></g><path d="M1018.0 90a10 10 0 0 0 10 -10v-7a10 10 0 0 0 -10 -10"></path></g><path d="M1028.0 63h20"></path></g></g></g><path d="M1048.0 63h10"></path><g> +<path d="M1058.0 63h0.0"></path><path d="M1294.0 63h0.0"></path><path d="M1058.0 63a10 10 0 0 0 10 -10v0a10 10 0 0 1 10 -10"></path><g> +<path d="M1078.0 43h196.0"></path></g><path d="M1274.0 43a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M1058.0 63h20"></path><g> +<path d="M1078.0 63h0.0"></path><path d="M1274.0 63h0.0"></path><g class="terminal"> +<path d="M1078.0 63h0.0"></path><path d="M1157.5 63h0.0"></path><rect height="22" rx="10" ry="10" width="79.5" x="1078.0" y="52"></rect><text x="1117.75" y="67">'where'</text></g><path d="M1157.5 63h10"></path><path d="M1167.5 63h10"></path><g class="non-terminal"> +<path d="M1177.5 63h0.0"></path><path d="M1274.0 63h0.0"></path><rect height="22" width="96.5" x="1177.5" y="52"></rect><text x="1225.75" y="67">'or' term</text></g></g><path d="M1274.0 63h20"></path></g></g><path d="M1294.0 63h10"></path><path d="M 1304.0 63 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + + <div class="railroad-group"> + <h1 class="railroad-heading">column name</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="110" viewBox="0 0 706.5 110" width="706.5" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 53v20m10 -20v20m-10 -10h20"></path></g><path d="M40 63h10"></path><g> +<path d="M50 63h0.0"></path><path d="M656.5 63h0.0"></path><g> +<path d="M50.0 63h0.0"></path><path d="M285.5 63h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="235.5" x="50.0" y="44"></rect><g class="terminal"> +<path d="M50.0 63h10.0"></path><path d="M275.5 63h10.0"></path><rect height="22" rx="10" ry="10" width="215.5" x="60.0" y="52"></rect><text x="167.75" y="67">W:(A-Za-z, $0-9A-Z_a-z)</text></g><g> +<path d="M50.0 36h0.0"></path><path d="M130.0 36h0.0"></path><text class="comment" x="90.0" y="41">identifier</text></g></g><path d="M285.5 63h10"></path><g> +<path d="M295.5 63h0.0"></path><path d="M656.5 63h0.0"></path><path d="M295.5 63a10 10 0 0 0 10 -10v-23a10 10 0 0 1 10 -10"></path><g> +<path d="M315.5 20h321.0"></path></g><path d="M636.5 20a10 10 0 0 1 10 10v23a10 10 0 0 0 10 10"></path><path d="M295.5 63h20"></path><g> +<path d="M315.5 63h0.0"></path><path d="M636.5 63h0.0"></path><path d="M315.5 63h10"></path><g> +<path d="M325.5 63h0.0"></path><path d="M626.5 63h0.0"></path><g class="terminal"> +<path d="M325.5 63h0.0"></path><path d="M371.0 63h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="325.5" y="52"></rect><text x="348.25" y="67">'.'</text></g><path d="M371.0 63h10"></path><path d="M381.0 63h10"></path><g> +<path d="M391.0 63h0.0"></path><path d="M626.5 63h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="235.5" x="391.0" y="44"></rect><g class="terminal"> +<path d="M391.0 63h10.0"></path><path d="M616.5 63h10.0"></path><rect height="22" rx="10" ry="10" width="215.5" x="401.0" y="52"></rect><text x="508.75" y="67">W:(A-Za-z, $0-9A-Z_a-z)</text></g><g> +<path d="M391.0 36h0.0"></path><path d="M471.0 36h0.0"></path><text class="comment" x="431.0" y="41">identifier</text></g></g></g><path d="M626.5 63h10"></path><path d="M325.5 63a10 10 0 0 0 -10 10v7a10 10 0 0 0 10 10"></path><g> +<path d="M325.5 90h301.0"></path></g><path d="M626.5 90a10 10 0 0 0 10 -10v-7a10 10 0 0 0 -10 -10"></path></g><path d="M636.5 63h20"></path></g></g><path d="M656.5 63h10"></path><path d="M 666.5 63 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + + <div class="railroad-group"> + <h1 class="railroad-heading">table name</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="110" viewBox="0 0 706.5 110" width="706.5" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 53v20m10 -20v20m-10 -10h20"></path></g><path d="M40 63h10"></path><g> +<path d="M50 63h0.0"></path><path d="M656.5 63h0.0"></path><g> +<path d="M50.0 63h0.0"></path><path d="M285.5 63h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="235.5" x="50.0" y="44"></rect><g class="terminal"> +<path d="M50.0 63h10.0"></path><path d="M275.5 63h10.0"></path><rect height="22" rx="10" ry="10" width="215.5" x="60.0" y="52"></rect><text x="167.75" y="67">W:(A-Za-z, $0-9A-Z_a-z)</text></g><g> +<path d="M50.0 36h0.0"></path><path d="M130.0 36h0.0"></path><text class="comment" x="90.0" y="41">identifier</text></g></g><path d="M285.5 63h10"></path><g> +<path d="M295.5 63h0.0"></path><path d="M656.5 63h0.0"></path><path d="M295.5 63a10 10 0 0 0 10 -10v-23a10 10 0 0 1 10 -10"></path><g> +<path d="M315.5 20h321.0"></path></g><path d="M636.5 20a10 10 0 0 1 10 10v23a10 10 0 0 0 10 10"></path><path d="M295.5 63h20"></path><g> +<path d="M315.5 63h0.0"></path><path d="M636.5 63h0.0"></path><path d="M315.5 63h10"></path><g> +<path d="M325.5 63h0.0"></path><path d="M626.5 63h0.0"></path><g class="terminal"> +<path d="M325.5 63h0.0"></path><path d="M371.0 63h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="325.5" y="52"></rect><text x="348.25" y="67">'.'</text></g><path d="M371.0 63h10"></path><path d="M381.0 63h10"></path><g> +<path d="M391.0 63h0.0"></path><path d="M626.5 63h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="235.5" x="391.0" y="44"></rect><g class="terminal"> +<path d="M391.0 63h10.0"></path><path d="M616.5 63h10.0"></path><rect height="22" rx="10" ry="10" width="215.5" x="401.0" y="52"></rect><text x="508.75" y="67">W:(A-Za-z, $0-9A-Z_a-z)</text></g><g> +<path d="M391.0 36h0.0"></path><path d="M471.0 36h0.0"></path><text class="comment" x="431.0" y="41">identifier</text></g></g></g><path d="M626.5 63h10"></path><path d="M325.5 63a10 10 0 0 0 -10 10v7a10 10 0 0 0 10 10"></path><g> +<path d="M325.5 90h301.0"></path></g><path d="M626.5 90a10 10 0 0 0 10 -10v-7a10 10 0 0 0 -10 -10"></path></g><path d="M636.5 63h20"></path></g></g><path d="M656.5 63h10"></path><path d="M 666.5 63 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + + <div class="railroad-group"> + <h1 class="railroad-heading">'or' term</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="125" viewBox="0 0 788.0 125" width="788.0" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 45v20m10 -20v20m-10 -10h20"></path></g><g> +<path d="M40 55h0.0"></path><path d="M748.0 55h0.0"></path><path d="M40.0 55h20"></path><g> +<path d="M60.0 55h0.0"></path><path d="M728.0 55h0.0"></path><g> +<path d="M60.0 55h0.0"></path><path d="M384.0 55h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="324.0" x="60.0" y="36"></rect><g> +<path d="M60.0 55h10.0"></path><path d="M374.0 55h10.0"></path><g> +<path d="M70.0 55h0.0"></path><path d="M249.0 55h0.0"></path><g class="non-terminal"> +<path d="M70.0 55h0.0"></path><path d="M175.0 55h0.0"></path><rect height="22" width="105.0" x="70.0" y="44"></rect><text x="122.5" y="59">'and' term</text></g><path d="M175.0 55h10"></path><path d="M185.0 55h10"></path><g class="terminal"> +<path d="M195.0 55h0.0"></path><path d="M249.0 55h0.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="195.0" y="44"></rect><text x="222.0" y="59">'or'</text></g></g><path d="M249.0 55h10"></path><path d="M259.0 55h10"></path><g class="non-terminal"> +<path d="M269.0 55h0.0"></path><path d="M374.0 55h0.0"></path><rect height="22" width="105.0" x="269.0" y="44"></rect><text x="321.5" y="59">'and' term</text></g></g><g> +<path d="M60.0 28h0.0"></path><path d="M91.0 28h0.0"></path><text class="comment" x="75.5" y="33">_FB</text></g></g><path d="M384.0 55h10"></path><path d="M394.0 55h10"></path><g> +<path d="M404.0 55h0.0"></path><path d="M728.0 55h0.0"></path><g class="non-terminal"> +<path d="M404.0 55h0.0"></path><path d="M509.0 55h0.0"></path><rect height="22" width="105.0" x="404.0" y="44"></rect><text x="456.5" y="59">'and' term</text></g><path d="M509.0 55h10"></path><path d="M519.0 55h10"></path><g> +<path d="M529.0 55h0.0"></path><path d="M728.0 55h0.0"></path><path d="M529.0 55h10"></path><g> +<path d="M539.0 55h0.0"></path><path d="M718.0 55h0.0"></path><g class="terminal"> +<path d="M539.0 55h0.0"></path><path d="M593.0 55h0.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="539.0" y="44"></rect><text x="566.0" y="59">'or'</text></g><path d="M593.0 55h10"></path><path d="M603.0 55h10"></path><g class="non-terminal"> +<path d="M613.0 55h0.0"></path><path d="M718.0 55h0.0"></path><rect height="22" width="105.0" x="613.0" y="44"></rect><text x="665.5" y="59">'and' term</text></g></g><path d="M718.0 55h10"></path><path d="M539.0 55a10 10 0 0 0 -10 10v0a10 10 0 0 0 10 10"></path><g> +<path d="M539.0 75h179.0"></path></g><path d="M718.0 75a10 10 0 0 0 10 -10v0a10 10 0 0 0 -10 -10"></path></g></g></g><path d="M728.0 55h20"></path><path d="M40.0 55a10 10 0 0 1 10 10v19a10 10 0 0 0 10 10"></path><g class="non-terminal"> +<path d="M60.0 94h281.5"></path><path d="M446.5 94h281.5"></path><rect height="22" width="105.0" x="341.5" y="83"></rect><text x="394.0" y="98">'and' term</text></g><path d="M728.0 94a10 10 0 0 0 10 -10v-19a10 10 0 0 1 10 -10"></path></g><path d="M 748.0 55 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + + <div class="railroad-group"> + <h1 class="railroad-heading">'and' term</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="125" viewBox="0 0 805.0 125" width="805.0" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 45v20m10 -20v20m-10 -10h20"></path></g><g> +<path d="M40 55h0.0"></path><path d="M765.0 55h0.0"></path><path d="M40.0 55h20"></path><g> +<path d="M60.0 55h0.0"></path><path d="M745.0 55h0.0"></path><g> +<path d="M60.0 55h0.0"></path><path d="M392.5 55h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="332.5" x="60.0" y="36"></rect><g> +<path d="M60.0 55h10.0"></path><path d="M382.5 55h10.0"></path><g> +<path d="M70.0 55h0.0"></path><path d="M257.5 55h0.0"></path><g class="non-terminal"> +<path d="M70.0 55h0.0"></path><path d="M175.0 55h0.0"></path><rect height="22" width="105.0" x="70.0" y="44"></rect><text x="122.5" y="59">'not' term</text></g><path d="M175.0 55h10"></path><path d="M185.0 55h10"></path><g class="terminal"> +<path d="M195.0 55h0.0"></path><path d="M257.5 55h0.0"></path><rect height="22" rx="10" ry="10" width="62.5" x="195.0" y="44"></rect><text x="226.25" y="59">'and'</text></g></g><path d="M257.5 55h10"></path><path d="M267.5 55h10"></path><g class="non-terminal"> +<path d="M277.5 55h0.0"></path><path d="M382.5 55h0.0"></path><rect height="22" width="105.0" x="277.5" y="44"></rect><text x="330.0" y="59">'not' term</text></g></g><g> +<path d="M60.0 28h0.0"></path><path d="M91.0 28h0.0"></path><text class="comment" x="75.5" y="33">_FB</text></g></g><path d="M392.5 55h10"></path><path d="M402.5 55h10"></path><g> +<path d="M412.5 55h0.0"></path><path d="M745.0 55h0.0"></path><g class="non-terminal"> +<path d="M412.5 55h0.0"></path><path d="M517.5 55h0.0"></path><rect height="22" width="105.0" x="412.5" y="44"></rect><text x="465.0" y="59">'not' term</text></g><path d="M517.5 55h10"></path><path d="M527.5 55h10"></path><g> +<path d="M537.5 55h0.0"></path><path d="M745.0 55h0.0"></path><path d="M537.5 55h10"></path><g> +<path d="M547.5 55h0.0"></path><path d="M735.0 55h0.0"></path><g class="terminal"> +<path d="M547.5 55h0.0"></path><path d="M610.0 55h0.0"></path><rect height="22" rx="10" ry="10" width="62.5" x="547.5" y="44"></rect><text x="578.75" y="59">'and'</text></g><path d="M610.0 55h10"></path><path d="M620.0 55h10"></path><g class="non-terminal"> +<path d="M630.0 55h0.0"></path><path d="M735.0 55h0.0"></path><rect height="22" width="105.0" x="630.0" y="44"></rect><text x="682.5" y="59">'not' term</text></g></g><path d="M735.0 55h10"></path><path d="M547.5 55a10 10 0 0 0 -10 10v0a10 10 0 0 0 10 10"></path><g> +<path d="M547.5 75h187.5"></path></g><path d="M735.0 75a10 10 0 0 0 10 -10v0a10 10 0 0 0 -10 -10"></path></g></g></g><path d="M745.0 55h20"></path><path d="M40.0 55a10 10 0 0 1 10 10v19a10 10 0 0 0 10 10"></path><g class="non-terminal"> +<path d="M60.0 94h290.0"></path><path d="M455.0 94h290.0"></path><rect height="22" width="105.0" x="350.0" y="83"></rect><text x="402.5" y="98">'not' term</text></g><path d="M745.0 94a10 10 0 0 0 10 -10v-19a10 10 0 0 1 10 -10"></path></g><path d="M 765.0 55 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + + <div class="railroad-group"> + <h1 class="railroad-heading">'not' term</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="372" viewBox="0 0 1622.5 372" width="1622.5" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 45v20m10 -20v20m-10 -10h20"></path></g><g> +<path d="M40 55h0.0"></path><path d="M1582.5 55h0.0"></path><path d="M40.0 55h20"></path><g> +<path d="M60.0 55h528.75"></path><path d="M1033.75 55h528.75"></path><g> +<path d="M588.75 55h0.0"></path><path d="M796.25 55h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="207.5" x="588.75" y="36"></rect><g> +<path d="M588.75 55h10.0"></path><path d="M786.25 55h10.0"></path><g class="terminal"> +<path d="M598.75 55h0.0"></path><path d="M661.25 55h0.0"></path><rect height="22" rx="10" ry="10" width="62.5" x="598.75" y="44"></rect><text x="630.0" y="59">'not'</text></g><path d="M661.25 55h10"></path><path d="M671.25 55h10"></path><g class="non-terminal"> +<path d="M681.25 55h0.0"></path><path d="M786.25 55h0.0"></path><rect height="22" width="105.0" x="681.25" y="44"></rect><text x="733.75" y="59">'not' term</text></g></g><g> +<path d="M588.75 28h0.0"></path><path d="M619.75 28h0.0"></path><text class="comment" x="604.25" y="33">_FB</text></g></g><path d="M796.25 55h10"></path><path d="M806.25 55h10"></path><g> +<path d="M816.25 55h0.0"></path><path d="M1033.75 55h0.0"></path><g> +<path d="M816.25 55h0.0"></path><path d="M918.75 55h0.0"></path><path d="M816.25 55a10 10 0 0 0 10 -10v0a10 10 0 0 1 10 -10"></path><g> +<path d="M836.25 35h62.5"></path></g><path d="M898.75 35a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M816.25 55h20"></path><g class="terminal"> +<path d="M836.25 55h0.0"></path><path d="M898.75 55h0.0"></path><rect height="22" rx="10" ry="10" width="62.5" x="836.25" y="44"></rect><text x="867.5" y="59">'not'</text></g><path d="M898.75 55h20"></path></g><path d="M918.75 55h10"></path><g class="non-terminal"> +<path d="M928.75 55h0.0"></path><path d="M1033.75 55h0.0"></path><rect height="22" width="105.0" x="928.75" y="44"></rect><text x="981.25" y="59">'not' term</text></g></g></g><path d="M1562.5 55h20"></path><path d="M40.0 55a10 10 0 0 1 10 10v27a10 10 0 0 0 10 10"></path><g> +<path d="M60.0 102h0.0"></path><path d="M1562.5 102h0.0"></path><path d="M60.0 102h20"></path><g> +<path d="M80.0 102h0.0"></path><path d="M1542.5 102h0.0"></path><path d="M80.0 102h20"></path><g> +<path d="M100.0 102h0.0"></path><path d="M1522.5 102h0.0"></path><path d="M100.0 102h20"></path><g> +<path d="M120.0 102h0.0"></path><path d="M1502.5 102h0.0"></path><path d="M120.0 102h20"></path><g> +<path d="M140.0 102h0.0"></path><path d="M1482.5 102h0.0"></path><g> +<path d="M140.0 102h0.0"></path><path d="M1366.0 102h0.0"></path><g class="non-terminal"> +<path d="M140.0 102h0.0"></path><path d="M253.5 102h0.0"></path><rect height="22" width="113.5" x="140.0" y="91"></rect><text x="196.75" y="106">column name</text></g><path d="M253.5 102h10"></path><g> +<path d="M263.5 102h0.0"></path><path d="M1366.0 102h0.0"></path><path d="M263.5 102a10 10 0 0 0 10 -10v0a10 10 0 0 1 10 -10h978.5"></path><path d="M359.0 122h987.0a10 10 0 0 0 10 -10v0a10 10 0 0 1 10 -10"></path><path d="M263.5 102h10"></path><g class="terminal"> +<path d="M273.5 102h10.0"></path><path d="M329.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="283.5" y="91"></rect><text x="306.25" y="106">'='</text></g><path d="M339.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M339.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M359.0 102h10.0"></path><path d="M423.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="369.0" y="91"></rect><text x="396.0" y="106">'!='</text></g><path d="M433.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M433.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M453.0 102h10.0"></path><path d="M517.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="463.0" y="91"></rect><text x="490.0" y="106">'<='</text></g><path d="M527.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M527.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M547.0 102h10.0"></path><path d="M602.5 102h10.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="557.0" y="91"></rect><text x="579.75" y="106">'<'</text></g><path d="M612.5 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M612.5 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M632.5 102h10.0"></path><path d="M696.5 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="642.5" y="91"></rect><text x="669.5" y="106">'>='</text></g><path d="M706.5 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M706.5 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M726.5 102h10.0"></path><path d="M782.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="736.5" y="91"></rect><text x="759.25" y="106">'>'</text></g><path d="M792.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M792.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M812.0 102h10.0"></path><path d="M876.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="822.0" y="91"></rect><text x="849.0" y="106">'EQ'</text></g><path d="M886.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M886.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M906.0 102h10.0"></path><path d="M970.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="916.0" y="91"></rect><text x="943.0" y="106">'NE'</text></g><path d="M980.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M980.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M1000.0 102h10.0"></path><path d="M1064.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="1010.0" y="91"></rect><text x="1037.0" y="106">'LT'</text></g><path d="M1074.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M1074.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M1094.0 102h10.0"></path><path d="M1158.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="1104.0" y="91"></rect><text x="1131.0" y="106">'LE'</text></g><path d="M1168.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M1168.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M1188.0 102h10.0"></path><path d="M1252.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="1198.0" y="91"></rect><text x="1225.0" y="106">'GT'</text></g><path d="M1262.0 102a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><path d="M1262.0 82a10 10 0 0 1 10 10v0a10 10 0 0 0 10 10"></path><g class="terminal"> +<path d="M1282.0 102h10.0"></path><path d="M1346.0 102h10.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="1292.0" y="91"></rect><text x="1319.0" y="106">'GE'</text></g><path d="M1356.0 102h10"></path></g></g><path d="M1366.0 102h10"></path><path d="M1376.0 102h10"></path><g class="non-terminal"> +<path d="M1386.0 102h0.0"></path><path d="M1482.5 102h0.0"></path><rect height="22" width="96.5" x="1386.0" y="91"></rect><text x="1434.25" y="106">Unnamed 2</text></g></g><path d="M1482.5 102h20"></path><path d="M120.0 102a10 10 0 0 1 10 10v51a10 10 0 0 0 10 10"></path><g> +<path d="M140.0 173h327.5"></path><path d="M1155.0 173h327.5"></path><g> +<path d="M467.5 173h0.0"></path><path d="M655.0 173h0.0"></path><g class="non-terminal"> +<path d="M467.5 173h0.0"></path><path d="M581.0 173h0.0"></path><rect height="22" width="113.5" x="467.5" y="162"></rect><text x="524.25" y="177">column name</text></g><path d="M581.0 173h10"></path><path d="M591.0 173h10"></path><g class="terminal"> +<path d="M601.0 173h0.0"></path><path d="M655.0 173h0.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="601.0" y="162"></rect><text x="628.0" y="177">'in'</text></g></g><path d="M655.0 173h10"></path><path d="M665.0 173h10"></path><g> +<path d="M675.0 173h0.0"></path><path d="M1155.0 173h0.0"></path><g> +<path d="M675.0 173h0.0"></path><path d="M1089.5 173h0.0"></path><g class="terminal"> +<path d="M675.0 173h0.0"></path><path d="M720.5 173h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="675.0" y="162"></rect><text x="697.75" y="177">'('</text></g><path d="M720.5 173h10"></path><path d="M730.5 173h10"></path><g> +<path d="M740.5 173h0.0"></path><path d="M1089.5 173h0.0"></path><g class="non-terminal"> +<path d="M740.5 173h0.0"></path><path d="M837.0 173h0.0"></path><rect height="22" width="96.5" x="740.5" y="162"></rect><text x="788.75" y="177">Unnamed 2</text></g><path d="M837.0 173h10"></path><g> +<path d="M847.0 173h0.0"></path><path d="M1089.5 173h0.0"></path><path d="M847.0 173a10 10 0 0 0 10 -10v-23a10 10 0 0 1 10 -10"></path><g> +<path d="M867.0 130h202.5"></path></g><path d="M1069.5 130a10 10 0 0 1 10 10v23a10 10 0 0 0 10 10"></path><path d="M847.0 173h20"></path><g> +<path d="M867.0 173h0.0"></path><path d="M1069.5 173h0.0"></path><path d="M867.0 173h10"></path><g> +<path d="M877.0 173h0.0"></path><path d="M1059.5 173h0.0"></path><g> +<path d="M877.0 173h0.0"></path><path d="M943.0 173h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="877.0" y="154"></rect><g class="terminal"> +<path d="M877.0 173h10.25"></path><path d="M932.75 173h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="887.25" y="162"></rect><text x="910.0" y="177">','</text></g><g> +<path d="M877.0 146h0.0"></path><path d="M943.0 146h0.0"></path><text class="comment" x="910.0" y="151">Suppress</text></g></g><path d="M943.0 173h10"></path><path d="M953.0 173h10"></path><g class="non-terminal"> +<path d="M963.0 173h0.0"></path><path d="M1059.5 173h0.0"></path><rect height="22" width="96.5" x="963.0" y="162"></rect><text x="1011.25" y="177">Unnamed 2</text></g></g><path d="M1059.5 173h10"></path><path d="M877.0 173a10 10 0 0 0 -10 10v7a10 10 0 0 0 10 10"></path><g> +<path d="M877.0 200h182.5"></path></g><path d="M1059.5 200a10 10 0 0 0 10 -10v-7a10 10 0 0 0 -10 -10"></path></g><path d="M1069.5 173h20"></path></g></g></g><path d="M1089.5 173h10"></path><path d="M1099.5 173h10"></path><g class="terminal"> +<path d="M1109.5 173h0.0"></path><path d="M1155.0 173h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="1109.5" y="162"></rect><text x="1132.25" y="177">')'</text></g></g></g><path d="M1482.5 173a10 10 0 0 0 10 -10v-51a10 10 0 0 1 10 -10"></path></g><path d="M1502.5 102h20"></path><path d="M100.0 102a10 10 0 0 1 10 10v97a10 10 0 0 0 10 10"></path><g> +<path d="M120.0 219h482.25"></path><path d="M1020.25 219h482.25"></path><g> +<path d="M602.25 219h0.0"></path><path d="M789.75 219h0.0"></path><g class="non-terminal"> +<path d="M602.25 219h0.0"></path><path d="M715.75 219h0.0"></path><rect height="22" width="113.5" x="602.25" y="208"></rect><text x="659.0" y="223">column name</text></g><path d="M715.75 219h10"></path><path d="M725.75 219h10"></path><g class="terminal"> +<path d="M735.75 219h0.0"></path><path d="M789.75 219h0.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="735.75" y="208"></rect><text x="762.75" y="223">'in'</text></g></g><path d="M789.75 219h10"></path><path d="M799.75 219h10"></path><g> +<path d="M809.75 219h0.0"></path><path d="M1020.25 219h0.0"></path><g> +<path d="M809.75 219h0.0"></path><path d="M954.75 219h0.0"></path><g class="terminal"> +<path d="M809.75 219h0.0"></path><path d="M855.25 219h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="809.75" y="208"></rect><text x="832.5" y="223">'('</text></g><path d="M855.25 219h10"></path><path d="M865.25 219h10"></path><g class="non-terminal"> +<path d="M875.25 219h0.0"></path><path d="M954.75 219h0.0"></path><rect height="22" width="79.5" x="875.25" y="208"></rect><text x="915.0" y="223">Forward</text></g></g><path d="M954.75 219h10"></path><path d="M964.75 219h10"></path><g class="terminal"> +<path d="M974.75 219h0.0"></path><path d="M1020.25 219h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="974.75" y="208"></rect><text x="997.5" y="223">')'</text></g></g></g><path d="M1502.5 219a10 10 0 0 0 10 -10v-97a10 10 0 0 1 10 -10"></path></g><path d="M1522.5 102h20"></path><path d="M80.0 102a10 10 0 0 1 10 10v127a10 10 0 0 0 10 10"></path><g> +<path d="M100.0 249h515.75"></path><path d="M1006.75 249h515.75"></path><g> +<path d="M615.75 249h0.0"></path><path d="M803.25 249h0.0"></path><g class="non-terminal"> +<path d="M615.75 249h0.0"></path><path d="M729.25 249h0.0"></path><rect height="22" width="113.5" x="615.75" y="238"></rect><text x="672.5" y="253">column name</text></g><path d="M729.25 249h10"></path><path d="M739.25 249h10"></path><g class="terminal"> +<path d="M749.25 249h0.0"></path><path d="M803.25 249h0.0"></path><rect height="22" rx="10" ry="10" width="54.0" x="749.25" y="238"></rect><text x="776.25" y="253">'is'</text></g></g><path d="M803.25 249h10"></path><g> +<path d="M813.25 249h0.0"></path><path d="M1006.75 249h0.0"></path><path d="M813.25 249h20"></path><g class="terminal"> +<path d="M833.25 249h41.25"></path><path d="M945.5 249h41.25"></path><rect height="22" rx="10" ry="10" width="71.0" x="874.5" y="238"></rect><text x="910.0" y="253">'null'</text></g><path d="M986.75 249h20"></path><path d="M813.25 249a10 10 0 0 1 10 10v10a10 10 0 0 0 10 10"></path><g> +<path d="M833.25 279h0.0"></path><path d="M986.75 279h0.0"></path><g class="terminal"> +<path d="M833.25 279h0.0"></path><path d="M895.75 279h0.0"></path><rect height="22" rx="10" ry="10" width="62.5" x="833.25" y="268"></rect><text x="864.5" y="283">'not'</text></g><path d="M895.75 279h10"></path><path d="M905.75 279h10"></path><g class="terminal"> +<path d="M915.75 279h0.0"></path><path d="M986.75 279h0.0"></path><rect height="22" rx="10" ry="10" width="71.0" x="915.75" y="268"></rect><text x="951.25" y="283">'null'</text></g></g><path d="M986.75 279a10 10 0 0 0 10 -10v-10a10 10 0 0 1 10 -10"></path></g></g><path d="M1522.5 249a10 10 0 0 0 10 -10v-127a10 10 0 0 1 10 -10"></path></g><path d="M1542.5 102h20"></path><path d="M60.0 102a10 10 0 0 1 10 10v211a10 10 0 0 0 10 10"></path><g> +<path d="M80.0 333h597.0"></path><path d="M945.5 333h597.0"></path><g> +<path d="M677.0 333h0.0"></path><path d="M859.5 333h0.0"></path><g> +<path d="M677.0 333h0.0"></path><path d="M743.0 333h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="677.0" y="314"></rect><g class="terminal"> +<path d="M677.0 333h10.25"></path><path d="M732.75 333h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="687.25" y="322"></rect><text x="710.0" y="337">'('</text></g><g> +<path d="M677.0 306h0.0"></path><path d="M743.0 306h0.0"></path><text class="comment" x="710.0" y="311">Suppress</text></g></g><path d="M743.0 333h10"></path><path d="M753.0 333h10"></path><g class="non-terminal"> +<path d="M763.0 333h0.0"></path><path d="M859.5 333h0.0"></path><rect height="22" width="96.5" x="763.0" y="322"></rect><text x="811.25" y="337">'or' term</text></g></g><path d="M859.5 333h10"></path><path d="M869.5 333h10"></path><g> +<path d="M879.5 333h0.0"></path><path d="M945.5 333h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="66" x="879.5" y="314"></rect><g class="terminal"> +<path d="M879.5 333h10.25"></path><path d="M935.25 333h10.25"></path><rect height="22" rx="10" ry="10" width="45.5" x="889.75" y="322"></rect><text x="912.5" y="337">')'</text></g><g> +<path d="M879.5 306h0.0"></path><path d="M945.5 306h0.0"></path><text class="comment" x="912.5" y="311">Suppress</text></g></g></g><path d="M1542.5 333a10 10 0 0 0 10 -10v-211a10 10 0 0 1 10 -10"></path></g><path d="M1562.5 102a10 10 0 0 0 10 -10v-27a10 10 0 0 1 10 -10"></path></g><path d="M 1582.5 55 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + + <div class="railroad-group"> + <h1 class="railroad-heading">Unnamed 2</h1> + <div class="railroad-description"></div> + <div class="railroad-svg"> + <svg class="railroad-diagram" height="278" viewBox="0 0 787.0 278" width="787.0" xmlns="http://www.w3.org/2000/svg"> +<g transform="translate(.5 .5)"> +<style>/* <![CDATA[ */ + svg.railroad-diagram { + background-color:hsl(30,20%,95%); + } + svg.railroad-diagram path { + stroke-width:3; + stroke:black; + fill:rgba(0,0,0,0); + } + svg.railroad-diagram text { + font:bold 14px monospace; + text-anchor:middle; + } + svg.railroad-diagram text.label{ + text-anchor:start; + } + svg.railroad-diagram text.comment{ + font:italic 12px monospace; + } + svg.railroad-diagram rect{ + stroke-width:3; + stroke:black; + fill:hsl(120,100%,90%); + } + svg.railroad-diagram rect.group-box { + stroke: gray; + stroke-dasharray: 10 5; + fill: none; + } + +/* ]]> */ +</style><g> +<path d="M20 45v20m10 -20v20m-10 -10h20"></path></g><g> +<path d="M40 55h0.0"></path><path d="M747.0 55h0.0"></path><path d="M40.0 55h20"></path><g> +<path d="M60.0 55h0.0"></path><path d="M727.0 55h0.0"></path><path d="M60.0 55h20"></path><g> +<path d="M80.0 55h146.0"></path><path d="M561.0 55h146.0"></path><path d="M226.0 55h20"></path><g> +<path d="M246.0 55h0.0"></path><path d="M541.0 55h0.0"></path><rect class="group-box" height="38" rx="10" ry="10" width="295.0" x="246.0" y="36"></rect><g class="terminal"> +<path d="M246.0 55h10.0"></path><path d="M531.0 55h10.0"></path><rect height="22" rx="10" ry="10" width="275.0" x="256.0" y="44"></rect><text x="393.5" y="59">Re:('[+-]?(?:\d+\.\d*|\.\d+)')</text></g><g> +<path d="M246.0 28h0.0"></path><path d="M333.0 28h0.0"></path><text class="comment" x="289.5" y="33">real number</text></g></g><path d="M541.0 55h20"></path><path d="M226.0 55a10 10 0 0 1 10 10v42a10 10 0 0 0 10 10"></path><g> +<path d="M246.0 117h63.75"></path><path d="M477.25 117h63.75"></path><rect class="group-box" height="38" rx="10" ry="10" width="167.5" x="309.75" y="98"></rect><g class="terminal"> +<path d="M309.75 117h10.0"></path><path d="M467.25 117h10.0"></path><rect height="22" rx="10" ry="10" width="147.5" x="319.75" y="106"></rect><text x="393.5" y="121">Re:('[+-]?\d+')</text></g><g> +<path d="M309.75 90h0.0"></path><path d="M417.75 90h0.0"></path><text class="comment" x="363.75" y="95">signed integer</text></g></g><path d="M541.0 117a10 10 0 0 0 10 -10v-42a10 10 0 0 1 10 -10"></path></g><path d="M707.0 55h20"></path><path d="M60.0 55a10 10 0 0 1 10 10v104a10 10 0 0 0 10 10"></path><g> +<path d="M80.0 179h0.0"></path><path d="M707.0 179h0.0"></path><rect class="group-box" height="68" rx="10" ry="10" width="627.0" x="80.0" y="160"></rect><g> +<path d="M80.0 179h0.0"></path><path d="M707.0 179h0.0"></path><path d="M80.0 179h20"></path><g> +<path d="M100.0 179h0.0"></path><path d="M687.0 179h0.0"></path><g class="terminal"> +<path d="M100.0 179h0.0"></path><path d="M621.5 179h0.0"></path><rect height="22" rx="10" ry="10" width="521.5" x="100.0" y="168"></rect><text x="360.75" y="183">Re:('"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')</text></g><path d="M621.5 179h10"></path><path d="M631.5 179h10"></path><g class="terminal"> +<path d="M641.5 179h0.0"></path><path d="M687.0 179h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="641.5" y="168"></rect><text x="664.25" y="183">'"'</text></g></g><path d="M687.0 179h20"></path><path d="M80.0 179a10 10 0 0 1 10 10v10a10 10 0 0 0 10 10"></path><g> +<path d="M100.0 209h0.0"></path><path d="M687.0 209h0.0"></path><g class="terminal"> +<path d="M100.0 209h0.0"></path><path d="M621.5 209h0.0"></path><rect height="22" rx="10" ry="10" width="521.5" x="100.0" y="198"></rect><text x="360.75" y="213">Re:("'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")</text></g><path d="M621.5 209h10"></path><path d="M631.5 209h10"></path><g class="terminal"> +<path d="M641.5 209h0.0"></path><path d="M687.0 209h0.0"></path><rect height="22" rx="10" ry="10" width="45.5" x="641.5" y="198"></rect><text x="664.25" y="213">"'"</text></g></g><path d="M687.0 209a10 10 0 0 0 10 -10v-10a10 10 0 0 1 10 -10"></path></g><g> +<path d="M80.0 152h0.0"></path><path d="M384.0 152h0.0"></path><text class="comment" x="232.0" y="157">quotedString using single or double quotes</text></g></g><path d="M707.0 179a10 10 0 0 0 10 -10v-104a10 10 0 0 1 10 -10"></path></g><path d="M727.0 55h20"></path><path d="M40.0 55a10 10 0 0 1 10 10v172a10 10 0 0 0 10 10"></path><g class="non-terminal"> +<path d="M60.0 247h276.75"></path><path d="M450.25 247h276.75"></path><rect height="22" width="113.5" x="336.75" y="236"></rect><text x="393.5" y="251">column name</text></g><path d="M727.0 247a10 10 0 0 0 10 -10v-172a10 10 0 0 1 10 -10"></path></g><path d="M 747.0 55 h 20 m -10 -10 v 20 m 10 -20 v 20"></path></g></svg> + </div> + </div> + +</body> +</html>
\ No newline at end of file diff --git a/pyparsing/diagram/__init__.py b/pyparsing/diagram/__init__.py index 85ed314..e9ad70d 100644 --- a/pyparsing/diagram/__init__.py +++ b/pyparsing/diagram/__init__.py @@ -8,7 +8,6 @@ from typing import ( NamedTuple, Generic, TypeVar, - Any, Dict, Callable, ) @@ -69,19 +68,6 @@ class EditablePartial(Generic[T]): return self.func(*args, **kwargs) -def get_name(element: pyparsing.ParserElement, default: str = None) -> str: - """ - Returns a human readable string for a parser element. By default it will first check the element's `name` attribute - for a user-defined string, and will fall back to the element type name if this doesn't exist. However, the fallback - value can be customized - """ - # return str(element) - if default is None: - default = element.__class__.__name__ - - return getattr(element, "name", default) - - def railroad_to_html(diagrams: List[NamedDiagram], **kwargs) -> str: """ Given a list of NamedDiagram, produce a single HTML string that visualises those diagrams @@ -129,10 +115,10 @@ def to_railroad( lookup = ConverterState(diagram_kwargs=diagram_kwargs) _to_diagram_element(element, lookup=lookup, parent=None, vertical=vertical) - # Convert the root if it hasn't been already root_id = id(element) + # Convert the root if it hasn't been already if root_id in lookup.first: - lookup.first[root_id].mark_for_extraction(root_id, lookup) + lookup.first[root_id].mark_for_extraction(root_id, lookup, force=True) # Now that we're finished, we can convert from intermediate structures into Railroad elements resolved = [resolve_partial(partial) for partial in lookup.diagrams.values()] @@ -162,7 +148,7 @@ class ElementState: element: pyparsing.ParserElement, converted: EditablePartial, parent: EditablePartial, - number: int = None, + number: int, name: str = None, index: Optional[int] = None, ): @@ -174,8 +160,7 @@ class ElementState: self.converted = converted # type: EditablePartial #: The parent Railroad element, which we store so that we can extract this if it's duplicated self.parent = parent # type: EditablePartial - #: The diagram number of this, when it gets turned into a diagram. This is only set when we know it's going to - # be extracted into a new diagram + #: The order in which we found this element, used for sorting diagrams if this is extracted into a diagram self.number = number # type: int #: The index of this inside its parent self.parent_index = index # type: Optional[int] @@ -184,29 +169,31 @@ class ElementState: #: If true, all of this element's chilren have been filled out self.complete = False # type: bool - def mark_for_extraction(self, el_id: int, state: "ConverterState"): + def mark_for_extraction( + self, el_id: int, state: "ConverterState", name: str = None, force: bool = False + ): """ Called when this instance has been seen twice, and thus should eventually be extracted into a sub-diagram + :param force: If true, force extraction now, regardless of the state of this. Only useful for extracting the + root element when we know we're finished """ self.extract = True - if self.number is None: - if self.parent is None: - self.number = 0 - else: - self.number = state.generate_index() - # Set the name if not self.name: - if hasattr(self.element, "name") and self.element.name: - self.name = self.element.name + if name: + # Allow forcing a custom name + self.name = name + elif self.element.customName: + self.name = self.element.customName else: unnamed_number = 1 if self.parent is None else state.generate_unnamed() self.name = "Unnamed {}".format(unnamed_number) # Just because this is marked for extraction doesn't mean we can do it yet. We may have to wait for children # to be added - if self.complete: + # Also, if this is just a string literal etc, don't bother extracting it + if force or (self.complete and _worth_extracting(self.element)): state.extract_into_diagram(el_id) @@ -256,47 +243,41 @@ class ConverterState: else: position.parent.kwargs["items"][position.parent_index] = ret + # If the element we're extracting is a group, skip to its content but keep the title + if position.converted.func == railroad.Group: + content = position.converted.kwargs["item"] + else: + content = position.converted + self.diagrams[el_id] = EditablePartial.from_call( NamedDiagram, name=position.name, diagram=EditablePartial.from_call( - railroad.Diagram, position.converted, **self.diagram_kwargs + railroad.Diagram, content, **self.diagram_kwargs ), index=position.number, ) del self.first[el_id] -def _worth_extracting(children: List[pyparsing.ParserElement]) -> bool: +def _worth_extracting(element: pyparsing.ParserElement) -> bool: """ - Returns true if the element with these children is worth having its own element. Simply, if any of its children + Returns true if this element is worth having its own sub-diagram. Simply, if any of its children themselves have children, then its complex enough to extract """ + children = element.recurse() return any( [hasattr(child, "expr") or hasattr(child, "exprs") for child in children] ) -def _element_children( - element: pyparsing.ParserElement, -) -> List[Union[str, pyparsing.ParserElement]]: - """ - Converts the nebulous list of child elements into a single list objects for easy use - """ - if hasattr(element, "exprs"): - return list(element.exprs) - elif hasattr(element, "expr"): - return [element.expr] - else: - return [] - - def _to_diagram_element( element: pyparsing.ParserElement, parent: Optional[EditablePartial], lookup: ConverterState = None, vertical: Union[int, bool] = 5, index: int = 0, + name_hint: str = None, ) -> Optional[EditablePartial]: """ Recursively converts a PyParsing Element to a railroad Element @@ -306,102 +287,140 @@ def _to_diagram_element( :param vertical: Controls at what point we make a list of elements vertical. If this is an integer (the default), it sets the threshold of the number of items before we go vertical. If True, always go vertical, if False, never do so + :param name_hint: If provided, this will override the generated name :returns: The converted version of the input element, but as a Partial that hasn't yet been constructed """ - exprs = _element_children(element) + exprs = element.recurse() + name = name_hint or element.customName or element.__class__.__name__ - name = get_name(element) # Python's id() is used to provide a unique identifier for elements el_id = id(element) - if el_id in lookup.first: - # If we've seen this element exactly once before, we are only just now finding out that it's a duplicate, - # so we have to extract it into a new diagram. - looked_up = lookup.first[el_id] - looked_up.mark_for_extraction(el_id, lookup) - return EditablePartial.from_call(railroad.NonTerminal, text=looked_up.name) - - elif el_id in lookup.diagrams: - # If we have seen the element at least twice before, and have already extracted it into a subdiagram, we - # just put in a marker element that refers to the sub-diagram - return EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] + # Here we basically bypass processing certain wrapper elements if they contribute nothing to the diagram + if isinstance(element, (pyparsing.Group, pyparsing.Forward)) and ( + not element.customName or not exprs[0].customName + ): + # However, if this element has a useful custom name, we can pass it on to the child + if not exprs[0].customName: + propagated_name = name + else: + propagated_name = None + + return _to_diagram_element( + element.expr, + parent=parent, + lookup=lookup, + vertical=vertical, + index=index, + name_hint=propagated_name, ) - else: - # Recursively convert child elements - # Here we find the most relevant Railroad element for matching pyparsing Element - # We use ``items=None`` here to hold the place for where the child elements will go once created - if isinstance(element, pyparsing.And): - if _should_vertical(vertical, len(exprs)): - ret = EditablePartial.from_call(railroad.Stack, items=[]) - else: - ret = EditablePartial.from_call(railroad.Sequence, items=[]) - elif isinstance(element, (pyparsing.Or, pyparsing.MatchFirst)): - if _should_vertical(vertical, len(exprs)): - ret = EditablePartial.from_call(railroad.HorizontalChoice, items=[]) - else: - ret = EditablePartial.from_call(railroad.Choice, 0, items=[]) - elif isinstance(element, pyparsing.Optional): - ret = EditablePartial.from_call(railroad.Optional, item="") - elif isinstance(element, pyparsing.OneOrMore): - ret = EditablePartial.from_call(railroad.OneOrMore, item="") - elif isinstance(element, pyparsing.ZeroOrMore): - ret = EditablePartial.from_call(railroad.ZeroOrMore, item="") - elif isinstance(element, pyparsing.Group): - # Generally there isn't any merit in labelling a group as a group if it doesn't have a custom name - if name != "Group": - ret = EditablePartial.from_call(railroad.Group, item=None, label=name) - else: - ret = EditablePartial.from_call(railroad.Group, item=None, label="") - elif isinstance(element, pyparsing.Empty) and name == "Empty": - # Skip unnamed "Empty" elements - ret = None - elif len(exprs) > 1: + # If the element isn't worth extracting, we always treat it as the first time we say it + if _worth_extracting(element): + if el_id in lookup.first: + # If we've seen this element exactly once before, we are only just now finding out that it's a duplicate, + # so we have to extract it into a new diagram. + looked_up = lookup.first[el_id] + looked_up.mark_for_extraction(el_id, lookup, name=name_hint) + return EditablePartial.from_call(railroad.NonTerminal, text=looked_up.name) + + elif el_id in lookup.diagrams: + # If we have seen the element at least twice before, and have already extracted it into a subdiagram, we + # just put in a marker element that refers to the sub-diagram + return EditablePartial.from_call( + railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] + ) + + # Recursively convert child elements + # Here we find the most relevant Railroad element for matching pyparsing Element + # We use ``items=[]`` here to hold the place for where the child elements will go once created + if isinstance(element, pyparsing.And): + if _should_vertical(vertical, len(exprs)): + ret = EditablePartial.from_call(railroad.Stack, items=[]) + else: ret = EditablePartial.from_call(railroad.Sequence, items=[]) - elif len(exprs) > 0: - ret = EditablePartial.from_call(railroad.Group, item="", label=name) + elif isinstance(element, (pyparsing.Or, pyparsing.MatchFirst)): + if _should_vertical(vertical, len(exprs)): + ret = EditablePartial.from_call(railroad.HorizontalChoice, items=[]) else: - ret = EditablePartial.from_call(railroad.Terminal, name) - - # Indicate this element's position in the tree so we can extract it if necessary - if _worth_extracting(exprs): - lookup.first[el_id] = ElementState( - element=element, converted=ret, parent=parent, index=index + ret = EditablePartial.from_call(railroad.Choice, 0, items=[]) + elif isinstance(element, pyparsing.Optional): + ret = EditablePartial.from_call(railroad.Optional, item="") + elif isinstance(element, pyparsing.OneOrMore): + ret = EditablePartial.from_call(railroad.OneOrMore, item="") + elif isinstance(element, pyparsing.ZeroOrMore): + ret = EditablePartial.from_call(railroad.ZeroOrMore, item="") + elif isinstance(element, pyparsing.Group): + ret = EditablePartial.from_call(railroad.Group, item=None, label=name) + elif isinstance(element, pyparsing.Empty) and not element.customName: + # Skip unnamed "Empty" elements + ret = None + elif len(exprs) > 1: + ret = EditablePartial.from_call(railroad.Sequence, items=[]) + elif len(exprs) > 0: + ret = EditablePartial.from_call(railroad.Group, item="", label=name) + else: + # If the terminal has a custom name, we annotate the terminal with it, but still show the defaultName, because + # it describes the pattern that it matches, which is useful to have present in the diagram + terminal = EditablePartial.from_call(railroad.Terminal, element.defaultName) + if element.customName is not None: + ret = EditablePartial.from_call( + railroad.Group, item=terminal, label=element.customName ) + else: + ret = terminal + + # Indicate this element's position in the tree so we can extract it if necessary + lookup.first[el_id] = ElementState( + element=element, + converted=ret, + parent=parent, + index=index, + number=lookup.generate_index(), + ) - i = 0 - for expr in exprs: - # Add a placeholder index in case we have to extract the child before we even add it to the parent - if "items" in ret.kwargs: - ret.kwargs["items"].insert(i, None) + i = 0 + for expr in exprs: + # Add a placeholder index in case we have to extract the child before we even add it to the parent + if "items" in ret.kwargs: + ret.kwargs["items"].insert(i, None) - item = _to_diagram_element( - expr, parent=ret, lookup=lookup, vertical=vertical, index=i - ) + item = _to_diagram_element( + expr, parent=ret, lookup=lookup, vertical=vertical, index=i + ) - # Some elements don't need to be shown in the diagram - if item is not None: - if "item" in ret.kwargs: - ret.kwargs["item"] = item - elif "items" in ret.kwargs: - # If we've already extracted the child, don't touch this index, since it's occupied by a nonterminal - if ret.kwargs["items"][i] is None: - ret.kwargs["items"][i] = item - i += 1 - - # Mark this element as "complete", ie it has all of its children - if el_id in lookup.first: - lookup.first[el_id].complete = True - - if ( - el_id in lookup.first - and lookup.first[el_id].extract - and lookup.first[el_id].complete - ): - lookup.extract_into_diagram(el_id) - return EditablePartial.from_call( - railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] - ) - else: - return ret + # Some elements don't need to be shown in the diagram + if item is not None: + if "item" in ret.kwargs: + ret.kwargs["item"] = item + elif "items" in ret.kwargs: + # If we've already extracted the child, don't touch this index, since it's occupied by a nonterminal + if ret.kwargs["items"][i] is None: + ret.kwargs["items"][i] = item + i += 1 + elif "items" in ret.kwargs: + # If we're supposed to skip this element, remove it from the parent + del ret.kwargs["items"][i] + + # If all this items children are none, skip this item + if ret and ( + ("items" in ret.kwargs and len(ret.kwargs["items"]) == 0) + or ("item" in ret.kwargs and ret.kwargs["item"] is None) + ): + return EditablePartial.from_call(railroad.Terminal, name) + + # Mark this element as "complete", ie it has all of its children + if el_id in lookup.first: + lookup.first[el_id].complete = True + + if ( + el_id in lookup.first + and lookup.first[el_id].extract + and lookup.first[el_id].complete + ): + lookup.extract_into_diagram(el_id) + return EditablePartial.from_call( + railroad.NonTerminal, text=lookup.diagrams[el_id].kwargs["name"] + ) + else: + return ret diff --git a/tests/test_diagram.py b/tests/test_diagram.py index a449bb0..eeb1ee8 100644 --- a/tests/test_diagram.py +++ b/tests/test_diagram.py @@ -4,6 +4,7 @@ from examples.simpleBool import boolExpr from examples.simpleSQL import simpleSQL from examples.mozillaCalendarParser import calendars from pyparsing.diagram import to_railroad, railroad_to_html +from pyparsing import Or import tempfile import os @@ -26,26 +27,29 @@ class TestRailroadDiagrams(unittest.TestCase): def test_bool_expr(self): with self.get_temp() as temp: railroad = to_railroad(boolExpr) + assert len(railroad) == 3 temp.write(railroad_to_html(railroad)) if self.railroad_debug(): - print(temp.name) + print("bool expr:" + temp.name) def test_json(self): with self.get_temp() as temp: railroad = to_railroad(jsonObject) + assert len(railroad) == 4 temp.write(railroad_to_html(railroad)) if self.railroad_debug(): - print(temp.name) + print("json: " + temp.name) def test_sql(self): with self.get_temp() as temp: railroad = to_railroad(simpleSQL) + assert len(railroad) == 7 temp.write(railroad_to_html(railroad)) if self.railroad_debug(): - print(temp.name) + print("sql: " + temp.name) def test_calendars(self): with self.get_temp() as temp: @@ -53,4 +57,10 @@ class TestRailroadDiagrams(unittest.TestCase): temp.write(railroad_to_html(railroad)) if self.railroad_debug(): - print(temp.name) + print("calendar: " + temp.name) + + def test_none_name(self): + grammar = Or(["foo", "bar"]) + railroad = to_railroad(grammar) + assert len(railroad) == 1 + assert railroad[0].name is not None |