Add Julian Scheid to credits, and add TODO note about character set support.
[vtparse.git] / vtparse_tables.rb
blob51ec53184745c9ad903dc6ac0f9f31cb318b6f57
2 class StateTransition
3     attr_accessor :to_state
4     def initialize(to_state)
5         @to_state = to_state
6     end
7 end
9 def transition_to(state)
10     StateTransition.new(state)
11 end
13 $states = {}
15 $anywhere_transitions = {
16     0x18       => [:execute, transition_to(:GROUND)],
17     0x1a       => [:execute, transition_to(:GROUND)],
18     0x80..0x8f => [:execute, transition_to(:GROUND)],
19     0x91..0x97 => [:execute, transition_to(:GROUND)],
20     0x99       => [:execute, transition_to(:GROUND)],
21     0x9a       => [:execute, transition_to(:GROUND)],
22     0x9c       => transition_to(:GROUND),
23     0x1b       => transition_to(:ESCAPE),
24     0x98       => transition_to(:SOS_PM_APC_STRING),
25     0x9e       => transition_to(:SOS_PM_APC_STRING),
26     0x9f       => transition_to(:SOS_PM_APC_STRING),
27     0x90       => transition_to(:DCS_ENTRY),
28     0x9d       => transition_to(:OSC_STRING),
29     0x9b       => transition_to(:CSI_ENTRY),
32 $states[:GROUND] = {
33     0x00..0x17 => :execute,
34     0x19       => :execute,
35     0x1c..0x1f => :execute,
36     0x20..0x7f => :print,
39 $states[:ESCAPE] = {
40     :on_entry  => :clear,
41     0x00..0x17 => :execute,
42     0x19       => :execute,
43     0x1c..0x1f => :execute,
44     0x7f       => :ignore,
45     0x20..0x2f => [:collect, transition_to(:ESCAPE_INTERMEDIATE)],
46     0x30..0x4f => [:esc_dispatch, transition_to(:GROUND)],
47     0x51..0x57 => [:esc_dispatch, transition_to(:GROUND)],
48     0x59       => [:esc_dispatch, transition_to(:GROUND)],
49     0x5a       => [:esc_dispatch, transition_to(:GROUND)],
50     0x5c       => [:esc_dispatch, transition_to(:GROUND)],
51     0x60..0x7e => [:esc_dispatch, transition_to(:GROUND)],
52     0x5b       => transition_to(:CSI_ENTRY),
53     0x5d       => transition_to(:OSC_STRING),
54     0x50       => transition_to(:DCS_ENTRY),
55     0x58       => transition_to(:SOS_PM_APC_STRING),
56     0x5e       => transition_to(:SOS_PM_APC_STRING),
57     0x5f       => transition_to(:SOS_PM_APC_STRING),
60 $states[:ESCAPE_INTERMEDIATE] = {
61     0x00..0x17 => :execute,
62     0x19       => :execute,
63     0x1c..0x1f => :execute,
64     0x20..0x2f => :collect,
65     0x7f       => :ignore,
66     0x30..0x7e => [:esc_dispatch, transition_to(:GROUND)]
69 $states[:CSI_ENTRY] = {
70     :on_entry  => :clear,
71     0x00..0x17 => :execute,
72     0x19       => :execute,
73     0x1c..0x1f => :execute,
74     0x7f       => :ignore,
75     0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)],
76     0x3a       => transition_to(:CSI_IGNORE),
77     0x30..0x39 => [:param, transition_to(:CSI_PARAM)],
78     0x3b       => [:param, transition_to(:CSI_PARAM)],
79     0x3c..0x3f => [:collect, transition_to(:CSI_PARAM)],
80     0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)]
83 $states[:CSI_IGNORE] = {
84     0x00..0x17 => :execute,
85     0x19       => :execute,
86     0x1c..0x1f => :execute,
87     0x20..0x3f => :ignore,
88     0x7f       => :ignore,
89     0x40..0x7e => transition_to(:GROUND),
92 $states[:CSI_PARAM] = {
93     0x00..0x17 => :execute,
94     0x19       => :execute,
95     0x1c..0x1f => :execute,
96     0x30..0x39 => :param,
97     0x3b       => :param,
98     0x7f       => :ignore,
99     0x3a       => transition_to(:CSI_IGNORE),
100     0x3c..0x3f => transition_to(:CSI_IGNORE),
101     0x20..0x2f => [:collect, transition_to(:CSI_INTERMEDIATE)],
102     0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)]
105 $states[:CSI_INTERMEDIATE] = {
106     0x00..0x17 => :execute,
107     0x19       => :execute,
108     0x1c..0x1f => :execute,
109     0x20..0x2f => :collect,
110     0x7f       => :ignore,
111     0x30..0x3f => transition_to(:CSI_IGNORE),
112     0x40..0x7e => [:csi_dispatch, transition_to(:GROUND)],
115 $states[:DCS_ENTRY] = {
116     :on_entry  => :clear,
117     0x00..0x17 => :ignore,
118     0x19       => :ignore,
119     0x1c..0x1f => :ignore,
120     0x7f       => :ignore,
121     0x3a       => transition_to(:DCS_IGNORE),
122     0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)],
123     0x30..0x39 => [:param, transition_to(:DCS_PARAM)],
124     0x3b       => [:param, transition_to(:DCS_PARAM)],
125     0x3c..0x3f => [:collect, transition_to(:DCS_PARAM)],
126     0x40..0x7e => [transition_to(:DCS_PASSTHROUGH)]
129 $states[:DCS_INTERMEDIATE] = {
130     0x00..0x17 => :ignore,
131     0x19       => :ignore,
132     0x1c..0x1f => :ignore,
133     0x20..0x2f => :collect,
134     0x7f       => :ignore,
135     0x30..0x3f => transition_to(:DCS_IGNORE),
136     0x40..0x7e => transition_to(:DCS_PASSTHROUGH)
139 $states[:DCS_IGNORE] = {
140     0x00..0x17 => :ignore,
141     0x19       => :ignore,
142     0x1c..0x1f => :ignore,
143     0x20..0x7f => :ignore,
146 $states[:DCS_PARAM] = {
147     0x00..0x17 => :ignore,
148     0x19       => :ignore,
149     0x1c..0x1f => :ignore,
150     0x30..0x39 => :param,
151     0x3b       => :param,
152     0x7f       => :ignore,
153     0x3a       => transition_to(:DCS_IGNORE),
154     0x3c..0x3f => transition_to(:DCS_IGNORE),
155     0x20..0x2f => [:collect, transition_to(:DCS_INTERMEDIATE)],
156     0x40..0x7e => transition_to(:DCS_PASSTHROUGH)
159 $states[:DCS_PASSTHROUGH] = {
160     :on_entry  => :hook,
161     0x00..0x17 => :put,
162     0x19       => :put,
163     0x1c..0x1f => :put,
164     0x20..0x7e => :put,
165     0x7f       => :ignore,
166     :on_exit   => :unhook
169 $states[:SOS_PM_APC_STRING] = {
170     0x00..0x17 => :ignore,
171     0x19       => :ignore,
172     0x1c..0x1f => :ignore,
173     0x20..0x7f => :ignore,
176 $states[:OSC_STRING] = {
177     :on_entry  => :osc_start,
178     0x00..0x17 => :ignore,
179     0x19       => :ignore,
180     0x1c..0x1f => :ignore,
181     0x20..0x7f => :osc_put,
182     :on_exit   => :osc_end
186 # get the list of actions implicit in the tables
188 action_names = {}
189 $states.each { |state, transitions|
190     transitions.each { |keys, actions|
191         actions = [actions] if !actions.kind_of?(Array)
192         actions.each { |action|
193             if action.kind_of?(Symbol)
194                 action_names[action] = 1
195             end
196         }
197     }
200 # establish an ordering to the states and actions
202 $actions_in_order = action_names.keys.sort   { |a1, a2| a1.to_s <=> a2.to_s } + [:error]
203 $states_in_order  = $states.keys.sort  { |s1, s2| s1.to_s <=> s2.to_s }
208 # Expand the above range-based data structures (which are convenient
209 # to write) into fully expanded tables (which are easier to use).
212 $state_tables = {}
214 def expand_ranges(hash_with_ranges_as_keys)
215     array = []
216     hash_with_ranges_as_keys.each { |range, val|
217         if range.kind_of?(Range)
218             range.each { |i|
219                 array[i] = val
220             }
221         elsif range.kind_of?(Fixnum)
222             array[range] = val
223         end
224     }
226     array
229 $states.each { |state, transitions|
230     $state_tables[state] = expand_ranges(transitions)
233 # seed all the states with the anywhere transitions
234 $anywhere_transitions = expand_ranges($anywhere_transitions)
236 $state_tables.each { |state, transitions|
237     $anywhere_transitions.each_with_index { |transition, i|
238         next if transition.nil?
239         if transitions[i]
240             raise "State #{state} already had a transition defined for 0x#{i.to_s(16)}, but " + \
241                   "that transition is also an anywhere transition!"
242         end
243         transitions[i] = transition
244     }
247 # for consistency, make all transitions *lists* of actions
248 $state_tables.each { |state, transitions|
249     transitions.map! { |t| t.kind_of?(Array) ? t : [t] }