blob: f381fafd92f599740120cf2972489fc7f3271b2a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#!/usr/bin/env raku
#
# This Raku program takes a list of C struct and constant definitions and converts
# it to valid Go code.
#use Grammar::Debugger;
# Not quite C
grammar NQC {
rule TOP { <construct>* }
rule construct { <constant> | <statement> || <comment> }
rule constant { '#define' <identifier> <number> }
rule statement { <struct> ';' }
rule struct { 'struct' <identifier> '{' <member>+ %% ';' '}' }
rule member { <type> <identifier> <arraysize>? }
rule comment { <single-line-comment> | <multi-line-comment> }
rule single-line-comment { '//' <-[\n]>+ }
rule multi-line-comment { '/*' .*? '*/' }
token arraysize { '[' <identifier> ']' }
token type { 'char' | '__s32' | '__u32' | '__u64' }
token identifier { <[a..z A..Z 0..9 _]>+ }
token number { \d+ }
}
class NQCToGoActions {
method TOP($/) {
make "// This file was generated - don't change manually!\n" ~
"package types\n\n" ~
$<construct>.map(*.made).join('')
}
method construct($/) { make $<constant>.made // $<statement>.made // '' }
method statement($/) { make "\n" ~ $<struct>.made ~ "\n"; }
method constant($/) { make 'const ' ~ $<identifier> ~ ' = ' ~ $<number> ~ "\n" }
method struct($/) {
make 'type ' ~ $<identifier>.made ~ " struct \{\n\t" ~
$<member>.map(*.made).join("\n\t") ~ "\n\}"
}
method member($/) {
make $<identifier>.made ~ ' ' ~ ($<arraysize> ?? $<arraysize> !! '') ~ $<type>.made
}
method type($/) {
make do given ~$/ {
when 'char' { 'byte' }
when '__s32' { 'int32' }
when '__u32' { 'uint32' }
when '__u64' { 'uint64' }
};
}
method identifier($/) {
# Convert identifier from snake_case (C) to CamelCase (Go)
make $/.Str.split('_').map(*.tc).join('')
}
}
say NQC.parse($*IN.slurp, :actions(NQCToGoActions.new)).made;
|