blob: f358e2a4a87d01d61b3b6f178b2918b385a94eef (
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
61
62
63
64
65
66
67
68
69
70
71
|
#!/usr/bin/env raku
#
# This Raku program takes a list of C struct and constant definitions and converts
# it to valid Go code.
use v6.d;
#use Grammar::Debugger;
# Not quite C
grammar NQC {
rule TOP { <construct>* }
rule construct { <constant> | <statement> | <comment> }
rule constant { '#define' <identifier> <number> <-[\n]>+ }
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\}\n\n"
~ self!struct-go-string-method($/);
}
# Generate String() method on the Go struct, for pretty printing.
method !struct-go-string-method($/) returns Str {
my Str $self-ref = $<identifier>.lc.substr(0,1);
my Str @format = $<member>.map({ $_.<identifier>.made ~ ':%v' });
my Str @args = $<member>.map({ "$self-ref." ~ $_.<identifier>.made });
return qq:to/END/;
func ({$self-ref} {$<identifier>}) String() string \{
\treturn fmt.Sprintf("{@format.join(' ')}", {@args.join(', ')})
\}
END
}
method member($/) { make $<identifier>.made ~ ' ' ~ ($<arraysize> // '') ~ $<type>.made }
method type($/) {
make do given ~$/ {
when 'char' { 'byte' }
when '__s32' { 'int32' }
when '__u32' { 'uint32' }
when '__u64' { 'uint64' }
}
}
# Convert identifier from snake_case (C) to CamelCase (Go)
method identifier($/) { make $/.Str.split('_').map(*.tc).join('') }
}
say NQC.parse($*IN.slurp, :actions(NQCToGoActions)).made;
|