2 # Defines a transition between one parser State and another.
4 # A state transition is triggered when a regular expression or "token" match
5 # is found in the source code.
7 # The Transition class handles transitions between states in a single language. To
8 # define transitions between two different languages, use the StitchTransition class.
10 # This transition defines state changes within this language only.
13 # A regular expression which triggers the state transition when it is matched.
16 # This transition can only be followed when we are in the 'from' state.
19 # The state we will transition to when the token is matched.
22 # One of :from, :to, or :neither.
24 # This determines which state 'owns' the text of the token.
26 # For instance, a double-quote character in the source code might trigger
27 # a transition from a code state to a string state.
28 # The who_eats value dictates whether the double-quote character itself
29 # should be considered part of the code or part of the string.
32 # Set to true if this transition should be ignored -- that is, continue
33 # on without changing state, and do not notify any listeners that a state
36 # Why would we ever want this?
37 # One example use is handling escaped string chars in the CMonoglot.
38 # When we are in the string state, we want to ignore all escaped double-quotes (\")
39 # since these should not return us to the code state. We do this by swallowing the
40 # entire \" token with a fake transition and remaining in the string state.
41 # Without this fake transition, the \ would be considered an ordinary part of the
42 # string and the " would incorrectly return us to the code state.
45 # Each transition needs a unique name. The default name is generated
46 # by combining the language name with the names of the 'from' state and the 'to' state.
47 # In the case that this is not unique, you may provide an additional string here
48 # that will be appended to the generated name.
49 attr_reader :name_extension
51 def initialize(language, token, from, to, who_eats, fake, name_extension = "")
58 @name_extension = name_extension.to_s.upcase
62 "#{ language.upcase }_#{ from.to_s.upcase }__#{ to.to_s.upcase }#{ name_extension == "" ? "" : "_" + name_extension }".upcase
74 raise 'UnknownWhoEats'
78 # Emit the transition as a C code definition in the generated source file.
80 full_from = from == :return ? "RETURN" : "&#{ language }_#{ from }".upcase
81 full_to = to == :return ? "RETURN" : "&#{ language }_#{ to }".upcase
82 io.puts %(Transition #{ definition } = { "#{ token }", #{ full_from }, #{ full_to }, #{ self.token_eater }, #{ fake } };)
86 # Represents a transition from a state in one Monoglot to a state in another Monoglot.
87 class StitchTransition < Transition
88 def initialize(token, from, to, who_eats, fake, polyglot_name)
94 @polyglot_name = polyglot_name
98 "#{ @polyglot_name.upcase }_#{ @from.to_s.upcase }__#{ @to.to_s.upcase }"
102 full_from = @from == :return ? "RETURN" : "&#{ @from }".upcase
103 full_to = @to == :return ? "RETURN" : "&#{ @to }".upcase
104 io.puts %(Transition #{ definition } = { "#{ @token }", #{ full_from }, #{ full_to }, #{ self.token_eater }, #{ @fake } };)