Initial Revision
[ohcount] / ext / ohcount_native / glots / monoglot.rb
1 require 'escape_helper'
2
3 module Ohcount
4         # A Monoglot is a compile-time code generator.
5         # It generates C source code which defines the states and transitions
6         # required for a single language parser.
7         #
8         # To create a parser which spans multiple languages, use a Polyglot.
9         class Monoglot
10                 include EscapeHelper
11
12                 # The name must be unique
13                 attr_reader :name
14
15                 # A collection of State objects representing possible states
16                 attr_reader :states
17
18                 # The Transition objects defining transitions between states
19                 attr_reader :transitions
20
21                 def initialize(name, states = [], transitions = [])
22                         @name = name
23                         @states = states
24                         @transitions = transitions
25                 end
26
27                 # Emit the generated C code for the state machine definition.
28                 def print(io)
29                         Monoglot::print_banner(io, name)
30                         print_states(io)
31                         print_transitions(io)
32                         print_polyglot_def(io)
33                 end
34
35                 def self.print_banner(io, name)
36                         io.puts ""
37                         io.puts "/*****************************************************************************"
38                         left = (80 - name.size)/2
39                         io.write " "*left
40                         io.puts name
41                         io.puts "*****************************************************************************/"
42                 end
43
44                 def definition
45                 "#{ @name.upcase }_POLYGLOT"
46                 end
47                 protected
48
49                 def print_states(io)
50                         #define each
51                         io.puts "/* States */"
52                         @states.each do |s|
53                                 s.print(io)
54                         end
55
56                         # now define the collection
57                         io.write "State *#{ name.upcase }_STATES[] = { "
58                         @states.each do |s|
59                                 io.write "&#{ s.definition }, "
60                         end
61                         io.write "NULL };\n"
62                 end
63
64                 def print_transitions(io)
65                         io.puts "/* Transitions */"
66                         # print each transition
67                         @transitions.each do |t|
68                                 t.print(io)
69                         end
70
71                         #aggregate the transitions
72                         io.write  "Transition *#{ name.upcase }_TRANSITIONS[] = {"
73                         @transitions.each do |t|
74                                 io.write " &#{ t.definition },"
75                         end
76                         io.write " NULL};\n"
77                 end
78
79                 def print_polyglot_def(io)
80                         io.puts <<LANG_DEF
81 Polyglot #{ definition } = {
82         "#{ @name.downcase }",
83                         #{ @name.upcase }_STATES,
84                         #{ @name.upcase }_TRANSITIONS,
85         NULL
86 };
87 LANG_DEF
88                 end
89
90         end
91 end