ruby_protobuf 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +6 -1
- data/Manifest.txt +23 -2
- data/bin/rprotoc +5 -5
- data/examples/addressbook.proto +24 -0
- data/examples/addressbook.rb +30 -0
- data/examples/reading_a_message.rb +32 -0
- data/examples/writing_a_message.rb +46 -0
- data/lib/protobuf/compiler/compiler.rb +38 -74
- data/lib/protobuf/compiler/compiler_old.rb +123 -0
- data/lib/protobuf/compiler/nodes.rb +208 -0
- data/lib/protobuf/compiler/proto.y +198 -0
- data/lib/protobuf/compiler/proto2.ebnf +79 -0
- data/lib/protobuf/compiler/proto_parser.rb +1259 -0
- data/lib/protobuf/compiler/template/rpc_bin.erb +4 -0
- data/lib/protobuf/compiler/template/rpc_client.erb +18 -0
- data/lib/protobuf/compiler/template/rpc_service.erb +25 -0
- data/lib/protobuf/compiler/visitors.rb +132 -0
- data/lib/protobuf/message/decoder.rb +8 -3
- data/lib/protobuf/message/enum.rb +4 -0
- data/lib/protobuf/message/field.rb +31 -5
- data/lib/protobuf/message/message.rb +130 -14
- data/lib/protobuf/rpc/client.rb +19 -0
- data/lib/protobuf/rpc/handler.rb +17 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/ruby_protobuf.rb +1 -20
- data/test/addressbook.proto +6 -0
- data/test/addressbook.rb +17 -14
- data/test/addressbook_base.proto +26 -0
- data/test/addressbook_base.rb +62 -0
- data/test/addressbook_ext.proto +6 -0
- data/test/addressbook_ext.rb +12 -0
- data/test/rpc.proto +6 -0
- data/test/test_addressbook.rb +3 -2
- data/test/test_compiler.rb +98 -3
- data/test/test_extension.rb +40 -0
- data/test/test_standard_message.rb +83 -0
- data/test/test_types.rb +3 -3
- metadata +31 -8
- data/lib/protobuf/compiler/parser.y +0 -138
- data/test/data/data2.bin +0 -3
@@ -0,0 +1,198 @@
|
|
1
|
+
class Protobuf::ProtoParser
|
2
|
+
#options no_result_var
|
3
|
+
rule
|
4
|
+
proto : proto_item
|
5
|
+
{ result = Protobuf::Node::ProtoNode.new val }
|
6
|
+
| proto proto_item
|
7
|
+
{ result.children << val[1] }
|
8
|
+
|
9
|
+
proto_item : message
|
10
|
+
| extend
|
11
|
+
| enum
|
12
|
+
| import
|
13
|
+
| package
|
14
|
+
| option
|
15
|
+
| service
|
16
|
+
| ';'
|
17
|
+
{ }
|
18
|
+
|
19
|
+
import : 'import' STRING_LITERAL ';'
|
20
|
+
{ result = Protobuf::Node::ImportNode.new val[1] }
|
21
|
+
|
22
|
+
package : 'package' IDENT dot_ident_list ';'
|
23
|
+
{ result = Protobuf::Node::PackageNode.new val[2].unshift(val[1]) }
|
24
|
+
|
25
|
+
dot_ident_list :
|
26
|
+
{ result = [] }
|
27
|
+
| dot_ident_list '.' IDENT
|
28
|
+
{ result << val[2] }
|
29
|
+
|
30
|
+
option : 'option' option_body ';'
|
31
|
+
{ result = Protobuf::Node::OptionNode.new *val[1] }
|
32
|
+
|
33
|
+
option_body : IDENT dot_ident_list '=' constant
|
34
|
+
{ result = [val[1].unshift(val[0]), val[3]] }
|
35
|
+
|
36
|
+
message : 'message' IDENT message_body
|
37
|
+
{ result = Protobuf::Node::MessageNode.new val[1], val[2] }
|
38
|
+
|
39
|
+
extend : 'extend' user_type '{' extend_body_list '}'
|
40
|
+
{ result = Protobuf::Node::ExtendNode.new val[1], val[3] }
|
41
|
+
|
42
|
+
extend_body_list :
|
43
|
+
{ result = [] }
|
44
|
+
| extend_body_list extend_body
|
45
|
+
{ result << val[1] }
|
46
|
+
|
47
|
+
extend_body : field
|
48
|
+
| group
|
49
|
+
| ';'
|
50
|
+
{ }
|
51
|
+
|
52
|
+
enum : 'enum' IDENT '{' enum_body_list '}'
|
53
|
+
{ result = Protobuf::Node::EnumNode.new val[1], val[3] }
|
54
|
+
|
55
|
+
enum_body_list :
|
56
|
+
{ result = [] }
|
57
|
+
| enum_body_list enum_body
|
58
|
+
{ result << val[1] }
|
59
|
+
|
60
|
+
enum_body : option
|
61
|
+
| enum_field
|
62
|
+
| ';'
|
63
|
+
{ }
|
64
|
+
|
65
|
+
enum_field : IDENT '=' integer_literal ';'
|
66
|
+
{ result = Protobuf::Node::EnumFieldNode.new val[0], val[2] }
|
67
|
+
|
68
|
+
service : 'service' IDENT '{' service_body_list '}'
|
69
|
+
{ result = Protobuf::Node::ServiceNode.new val[1], val[3] }
|
70
|
+
|
71
|
+
service_body_list :
|
72
|
+
{ result = [] }
|
73
|
+
| service_body_list service_body
|
74
|
+
{ result << val[1] }
|
75
|
+
|
76
|
+
service_body : option
|
77
|
+
| rpc
|
78
|
+
| ';'
|
79
|
+
{ }
|
80
|
+
|
81
|
+
rpc : 'rpc' IDENT '(' user_type ')' 'returns' '(' user_type ')' ';'
|
82
|
+
{ result = Protobuf::Node::RpcNode.new val[1], val[3], val[7] }
|
83
|
+
|
84
|
+
message_body : '{' message_body_body_list '}'
|
85
|
+
{ result = val[1] }
|
86
|
+
|
87
|
+
message_body_body_list :
|
88
|
+
{ result = [] }
|
89
|
+
| message_body_body_list message_body_body
|
90
|
+
{ result << val[1] }
|
91
|
+
|
92
|
+
message_body_body : field
|
93
|
+
| enum
|
94
|
+
| message
|
95
|
+
| extend
|
96
|
+
| extensions
|
97
|
+
| group
|
98
|
+
| option
|
99
|
+
| ';'
|
100
|
+
{ }
|
101
|
+
|
102
|
+
group : label 'group' CAMEL_IDENT '=' integer_literal message_body
|
103
|
+
{ result = Protobuf::Node::GroupNode.new val[0], val[2], val[4], val[5] }
|
104
|
+
|
105
|
+
field : label type IDENT '=' integer_literal ';'
|
106
|
+
{ result = Protobuf::Node::FieldNode.new val[0], val[1], val[2], val[4] }
|
107
|
+
| label type IDENT '=' integer_literal '[' field_option_list ']' ';'
|
108
|
+
{ result = Protobuf::Node::FieldNode.new val[0], val[1], val[2], val[4], val[6] }
|
109
|
+
|
110
|
+
field_option_list : field_option
|
111
|
+
{ result = val }
|
112
|
+
| field_option_list ',' field_option
|
113
|
+
{ result << val[2] }
|
114
|
+
|
115
|
+
field_option : option_body
|
116
|
+
| 'default' '=' constant
|
117
|
+
{ result = [:default, val[2]] }
|
118
|
+
|
119
|
+
extensions : 'extensions' extension comma_extension_list ';'
|
120
|
+
{ result = Protobuf::Node::ExtensionsNode.new val[2].unshift(val[1]) }
|
121
|
+
|
122
|
+
comma_extension_list :
|
123
|
+
{ result = [] }
|
124
|
+
| ',' extension
|
125
|
+
{ result << val[1] }
|
126
|
+
|
127
|
+
extension : integer_literal
|
128
|
+
{ result = Protobuf::Node::ExtensionRangeNode.new val[0] }
|
129
|
+
| integer_literal 'to' integer_literal
|
130
|
+
{ result = Protobuf::Node::ExtensionRangeNode.new val[0], val[2] }
|
131
|
+
| integer_literal 'to' 'max'
|
132
|
+
{ result = Protobuf::Node::ExtensionRangeNode.new val[0], :max }
|
133
|
+
|
134
|
+
label : 'required'
|
135
|
+
| 'optional'
|
136
|
+
| 'repeated'
|
137
|
+
|
138
|
+
type : 'double' | 'float' | 'int32' | 'int64' | 'uint32' | 'uint64'
|
139
|
+
| 'sint32' | 'sint64' | 'fixed32' | 'fixed64' | 'sfixed32' | 'sfixed64'
|
140
|
+
| 'bool' | 'string' | 'bytes' | user_type
|
141
|
+
|
142
|
+
user_type : IDENT dot_ident_list
|
143
|
+
{ result = val[1].unshift(val[0]) }
|
144
|
+
| '.' IDENT dot_ident_list
|
145
|
+
{ result = val[1].unshift(val[0]) }
|
146
|
+
|
147
|
+
constant : IDENT
|
148
|
+
| integer_literal
|
149
|
+
| FLOAT_LITERAL
|
150
|
+
| STRING_LITERAL
|
151
|
+
| BOOLEAN_LITERAL
|
152
|
+
|
153
|
+
integer_literal : DEC_INTEGER
|
154
|
+
| HEX_INTEGER
|
155
|
+
| OCT_INTEGER
|
156
|
+
end
|
157
|
+
|
158
|
+
---- inner
|
159
|
+
|
160
|
+
def parse(f)
|
161
|
+
@q = []
|
162
|
+
f.each do |line|
|
163
|
+
until line.empty? do
|
164
|
+
case line
|
165
|
+
when /\A\s+/, /\A\/\/.*/
|
166
|
+
;
|
167
|
+
when /\A(required|optional|repeated|import|package|option|message|extend|enum|service|rpc|returns|group|default|extensions|to|max|double|float|int32|int64|uint32|uint64|sint32|sint64|fixed32|fixed64|sfixed32|sfixed64|bool|string|bytes)/
|
168
|
+
@q.push [$&, $&.to_sym]
|
169
|
+
when /\A[1-9]\d*/, /\A0(?![.xX0-9])/
|
170
|
+
@q.push [:DEC_INTEGER, $&.to_i]
|
171
|
+
when /\A0[xX]([A-Fa-f0-9])+/
|
172
|
+
@q.push [:HEX_INTEGER, $&.to_i(0)]
|
173
|
+
when /\A0[0-7]+/
|
174
|
+
@q.push [:OCT_INTEGER, $&.to_i(0)]
|
175
|
+
when /\A\d+(\.\d+)?([Ee][\+-]?\d+)?/
|
176
|
+
@q.push [:FLOAT_LITERAL, $&.to_f]
|
177
|
+
when /\A(true|false)/
|
178
|
+
@q.push [:BOOLEAN_LITERAL, $& == 'true']
|
179
|
+
when /\A"(?:[^"\\]+|\\.)*"/, /\A'(?:[^'\\]+|\\.)*'/
|
180
|
+
@q.push [:STRING_LITERAL, eval($&)]
|
181
|
+
when /\A[a-zA-Z_][\w_]*/
|
182
|
+
@q.push [:IDENT, $&.to_sym]
|
183
|
+
when /\A[A-Z][\w_]*/
|
184
|
+
@q.push [:CAMEL_IDENT, $&.to_sym]
|
185
|
+
when /\A./
|
186
|
+
@q.push [$&, $&]
|
187
|
+
else
|
188
|
+
raise ArgumentError.new(line)
|
189
|
+
end
|
190
|
+
line = $'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
do_parse
|
194
|
+
end
|
195
|
+
|
196
|
+
def next_token
|
197
|
+
@q.shift
|
198
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# See: http://groups.google.com/group/protobuf/browse_thread/thread/1cccfc624cd612da
|
2
|
+
|
3
|
+
proto ::= ( message | extend | enum | import | package | option | ";" )*
|
4
|
+
|
5
|
+
import ::= "import" strLit ";"
|
6
|
+
|
7
|
+
package ::= "package" ident ( "." ident )* ";"
|
8
|
+
|
9
|
+
option ::= "option" optionBody ";"
|
10
|
+
|
11
|
+
optionBody ::= ident ( "." ident )* "=" constant
|
12
|
+
|
13
|
+
message ::= "message" ident messageBody
|
14
|
+
|
15
|
+
extend ::= "extend" userType "{" ( field | group | ";" )* "}"
|
16
|
+
|
17
|
+
enum ::= "enum" ident "{" ( option | enumField | ";" )* "}"
|
18
|
+
|
19
|
+
enumField ::= ident "=" intLit ";"
|
20
|
+
|
21
|
+
service ::= "service" ident "{" ( option | rpc | ";" )* "}"
|
22
|
+
|
23
|
+
rpc ::= "rpc" ident "(" userType ")" "returns" "(" userType ")" ";"
|
24
|
+
|
25
|
+
messageBody ::= "{" ( field | enum | message | extend | extensions | group | option | ":" )* "}"
|
26
|
+
|
27
|
+
group ::= label "group" camelIdent "=" intLit messageBody
|
28
|
+
|
29
|
+
field ::= label type ident "=" intLit ( "[" fieldOption ( "," fieldOption )* "]" )? ";"
|
30
|
+
# tag number must be 2^29-1 or lower, not 0, and not 19000-19999 (reserved)
|
31
|
+
|
32
|
+
fieldOption ::= optionBody | "default" "=" constant
|
33
|
+
|
34
|
+
# extension numbers must not overlap with field or other extension numbers
|
35
|
+
extensions ::= "extensions" extension ( "," extension )* ";"
|
36
|
+
|
37
|
+
extension ::= intLit ( "to" ( intLit | "max" ) )?
|
38
|
+
|
39
|
+
label ::= "required" | "optional" | "repeated"
|
40
|
+
|
41
|
+
type ::= "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
|
42
|
+
| "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
|
43
|
+
| "bool" | "string" | "bytes" | userType
|
44
|
+
|
45
|
+
# leading dot for identifiers means they're fully qualified
|
46
|
+
userType ::= "."? ident ( "." ident )*
|
47
|
+
|
48
|
+
constant ::= ident | intLit | floatLit | strLit | boolLit
|
49
|
+
|
50
|
+
ident ::= /[A-Za-z_][\w_]*/
|
51
|
+
|
52
|
+
# according to parser.cc, group names must start with a capital letter as a
|
53
|
+
# hack for backwards-compatibility
|
54
|
+
camelIdent ::= /[A-Z][\w_]*/
|
55
|
+
|
56
|
+
intLit ::= decInt | hexInt | octInt
|
57
|
+
|
58
|
+
decInt ::= /[1-9]\d*/
|
59
|
+
|
60
|
+
hexInt ::= /0[xX]([A-Fa-f0-9])+/
|
61
|
+
|
62
|
+
octInt ::= /0[0-7]+/
|
63
|
+
|
64
|
+
# allow_f_after_float_ is disabled by default in tokenizer.cc
|
65
|
+
floatLit ::= /\d+(\.\d+)?([Ee][\+-]?\d+)?/
|
66
|
+
|
67
|
+
boolLit ::= "true" | "false"
|
68
|
+
|
69
|
+
# contents must not contain unescaped quote character
|
70
|
+
strLit ::= quote ( hexEscape | octEscape | charEscape | /[^\0\n]/ )* quote
|
71
|
+
|
72
|
+
quote ::= /["']/
|
73
|
+
|
74
|
+
hexEscape ::= /\\[Xx][A-Fa-f0-9]{1,2}/
|
75
|
+
|
76
|
+
octEscape ::= /\\0?[0-7]{1,3}/
|
77
|
+
|
78
|
+
charEscape ::= /\\[abfnrtv\\\?'"]/
|
79
|
+
|