sgf_parser 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/.irbrc +3 -0
  2. data/.rvmrc +4 -0
  3. data/Gemfile +10 -0
  4. data/Gemfile.lock +17 -0
  5. data/LICENSE +20 -0
  6. data/README.textile +27 -0
  7. data/Rakefile +20 -0
  8. data/TODO +0 -0
  9. data/VERSION +1 -0
  10. data/bin/sgf +28 -0
  11. data/bin/stm2dot +18 -0
  12. data/doc/sgf_state_machine.dot +58 -0
  13. data/doc/sgf_state_machine.svg +269 -0
  14. data/lib/sgf.rb +15 -0
  15. data/lib/sgf/binary_file_error.rb +4 -0
  16. data/lib/sgf/debugger.rb +15 -0
  17. data/lib/sgf/default_event_listener.rb +37 -0
  18. data/lib/sgf/model/constants.rb +19 -0
  19. data/lib/sgf/model/event_listener.rb +72 -0
  20. data/lib/sgf/model/game.rb +52 -0
  21. data/lib/sgf/model/label.rb +12 -0
  22. data/lib/sgf/model/node.rb +115 -0
  23. data/lib/sgf/model/property_handler.rb +51 -0
  24. data/lib/sgf/more/state_machine_presenter.rb +43 -0
  25. data/lib/sgf/more/stm_dot_converter.rb +139 -0
  26. data/lib/sgf/parse_error.rb +25 -0
  27. data/lib/sgf/parser.rb +56 -0
  28. data/lib/sgf/renderer.rb +25 -0
  29. data/lib/sgf/sgf_helper.rb +55 -0
  30. data/lib/sgf/sgf_state_machine.rb +174 -0
  31. data/lib/sgf/state_machine.rb +76 -0
  32. data/sgf_parser.gemspec +95 -0
  33. data/spec/fixtures/2009-11-01-1.sgf +24 -0
  34. data/spec/fixtures/2009-11-01-2.sgf +23 -0
  35. data/spec/fixtures/chinese_gb.sgf +9 -0
  36. data/spec/fixtures/chinese_utf.sgf +9 -0
  37. data/spec/fixtures/example.sgf +18 -0
  38. data/spec/fixtures/good.sgf +55 -0
  39. data/spec/fixtures/good1.sgf +167 -0
  40. data/spec/fixtures/kgs.sgf +723 -0
  41. data/spec/fixtures/test.png +0 -0
  42. data/spec/sgf/model/event_listener_spec.rb +97 -0
  43. data/spec/sgf/model/game_spec.rb +29 -0
  44. data/spec/sgf/model/node_spec.rb +84 -0
  45. data/spec/sgf/more/state_machine_presenter_spec.rb +29 -0
  46. data/spec/sgf/parse_error_spec.rb +10 -0
  47. data/spec/sgf/parser_spec.rb +210 -0
  48. data/spec/sgf/sgf_helper_spec.rb +68 -0
  49. data/spec/sgf/sgf_state_machine_spec.rb +166 -0
  50. data/spec/sgf/state_machine_spec.rb +137 -0
  51. data/spec/spec.opts +4 -0
  52. data/spec/spec_helper.rb +47 -0
  53. metadata +150 -0
