Class: Resyma::MonoLanguage

Inherits:
Object
  • Object
show all
Defined in:
lib/resyma/language.rb

Overview

Language created from single automaton and a associated action. Syntax:

regex >> expr

where ‘regex` should adhere to syntax described in Resyma::RegexBuildVistor, and `expr` is an arbitrary ruby expression. Note that

- Readonly variable `nodes` is visible in the `expr`, which is a `Array` of
  Resyma::Core::ParseTree and denotes the derivational node sequence
- Readonly variables `src_binding`, `src_filename` and `src_lineno` are
  visible in the `expr`, which describe the environment surrounding the DSL
- Variables above can be shadowed by local variables
- Multiple expressions can be grouped to atom by `begin; end`

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(automaton, action) ⇒ MonoLanguage

Returns a new instance of MonoLanguage.



147
148
149
150
# File 'lib/resyma/language.rb', line 147

def initialize(automaton, action)
  @automaton = automaton
  @action = action
end

Instance Attribute Details

#actionObject

Returns the value of attribute action.



152
153
154
# File 'lib/resyma/language.rb', line 152

def action
  @action
end

#automatonObject

Returns the value of attribute automaton.



152
153
154
# File 'lib/resyma/language.rb', line 152

def automaton
  @automaton
end

Class Method Details

.from(ast, bd, filename, _lino) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/resyma/language.rb', line 158

def self.from(ast, bd, filename, _lino)
  if ast.type != :send
    raise IllegalLanguageDefinitionError,
          "AST with type #{ast} cannot define a language"
  elsif ast.children[1] != :>>
    raise IllegalLanguageDefinitionError,
          "Only AST whose operator is '>>' can define a language"
  elsif ast.children.length != 3
    raise IllegalLanguageDefinitionError,
          "Language definition should be 'regex >> expr'"
  end

  regex_ast, _, action_ast = ast.children

  automaton = RegexBuildVistor.new.visit(regex_ast).to_automaton
  action_proc_ast = node :block, [
    node(:send, [nil, :lambda]),
    node(:args, [node(:arg, [:__ae__])]),
    node(:block, [
           node(:send, [node(:lvar, [:__ae__]), :instance_eval]),
           node(:args, []),
           action_ast
         ])
  ]
  action_str = Unparser.unparse(action_proc_ast)
  # lambda generated by unparser will add two lines before our code
  # The following adjustment allow us to locate `proc`s in the action
  # properly
  action = eval(action_str, bd, filename,
                action_ast.loc.expression.line - 2)
  new automaton, action
end

.node(type, children) ⇒ Object



154
155
156
# File 'lib/resyma/language.rb', line 154

def self.node(type, children)
  Parser::AST::Node.new(type, children)
end