~bduggan/raku-protobuf

ref: 1111fa768f7a83817e7b58bc8a8e0d5ba43739eb raku-protobuf/lib/Protobuf/Actions.rakumod -rw-r--r-- 1.8 KiB
1111fa76Brian Duggan repeated 7 months ago
                                                                                
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
72
73
74
75
76
class Protobuf::Service {
  has $.name;
  has @.endpoints;
}
class Protobuf::Definition {
  has @.services;
  has @.messages;
}
class Protobuf::Endpoint {
  has $.name;
  has $.request is rw;
  has $.response is rw;
}
class Protobuf::Message {
  has $.name;
  has @.fields;
}
class Protobuf::Field {
  has $.name;
  has $.type;
  has Bool $.repeated = False;
}

class Protobuf::Actions {

  method TOP($/) {
    my @things := $<proto>.made.List;
    my @services = @things.grep( * ~~ Protobuf::Service );
    my @messages = @things.grep( * ~~ Protobuf::Message );
    for @services -> $s {
      for $s.endpoints -> $e {
        $e.request = %*messages{ $e.request.name };
        $e.response = %*messages{ $e.response.name };
      }
    }
    $/.make: Protobuf::Definition.new: :@services, :@messages;
  }

  method proto($/) {
    $/.make: $<topLevelDef>.map( *.made ).grep( *.defined )
  }

  method topLevelDef($/) {
    $/.make: $<service>.made // $<message>.made
  }

  method message($/) {
    my $name = ~$<messageName>;
    my @fields = $<messageBody>.made;
    my $msg =  Protobuf::Message.new( :$name, :@fields );
    %*messages{ $name } = $msg;
    $/.make: $msg;
  }

  method messageBody($/) {
    $/.make: $<field>.map: *.made;
  }

  method field($/) {
    my $type = ~$<type>;
    my $repeated = $<repeated>.chars > 0;
    $/.make: Protobuf::Field.new( name => ~$<fieldName>, type => %*messages{ $type } // $type, :$repeated );
  }

  method service($/) {
    $/.make: Protobuf::Service.new: name => ~$<serviceName>, endpoints => ($<rpc>.map(*.made).grep(*.defined))
  }

  method rpc($/) {
    $/.make: Protobuf::Endpoint.new(name => ~$<rpcName>, request => $<request>.?made, response => $<response>.?made )
  }

  method messageType($/) {
    $/.make: Protobuf::Message.new: name => ~$<messageName>
  }
}