Class: AtCoderFriends::CxxGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/at_coder_friends/cxx_generator.rb

Overview

generates C++ source code from definition

Constant Summary collapse

TEMPLATE =
<<~TEXT
  #include <cstdio>

  using namespace std;

  #define REP(i,n)   for(int i=0; i<(int)(n); i++)
  #define FOR(i,b,e) for(int i=(b); i<=(int)(e); i++)

  /*** CONSTS ***/

  /*** DCLS ***/

  void solve() {
    int ans = 0;
    printf("%d\\n", ans);
  }

  void input() {
  /*** READS ***/
  }

  int main() {
    input();
    solve();
    return 0;
  }
TEXT
SCANF_FMTS =
[
  'scanf("%<fmt>s", %<addr>s);',
  'REP(i, %<sz1>s) scanf("%<fmt>s", %<addr>s);',
  'REP(i, %<sz1>s) REP(j, %<sz2>s) scanf("%<fmt>s", %<addr>s);'
].freeze
FMT_FMTS =
{ number: '%d', string: '%s', char: '%s' }.freeze
ADDR_FMTS =
{
  single: {
    number: '&%<v>s',
    string: '%<v>s'
  },
  harray: {
    number: '%<v>s + i',
    string: '%<v>s[i]',
    char: '%<v>s'
  },
  varray: {
    number: '%<v>s + i',
    string: '%<v>s[i]'
  },
  matrix: {
    number: '&%<v>s[i][j]',
    string: '%<v>s[i][j]',
    char: '%<v>s[i]'
  }
}.freeze

Instance Method Summary collapse

Instance Method Details

#gen_arr_size(szs) ⇒ Object



155
156
157
# File 'lib/at_coder_friends/cxx_generator.rb', line 155

def gen_arr_size(szs)
  szs.map { |sz| sz =~ /\D/ ? "#{sz.upcase}_MAX" : sz }
end

#gen_consts(desc) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
# File 'lib/at_coder_friends/cxx_generator.rb', line 78

def gen_consts(desc)
  desc
    .gsub(/[,\\\(\)\{\}\|]/, '')
    .gsub(/(≤|leq)/i, '')
    .scan(/([\da-z_]+)\s*≦\s*(\d+)(?:\^(\d+))?/i)
    .map do |v, sz, k|
      sz = sz.to_i
      sz **= k.to_i if k
      "const int #{v.upcase}_MAX = #{sz};"
    end
end

#gen_decl(inpdef) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/at_coder_friends/cxx_generator.rb', line 94

def gen_decl(inpdef)
  case inpdef.container
  when :single
    gen_single_decl(inpdef)
  when :harray
    gen_harray_decl(inpdef)
  when :varray
    gen_varray_decl(inpdef)
  when :matrix
    gen_matrix_decl(inpdef)
  end
end

#gen_decls(defs) ⇒ Object



90
91
92
# File 'lib/at_coder_friends/cxx_generator.rb', line 90

def gen_decls(defs)
  defs.map { |inpdef| gen_decl(inpdef) }.flatten
end

#gen_harray_decl(inpdef) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/at_coder_friends/cxx_generator.rb', line 118

def gen_harray_decl(inpdef)
  v = inpdef.names[0]
  sz = gen_arr_size(inpdef.size)[0]
  case inpdef.item
  when :number
    "int #{v}[#{sz}];"
  when :string
    "char #{v}[#{sz}][#{v.upcase}_MAX + 1];"
  when :char
    "char #{v}[#{sz} + 1];"
  end
end

#gen_matrix_decl(inpdef) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/at_coder_friends/cxx_generator.rb', line 142

def gen_matrix_decl(inpdef)
  v = inpdef.names[0]
  sz1, sz2 = gen_arr_size(inpdef.size)
  case inpdef.item
  when :number
    "int #{v}[#{sz1}][#{sz2}];"
  when :string
    "char #{v}[#{sz1}][#{sz2}][#{v.upcase}_MAX + 1];"
  when :char
    "char #{v}[#{sz1}][#{sz2} + 1];"
  end
end

#gen_read(inpdef) ⇒ Object

rubocop:disable Metrics/AbcSize



164
165
166
167
168
169
170
171
172
# File 'lib/at_coder_friends/cxx_generator.rb', line 164

def gen_read(inpdef)
  dim = inpdef.size.size - (inpdef.item == :char ? 1 : 0)
  scanf = SCANF_FMTS[dim]
  sz1, sz2 = inpdef.size
  fmt = FMT_FMTS[inpdef.item] * inpdef.names.size
  addr_fmt = ADDR_FMTS[inpdef.container][inpdef.item]
  addr = inpdef.names.map { |v| format(addr_fmt, v: v) }.join(', ')
  format(scanf, sz1: sz1, sz2: sz2, fmt: fmt, addr: addr)
end

#gen_reads(defs) ⇒ Object



159
160
161
# File 'lib/at_coder_friends/cxx_generator.rb', line 159

def gen_reads(defs)
  defs.map { |inpdef| gen_read(inpdef) }.flatten
end

#gen_single_decl(inpdef) ⇒ Object



107
108
109
110
111
112
113
114
115
116
# File 'lib/at_coder_friends/cxx_generator.rb', line 107

def gen_single_decl(inpdef)
  names = inpdef.names
  case inpdef.item
  when :number
    dcl = names.join(', ')
    "int #{dcl};"
  when :string
    names.map { |v| "char #{v}[#{v.upcase}_MAX + 1];" }
  end
end

#gen_varray_decl(inpdef) ⇒ Object



131
132
133
134
135
136
137
138
139
140
# File 'lib/at_coder_friends/cxx_generator.rb', line 131

def gen_varray_decl(inpdef)
  names = inpdef.names
  sz = gen_arr_size(inpdef.size)[0]
  case inpdef.item
  when :number
    names.map { |v| "int #{v}[#{sz}];" }
  when :string
    names.map { |v| "char #{v}[#{sz}][#{v.upcase}_MAX + 1];" }
  end
end

#generate(defs, desc) ⇒ Object



68
69
70
71
72
73
74
75
76
# File 'lib/at_coder_friends/cxx_generator.rb', line 68

def generate(defs, desc)
  consts = gen_consts(desc)
  dcls = gen_decls(defs)
  reads = gen_reads(defs)
  TEMPLATE
    .sub('/*** CONSTS ***/', consts.join("\n"))
    .sub('/*** DCLS ***/', dcls.join("\n"))
    .sub('/*** READS ***/', reads.map { |s| '  ' + s }.join("\n"))
end

#process(pbm) ⇒ Object



63
64
65
66
# File 'lib/at_coder_friends/cxx_generator.rb', line 63

def process(pbm)
  src = generate(pbm.defs, pbm.desc)
  pbm.add_src(:cxx, src)
end