data/.irbrc ADDED
@@ -0,0 +1,3 @@
1
+ $:.push(File.dirname(__FILE__) + '/lib')
2
+
3
+ require 'sgf'
data/.rvmrc ADDED
@@ -0,0 +1,4 @@
1
+ export rvm_gemset_create_on_use_flag=1
2
+
3
+ rvm use 1.8.7@sgf_parser
4
+
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ group :development do
4
+ gem "jeweler"
5
+ end
6
+
7
+ group :test do
8
+ gem "rspec", "~>1.3.0"
9
+ end
10
+
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ git (1.2.5)
5
+ jeweler (1.6.4)
6
+ bundler (~> 1.0)
7
+ git (>= 1.2.5)
8
+ rake
9
+ rake (0.9.2.2)
10
+ rspec (1.3.2)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ jeweler
17
+ rspec (~> 1.3.0)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 YOUR NAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.textile ADDED
@@ -0,0 +1,27 @@
1
+ A SGF parser gem
2
+
3
+
4
+ NOTES
5
+
6
+ (Below are tested on MAC OS X 10.5.8)
7
+ Use 'file -i XXX.sgf' to check file encoding
8
+ Use 'iconv -f gb18030 XXX.sgf' to convert GB2312/GB18030 to UTF16
9
+
10
+ Benchmark
11
+
12
+ time for i in {1..1000}; do bin/sgf spec/fixtures/2009-11-01-1.sgf; done
13
+
14
+ Fri Jan 8 08:49:18 EST 2010
15
+ real 0m26.221s
16
+ user 0m20.404s
17
+ sys 0m5.262s
18
+
19
+ Fri Jan 8 09:55:02 EST 2010
20
+ real 0m24.453s
21
+ user 0m18.758s
22
+ sys 0m5.080s
23
+
24
+ Sun Jan 10 10:01:09 EST 2010
25
+ real 0m18.660s
26
+ user 0m12.994s
27
+ sys 0m5.099s
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gem|
4
+ gem.name = "sgf_parser"
5
+ gem.summary = %Q{A SGF parser}
6
+ gem.description = %Q{A simple SGF parser}
7
+ gem.email = "gcao99@gmail.com"
8
+ gem.homepage = "http://github.com/gcao/discuz_robot"
9
+ gem.authors = ["Guoliang Cao"]
10
+ gem.add_development_dependency "rspec", "~> 1.3.0"
11
+ end
12
+ Jeweler::GemcutterTasks.new
13
+ rescue LoadError
14
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
15
+ end
16
+
17
+ desc "visualize SGF state machine"
18
+ task :vst do
19
+ system("bin/stm2dot && dot -T svg -o doc/sgf_state_machine.svg doc/sgf_state_machine.dot")
20
+ end
data/TODO ADDED
File without changes
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/bin/sgf ADDED
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ if ARGV.size == 0
4
+ puts <<-USAGE
5
+ Usage:
6
+ sgf <DIRECTORY_OR_FILE>
7
+ USAGE
8
+ exit 1
9
+ end
10
+
11
+ sgf_rb = File.expand_path(File.dirname(__FILE__) + '/../lib/sgf.rb')
12
+ if File.exists?(sgf_rb)
13
+ require sgf_rb
14
+ else
15
+ require 'rubygems'
16
+ require 'sgf'
17
+ end
18
+
19
+ filename = ARGV[0]
20
+ debug = ENV["DEBUG"] == "true"
21
+
22
+ if File.directory?(filename)
23
+ Dir["#{filename}/**/*"].each do |file|
24
+ SGF::Parser.parse_file(file, debug)
25
+ end
26
+ else
27
+ SGF::Parser.parse_file(filename, debug)
28
+ end
data/bin/stm2dot ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ dot_file = File.expand_path(File.dirname(__FILE__) + "/../doc/sgf_state_machine.dot")
4
+ dot_file = ARGV[0] if ARGV.size > 0
5
+
6
+ sgf_rb = File.expand_path(File.dirname(__FILE__) + '/../lib/sgf.rb')
7
+ if File.exists?(sgf_rb)
8
+ require sgf_rb
9
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/sgf/more/stm_dot_converter.rb')
10
+ else
11
+ require 'rubygems'
12
+ require 'sgf'
13
+ require 'sgf/more/stm_dot_converter'
14
+ end
15
+
16
+ File.open(dot_file, 'w') do |f|
17
+ f.print SGF::More::StmDotConverter.new.process(SGF::SGFStateMachine.new)
18
+ end
@@ -0,0 +1,58 @@
1
+ digraph SGF_STATE_MACHINE{
2
+ {rank = same; begin;}
3
+ {rank = same; game_begin;}
4
+ {rank = same; var_begin game_node;}
5
+ {rank = same; prop_name_begin;}
6
+ {rank = same; prop_name;}
7
+ {rank = same; value_begin;}
8
+ {rank = same; value value_escape;}
9
+ {rank = same; value_end;}
10
+ {rank = same; var_end;}
11
+ {rank = same; game_end invalid;}
12
+ begin[style = "filled",shape = "circle",fillcolor = "#44ff44"];
13
+ value[];
14
+ value_escape[];
15
+ value -> value_escape[label="\\"];
16
+ value -> value[label="[^\]]"];
17
+ value_end[];
18
+ value -> value_end[label="\]", weight=100];
19
+ game_node[];
20
+ value_end -> game_node[label=";"];
21
+ var_begin[];
22
+ value_end -> var_begin[label="\("];
23
+ prop_name_begin[];
24
+ value_end -> prop_name_begin[label="[a-zA-Z]"];
25
+ value_begin[];
26
+ value_end -> value_begin[label="\["];
27
+ var_end[];
28
+ value_end -> var_end[label="\)", weight=100];
29
+ invalid[style = "filled",label = "error",shape = "octagon",fillcolor = "#ff4444"];
30
+ value_end -> invalid[color="#FFBBBB", weight=-100];
31
+ var_end -> game_node[label=";", weight=90];
32
+ var_end -> var_begin[label="\("];
33
+ game_end[style = "filled",label = "end",shape = "doublecircle",fillcolor = "#44ff44"];
34
+ var_end -> game_end[label="EOS", weight=100];
35
+ var_end -> var_end[label="\)"];
36
+ var_end -> invalid[color="#FFBBBB", weight=-100];
37
+ value_begin -> value[label="[^\]]", weight=100];
38
+ value_begin -> value_escape[label="\\"];
39
+ value_begin -> value_end[label="\]"];
40
+ game_begin[];
41
+ begin -> game_begin[label="\(", weight=100];
42
+ begin -> invalid[color="#FFBBBB", weight=-100];
43
+ game_node -> var_begin[label="\("];
44
+ game_node -> prop_name_begin[label="[a-zA-Z]", weight=100];
45
+ game_node -> var_end[label="\)"];
46
+ game_node -> invalid[color="#FFBBBB", weight=-100];
47
+ prop_name[];
48
+ prop_name_begin -> prop_name[label="[a-zA-Z]", weight=100];
49
+ prop_name_begin -> value_begin[label="\["];
50
+ prop_name_begin -> invalid[color="#FFBBBB", weight=-100];
51
+ game_begin -> game_node[label=";", weight=100];
52
+ game_begin -> invalid[color="#FFBBBB", weight=-100];
53
+ value_escape -> value[label="."];
54
+ var_begin -> game_node[label=";"];
55
+ var_begin -> invalid[color="#FFBBBB", weight=-100];
56
+ prop_name -> value_begin[label="\[", weight=100];
57
+ prop_name -> invalid[color="#FFBBBB", weight=-100];
58
+ }
@@ -0,0 +1,269 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4
+ <!-- Generated by graphviz version 2.24.0 (20090616.2323)
5
+ -->
6
+ <!-- Title: SGF_STATE_MACHINE Pages: 1 -->
7
+ <svg width="879pt" height="864pt"
8
+ viewBox="0.00 0.00 879.38 864.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9
+ <g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 860)">
10
+ <title>SGF_STATE_MACHINE</title>
11
+ <polygon fill="white" stroke="white" points="-4,5 -4,-860 876.382,-860 876.382,5 -4,5"/>
12
+ <!-- begin -->
13
+ <g id="node2" class="node"><title>begin</title>
14
+ <ellipse fill="#44ff44" stroke="black" cx="174" cy="-825" rx="29.8234" ry="30.3205"/>
15
+ <text text-anchor="middle" x="174" y="-819.4" font-family="Times,serif" font-size="14.00">begin</text>
16
+ </g>
17
+ <!-- game_begin -->
18
+ <g id="node4" class="node"><title>game_begin</title>
19
+ <ellipse fill="none" stroke="black" cx="174" cy="-726" rx="54.9558" ry="18"/>
20
+ <text text-anchor="middle" x="174" y="-720.4" font-family="Times,serif" font-size="14.00">game_begin</text>
21
+ </g>
22
+ <!-- begin&#45;&gt;game_begin -->
23
+ <g id="edge46" class="edge"><title>begin&#45;&gt;game_begin</title>
24
+ <path fill="none" stroke="black" d="M174,-794.489C174,-781.746 174,-767.024 174,-754.502"/>
25
+ <polygon fill="black" stroke="black" points="177.5,-754.17 174,-744.17 170.5,-754.17 177.5,-754.17"/>
26
+ <text text-anchor="middle" x="176.5" y="-763.4" font-family="Times,serif" font-size="14.00">(</text>
27
+ </g>
28
+ <!-- invalid -->
29
+ <g id="node23" class="node"><title>invalid</title>
30
+ <polygon fill="#ff4444" stroke="black" points="60.0837,-20.5442 60.0837,-35.4558 42.4611,-46 17.5389,-46 -0.0837396,-35.4558 -0.0837396,-20.5442 17.5389,-10 42.4611,-10 60.0837,-20.5442"/>
31
+ <text text-anchor="middle" x="30" y="-22.4" font-family="Times,serif" font-size="14.00">error</text>
32
+ </g>
33
+ <!-- begin&#45;&gt;invalid -->
34
+ <g id="edge48" class="edge"><title>begin&#45;&gt;invalid</title>
35
+ <path fill="none" stroke="#ffbbbb" d="M204.014,-820.483C314.092,-803.369 693.77,-739.341 781,-658 915.865,-532.24 870.516,-425.895 830,-246 824.5,-221.58 827.277,-213.22 814,-192 774.054,-128.158 740.303,-127.064 668,-106 440.842,-39.8213 371.479,-94.3096 138,-56 114.346,-52.1188 88.3239,-45.4471 67.7504,-39.5896"/>
36
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="68.7019,-36.2214 58.1226,-36.7953 66.7507,-42.944 68.7019,-36.2214"/>
37
+ </g>
38
+ <!-- game_node -->
39
+ <g id="node7" class="node"><title>game_node</title>
40
+ <ellipse fill="none" stroke="black" cx="174" cy="-640" rx="51.9298" ry="18"/>
41
+ <text text-anchor="middle" x="174" y="-634.4" font-family="Times,serif" font-size="14.00">game_node</text>
42
+ </g>
43
+ <!-- game_begin&#45;&gt;game_node -->
44
+ <g id="edge64" class="edge"><title>game_begin&#45;&gt;game_node</title>
45
+ <path fill="none" stroke="black" d="M174,-707.762C174,-696.36 174,-681.434 174,-668.494"/>
46
+ <polygon fill="black" stroke="black" points="177.5,-668.212 174,-658.212 170.5,-668.212 177.5,-668.212"/>
47
+ <text text-anchor="middle" x="176.5" y="-677.4" font-family="Times,serif" font-size="14.00">;</text>
48
+ </g>
49
+ <!-- game_begin&#45;&gt;invalid -->
50
+ <g id="edge66" class="edge"><title>game_begin&#45;&gt;invalid</title>
51
+ <path fill="none" stroke="#ffbbbb" d="M189.034,-708.181C199.923,-696.687 215.717,-682.68 233,-676 286.925,-655.158 705.112,-690.388 753,-658 787.614,-634.589 781.991,-612.805 791,-572 803.512,-515.326 855.404,-275.074 792,-192 701.939,-73.9992 283.256,-86.5902 138,-56 114.975,-51.1511 89.4837,-44.5993 69.0509,-39.0525"/>
52
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="69.7337,-35.6106 59.164,-36.3403 67.8818,-42.3612 69.7337,-35.6106"/>
53
+ </g>
54
+ <!-- var_begin -->
55
+ <g id="node6" class="node"><title>var_begin</title>
56
+ <ellipse fill="none" stroke="black" cx="699" cy="-640" rx="44.9809" ry="18"/>
57
+ <text text-anchor="middle" x="699" y="-634.4" font-family="Times,serif" font-size="14.00">var_begin</text>
58
+ </g>
59
+ <!-- var_begin&#45;&gt;game_node -->
60
+ <g id="edge70" class="edge"><title>var_begin&#45;&gt;game_node</title>
61
+ <path fill="none" stroke="black" d="M654.652,-635.933C603.645,-631.475 517.36,-624.611 443,-622 370.931,-619.469 288.175,-626.505 233.701,-632.508"/>
62
+ <polygon fill="black" stroke="black" points="233.076,-629.056 223.531,-633.653 233.86,-636.012 233.076,-629.056"/>
63
+ <text text-anchor="middle" x="440" y="-623.4" font-family="Times,serif" font-size="14.00">;</text>
64
+ </g>
65
+ <!-- var_begin&#45;&gt;invalid -->
66
+ <g id="edge72" class="edge"><title>var_begin&#45;&gt;invalid</title>
67
+ <path fill="none" stroke="#ffbbbb" d="M704.97,-622.028C728.252,-548.187 804.43,-267.018 653,-160 630.845,-144.342 196.1,-95.4045 170,-88 131.769,-77.1539 90.1783,-58.3652 62.3473,-44.6968"/>
68
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="63.6171,-41.4193 53.1051,-40.0971 60.4982,-47.6861 63.6171,-41.4193"/>
69
+ </g>
70
+ <!-- game_node&#45;&gt;var_begin -->
71
+ <g id="edge50" class="edge"><title>game_node&#45;&gt;var_begin</title>
72
+ <path fill="none" stroke="black" d="M226.743,-640C326.419,-640 541.565,-640 643.403,-640"/>
73
+ <polygon fill="black" stroke="black" points="643.485,-643.5 653.485,-640 643.485,-636.5 643.485,-643.5"/>
74
+ <text text-anchor="middle" x="440" y="-641.4" font-family="Times,serif" font-size="14.00">(</text>
75
+ </g>
76
+ <!-- prop_name_begin -->
77
+ <g id="node9" class="node"><title>prop_name_begin</title>
78
+ <ellipse fill="none" stroke="black" cx="174" cy="-554" rx="74.0375" ry="18"/>
79
+ <text text-anchor="middle" x="174" y="-548.4" font-family="Times,serif" font-size="14.00">prop_name_begin</text>
80
+ </g>
81
+ <!-- game_node&#45;&gt;prop_name_begin -->
82
+ <g id="edge52" class="edge"><title>game_node&#45;&gt;prop_name_begin</title>
83
+ <path fill="none" stroke="black" d="M174,-621.762C174,-610.36 174,-595.434 174,-582.494"/>
84
+ <polygon fill="black" stroke="black" points="177.5,-582.212 174,-572.212 170.5,-582.212 177.5,-582.212"/>
85
+ <text text-anchor="middle" x="200.5" y="-591.4" font-family="Times,serif" font-size="14.00">[a&#45;zA&#45;Z]</text>
86
+ </g>
87
+ <!-- var_end -->
88
+ <g id="node20" class="node"><title>var_end</title>
89
+ <ellipse fill="none" stroke="black" cx="174" cy="-124" rx="38.0318" ry="18"/>
90
+ <text text-anchor="middle" x="174" y="-118.4" font-family="Times,serif" font-size="14.00">var_end</text>
91
+ </g>
92
+ <!-- game_node&#45;&gt;var_end -->
93
+ <g id="edge54" class="edge"><title>game_node&#45;&gt;var_end</title>
94
+ <path fill="none" stroke="black" d="M225.514,-637.499C326.191,-632.297 541.889,-619.499 572,-604 598.06,-590.586 615,-583.31 615,-554 615,-554 615,-554 615,-425 615,-345.294 651.9,-309.707 604,-246 557.505,-184.162 322.558,-144.639 220.943,-130.185"/>
95
+ <polygon fill="black" stroke="black" points="221.347,-126.708 210.958,-128.785 220.375,-133.64 221.347,-126.708"/>
96
+ <text text-anchor="middle" x="623.5" y="-376.4" font-family="Times,serif" font-size="14.00">)</text>
97
+ </g>
98
+ <!-- game_node&#45;&gt;invalid -->
99
+ <g id="edge56" class="edge"><title>game_node&#45;&gt;invalid</title>
100
+ <path fill="none" stroke="#ffbbbb" d="M215.515,-628.956C311.427,-600.752 538.639,-517.257 517,-364 509.37,-309.958 521.521,-284.664 483,-246 468.457,-231.404 144.291,-153.206 127,-142 126.394,-141.607 79.7758,-86.6943 51.3959,-53.2349"/>
101
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="53.7501,-50.5995 44.6127,-45.2367 48.4115,-55.1271 53.7501,-50.5995"/>
102
+ </g>
103
+ <!-- prop_name -->
104
+ <g id="node11" class="node"><title>prop_name</title>
105
+ <ellipse fill="none" stroke="black" cx="174" cy="-468" rx="49.9024" ry="18"/>
106
+ <text text-anchor="middle" x="174" y="-462.4" font-family="Times,serif" font-size="14.00">prop_name</text>
107
+ </g>
108
+ <!-- prop_name_begin&#45;&gt;prop_name -->
109
+ <g id="edge58" class="edge"><title>prop_name_begin&#45;&gt;prop_name</title>
110
+ <path fill="none" stroke="black" d="M174,-535.762C174,-524.36 174,-509.434 174,-496.494"/>
111
+ <polygon fill="black" stroke="black" points="177.5,-496.212 174,-486.212 170.5,-496.212 177.5,-496.212"/>
112
+ <text text-anchor="middle" x="200.5" y="-505.4" font-family="Times,serif" font-size="14.00">[a&#45;zA&#45;Z]</text>
113
+ </g>
114
+ <!-- value_begin -->
115
+ <g id="node13" class="node"><title>value_begin</title>
116
+ <ellipse fill="none" stroke="black" cx="174" cy="-382" rx="53.8258" ry="18"/>
117
+ <text text-anchor="middle" x="174" y="-376.4" font-family="Times,serif" font-size="14.00">value_begin</text>
118
+ </g>
119
+ <!-- prop_name_begin&#45;&gt;value_begin -->
120
+ <g id="edge60" class="edge"><title>prop_name_begin&#45;&gt;value_begin</title>
121
+ <path fill="none" stroke="black" d="M210.421,-538.158C218.501,-532.918 226.107,-526.257 231,-518 246.414,-491.989 243.575,-478.326 233,-450 226.707,-433.145 214.145,-417.699 202.223,-405.803"/>
122
+ <polygon fill="black" stroke="black" points="204.601,-403.234 194.945,-398.874 199.774,-408.304 204.601,-403.234"/>
123
+ <text text-anchor="middle" x="244.5" y="-462.4" font-family="Times,serif" font-size="14.00">[</text>
124
+ </g>
125
+ <!-- prop_name_begin&#45;&gt;invalid -->
126
+ <g id="edge62" class="edge"><title>prop_name_begin&#45;&gt;invalid</title>
127
+ <path fill="none" stroke="#ffbbbb" d="M155.178,-536.552C142.27,-523.675 125.621,-505.131 115,-486 38.6639,-348.491 46.3484,-298.62 32,-142 29.2401,-111.875 28.6712,-104.25 29,-74 29.0619,-68.3089 29.1667,-62.2224 29.2859,-56.4015"/>
128
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="32.7861,-56.4289 29.5096,-46.3534 25.7878,-56.273 32.7861,-56.4289"/>
129
+ </g>
130
+ <!-- prop_name&#45;&gt;value_begin -->
131
+ <g id="edge74" class="edge"><title>prop_name&#45;&gt;value_begin</title>
132
+ <path fill="none" stroke="black" d="M174,-449.762C174,-438.36 174,-423.434 174,-410.494"/>
133
+ <polygon fill="black" stroke="black" points="177.5,-410.212 174,-400.212 170.5,-410.212 177.5,-410.212"/>
134
+ <text text-anchor="middle" x="176.5" y="-419.4" font-family="Times,serif" font-size="14.00">[</text>
135
+ </g>
136
+ <!-- prop_name&#45;&gt;invalid -->
137
+ <g id="edge76" class="edge"><title>prop_name&#45;&gt;invalid</title>
138
+ <path fill="none" stroke="#ffbbbb" d="M153.636,-451.342C139.541,-438.704 121.495,-420.119 111,-400 49.7354,-282.557 34.7516,-121.018 31.133,-56.3951"/>
139
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="34.617,-55.9888 30.6124,-46.18 27.6261,-56.3452 34.617,-55.9888"/>
140
+ </g>
141
+ <!-- value -->
142
+ <g id="node15" class="node"><title>value</title>
143
+ <ellipse fill="none" stroke="black" cx="174" cy="-296" rx="29.1856" ry="18"/>
144
+ <text text-anchor="middle" x="174" y="-290.4" font-family="Times,serif" font-size="14.00">value</text>
145
+ </g>
146
+ <!-- value_begin&#45;&gt;value -->
147
+ <g id="edge40" class="edge"><title>value_begin&#45;&gt;value</title>
148
+ <path fill="none" stroke="black" d="M174,-363.762C174,-352.36 174,-337.434 174,-324.494"/>
149
+ <polygon fill="black" stroke="black" points="177.5,-324.212 174,-314.212 170.5,-324.212 177.5,-324.212"/>
150
+ <text text-anchor="middle" x="184.5" y="-333.4" font-family="Times,serif" font-size="14.00">[^]]</text>
151
+ </g>
152
+ <!-- value_escape -->
153
+ <g id="node16" class="node"><title>value_escape</title>
154
+ <ellipse fill="none" stroke="black" cx="336" cy="-296" rx="58.1142" ry="18"/>
155
+ <text text-anchor="middle" x="336" y="-290.4" font-family="Times,serif" font-size="14.00">value_escape</text>
156
+ </g>
157
+ <!-- value_begin&#45;&gt;value_escape -->
158
+ <g id="edge42" class="edge"><title>value_begin&#45;&gt;value_escape</title>
159
+ <path fill="none" stroke="black" d="M202.962,-366.625C229.324,-352.631 268.437,-331.867 297.436,-316.472"/>
160
+ <polygon fill="black" stroke="black" points="299.276,-319.458 306.468,-311.678 295.994,-313.275 299.276,-319.458"/>
161
+ <text text-anchor="middle" x="267" y="-333.4" font-family="Times,serif" font-size="14.00">\</text>
162
+ </g>
163
+ <!-- value_end -->
164
+ <g id="node18" class="node"><title>value_end</title>
165
+ <ellipse fill="none" stroke="black" cx="174" cy="-210" rx="46.877" ry="18"/>
166
+ <text text-anchor="middle" x="174" y="-204.4" font-family="Times,serif" font-size="14.00">value_end</text>
167
+ </g>
168
+ <!-- value_begin&#45;&gt;value_end -->
169
+ <g id="edge44" class="edge"><title>value_begin&#45;&gt;value_end</title>
170
+ <path fill="none" stroke="black" d="M223.054,-374.395C283.665,-363.879 381.452,-342.876 403,-314 450.943,-249.751 312.342,-224.167 230.103,-214.834"/>
171
+ <polygon fill="black" stroke="black" points="230.444,-211.35 220.124,-213.749 229.687,-218.309 230.444,-211.35"/>
172
+ <text text-anchor="middle" x="415.5" y="-290.4" font-family="Times,serif" font-size="14.00">]</text>
173
+ </g>
174
+ <!-- value&#45;&gt;value -->
175
+ <g id="edge14" class="edge"><title>value&#45;&gt;value</title>
176
+ <path fill="none" stroke="black" d="M200.574,-303.806C211.629,-304.344 221,-301.742 221,-296 221,-292.142 216.77,-289.701 210.641,-288.679"/>
177
+ <polygon fill="black" stroke="black" points="210.731,-285.179 200.574,-288.194 210.394,-292.171 210.731,-285.179"/>
178
+ <text text-anchor="middle" x="231.5" y="-290.4" font-family="Times,serif" font-size="14.00">[^]]</text>
179
+ </g>
180
+ <!-- value&#45;&gt;value_escape -->
181
+ <g id="edge12" class="edge"><title>value&#45;&gt;value_escape</title>
182
+ <path fill="none" stroke="black" d="M203.713,-296C221.694,-296 245.404,-296 267.779,-296"/>
183
+ <polygon fill="black" stroke="black" points="267.94,-299.5 277.94,-296 267.94,-292.5 267.94,-299.5"/>
184
+ <text text-anchor="middle" x="240" y="-297.4" font-family="Times,serif" font-size="14.00">\</text>
185
+ </g>
186
+ <!-- value&#45;&gt;value_end -->
187
+ <g id="edge16" class="edge"><title>value&#45;&gt;value_end</title>
188
+ <path fill="none" stroke="black" d="M174,-277.762C174,-266.36 174,-251.434 174,-238.494"/>
189
+ <polygon fill="black" stroke="black" points="177.5,-238.212 174,-228.212 170.5,-238.212 177.5,-238.212"/>
190
+ <text text-anchor="middle" x="176.5" y="-247.4" font-family="Times,serif" font-size="14.00">]</text>
191
+ </g>
192
+ <!-- value_escape&#45;&gt;value -->
193
+ <g id="edge68" class="edge"><title>value_escape&#45;&gt;value</title>
194
+ <path fill="none" stroke="black" d="M296.078,-282.808C278.349,-278.467 257.193,-275.352 238,-278 228.596,-279.297 218.628,-281.619 209.429,-284.173"/>
195
+ <polygon fill="black" stroke="black" points="208.421,-280.821 199.813,-286.998 210.394,-287.538 208.421,-280.821"/>
196
+ <text text-anchor="middle" x="240" y="-279.4" font-family="Times,serif" font-size="14.00">.</text>
197
+ </g>
198
+ <!-- value_end&#45;&gt;var_begin -->
199
+ <g id="edge20" class="edge"><title>value_end&#45;&gt;var_begin</title>
200
+ <path fill="none" stroke="black" d="M221.064,-211.66C349.066,-217.446 694,-242.033 694,-339 694,-554 694,-554 694,-554 694,-573.261 695.265,-594.909 696.523,-611.666"/>
201
+ <polygon fill="black" stroke="black" points="693.055,-612.206 697.335,-621.898 700.033,-611.652 693.055,-612.206"/>
202
+ <text text-anchor="middle" x="696.5" y="-419.4" font-family="Times,serif" font-size="14.00">(</text>
203
+ </g>
204
+ <!-- value_end&#45;&gt;game_node -->
205
+ <g id="edge18" class="edge"><title>value_end&#45;&gt;game_node</title>
206
+ <path fill="none" stroke="black" d="M220.488,-213.028C301.462,-218.651 461.821,-231.464 483,-246 495.96,-254.895 569,-382.967 569,-425 569,-554 569,-554 569,-554 569,-577.472 570.412,-589.443 552,-604 527.784,-623.146 336.627,-633.548 235.798,-637.751"/>
207
+ <polygon fill="black" stroke="black" points="235.588,-634.257 225.739,-638.162 235.874,-641.251 235.588,-634.257"/>
208
+ <text text-anchor="middle" x="571.5" y="-419.4" font-family="Times,serif" font-size="14.00">;</text>
209
+ </g>
210
+ <!-- value_end&#45;&gt;prop_name_begin -->
211
+ <g id="edge22" class="edge"><title>value_end&#45;&gt;prop_name_begin</title>
212
+ <path fill="none" stroke="black" d="M220.595,-213.091C297.764,-218.604 445.483,-230.977 464,-246 475.679,-255.475 472.522,-263.167 475,-278 497.343,-411.73 318.344,-499.678 226.341,-535.62"/>
213
+ <polygon fill="black" stroke="black" points="224.994,-532.388 216.913,-539.24 227.503,-538.923 224.994,-532.388"/>
214
+ <text text-anchor="middle" x="487.5" y="-376.4" font-family="Times,serif" font-size="14.00">[a&#45;zA&#45;Z]</text>
215
+ </g>
216
+ <!-- value_end&#45;&gt;value_begin -->
217
+ <g id="edge24" class="edge"><title>value_end&#45;&gt;value_begin</title>
218
+ <path fill="none" stroke="black" d="M220.569,-212.912C293.913,-217.979 429.534,-229.477 444,-246 473.277,-279.439 473.277,-312.561 444,-346 430.593,-361.313 313.119,-372.311 237.605,-377.872"/>
219
+ <polygon fill="black" stroke="black" points="236.965,-374.409 227.243,-378.621 237.469,-381.391 236.965,-374.409"/>
220
+ <text text-anchor="middle" x="468.5" y="-290.4" font-family="Times,serif" font-size="14.00">[</text>
221
+ </g>
222
+ <!-- value_end&#45;&gt;var_end -->
223
+ <g id="edge26" class="edge"><title>value_end&#45;&gt;var_end</title>
224
+ <path fill="none" stroke="black" d="M174,-191.762C174,-180.36 174,-165.434 174,-152.494"/>
225
+ <polygon fill="black" stroke="black" points="177.5,-152.212 174,-142.212 170.5,-152.212 177.5,-152.212"/>
226
+ <text text-anchor="middle" x="176.5" y="-161.4" font-family="Times,serif" font-size="14.00">)</text>
227
+ </g>
228
+ <!-- value_end&#45;&gt;invalid -->
229
+ <g id="edge28" class="edge"><title>value_end&#45;&gt;invalid</title>
230
+ <path fill="none" stroke="#ffbbbb" d="M150.702,-194.064C133.331,-181.378 109.802,-162.414 93,-142 71.0237,-115.299 52.8214,-79.8169 41.7266,-55.5736"/>
231
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="44.8323,-53.9448 37.5542,-46.2454 38.4424,-56.8029 44.8323,-53.9448"/>
232
+ </g>
233
+ <!-- var_end&#45;&gt;var_begin -->
234
+ <g id="edge32" class="edge"><title>var_end&#45;&gt;var_begin</title>
235
+ <path fill="none" stroke="black" d="M212.103,-125.364C310.15,-129.113 569.322,-140.605 653,-160 711.29,-173.511 778,-150.165 778,-210 778,-554 778,-554 778,-554 778,-578.461 771.042,-585.535 755,-604 749.67,-610.135 743.044,-615.615 736.235,-620.338"/>
236
+ <polygon fill="black" stroke="black" points="734.105,-617.547 727.597,-625.908 737.898,-623.431 734.105,-617.547"/>
237
+ <text text-anchor="middle" x="780.5" y="-376.4" font-family="Times,serif" font-size="14.00">(</text>
238
+ </g>
239
+ <!-- var_end&#45;&gt;game_node -->
240
+ <g id="edge30" class="edge"><title>var_end&#45;&gt;game_node</title>
241
+ <path fill="none" stroke="black" d="M211.044,-128.204C246.635,-132.144 301.943,-138.01 350,-142 381.289,-144.598 605.972,-142.44 632,-160 652.434,-173.786 656,-185.35 656,-210 656,-554 656,-554 656,-554 656,-579.255 650.162,-590.216 629,-604 596.854,-624.937 352.973,-634.799 236.093,-638.36"/>
242
+ <polygon fill="black" stroke="black" points="235.758,-634.868 225.867,-638.665 235.967,-641.865 235.758,-634.868"/>
243
+ <text text-anchor="middle" x="658.5" y="-376.4" font-family="Times,serif" font-size="14.00">;</text>
244
+ </g>
245
+ <!-- var_end&#45;&gt;var_end -->
246
+ <g id="edge36" class="edge"><title>var_end&#45;&gt;var_end</title>
247
+ <path fill="none" stroke="black" d="M208.176,-131.871C220.224,-131.997 230,-129.373 230,-124 230,-120.306 225.379,-117.912 218.576,-116.817"/>
248
+ <polygon fill="black" stroke="black" points="218.385,-113.297 208.176,-116.129 217.923,-120.281 218.385,-113.297"/>
249
+ <text text-anchor="middle" x="232.5" y="-118.4" font-family="Times,serif" font-size="14.00">)</text>
250
+ </g>
251
+ <!-- game_end -->
252
+ <g id="node22" class="node"><title>game_end</title>
253
+ <ellipse fill="#44ff44" stroke="black" cx="174" cy="-28" rx="22.9471" ry="23.372"/>
254
+ <ellipse fill="none" stroke="black" cx="174" cy="-28" rx="26.8743" ry="27.372"/>
255
+ <text text-anchor="middle" x="174" y="-22.4" font-family="Times,serif" font-size="14.00">end</text>
256
+ </g>
257
+ <!-- var_end&#45;&gt;game_end -->
258
+ <g id="edge34" class="edge"><title>var_end&#45;&gt;game_end</title>
259
+ <path fill="none" stroke="black" d="M174,-105.943C174,-94.6899 174,-79.7809 174,-66.0175"/>
260
+ <polygon fill="black" stroke="black" points="177.5,-65.7953 174,-55.7954 170.5,-65.7954 177.5,-65.7953"/>
261
+ <text text-anchor="middle" x="187.5" y="-75.4" font-family="Times,serif" font-size="14.00">EOS</text>
262
+ </g>
263
+ <!-- var_end&#45;&gt;invalid -->
264
+ <g id="edge38" class="edge"><title>var_end&#45;&gt;invalid</title>
265
+ <path fill="none" stroke="#ffbbbb" d="M151.816,-109.21C126.9,-92.5997 86.3725,-65.5817 58.9735,-47.3157"/>
266
+ <polygon fill="#ffbbbb" stroke="#ffbbbb" points="60.8375,-44.3519 50.5755,-41.717 56.9545,-50.1762 60.8375,-44.3519"/>
267
+ </g>
268
+ </g>
269
+ </svg>