brotorift 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/brotorift +12 -0
- data/lib/ast.rb +169 -0
- data/lib/brotorift.rb +102 -0
- data/lib/case_helper.rb +13 -0
- data/lib/compiler.rb +288 -0
- data/lib/compiler_error.rb +191 -0
- data/lib/generators/elixir_server_generator.ex.erb +162 -0
- data/lib/generators/elixir_server_generator.rb +435 -0
- data/lib/generators/scala_server_generator.rb +137 -0
- data/lib/generators/scala_server_generator.scala.erb +92 -0
- data/lib/generators/unity_client_generator.cs.erb +103 -0
- data/lib/generators/unity_client_generator.rb +188 -0
- data/lib/lexer.rb +42 -0
- data/lib/parser.rb +105 -0
- data/lib/runtime.rb +345 -0
- data/lib/sequence_diagram_generator.rb +47 -0
- metadata +88 -0
@@ -0,0 +1,103 @@
|
|
1
|
+
using Brotorift;
|
2
|
+
using UnityEngine;
|
3
|
+
using System;
|
4
|
+
using System.Collections.Generic;
|
5
|
+
using System.Text;
|
6
|
+
|
7
|
+
namespace <%= node.namespace %>
|
8
|
+
{
|
9
|
+
#region Enums
|
10
|
+
<% for e in runtime.enums.values %>
|
11
|
+
/// <summary>
|
12
|
+
/// <%= e.doc %>
|
13
|
+
/// </summary>
|
14
|
+
public enum <%= e.name %>
|
15
|
+
{<% for v in e.elements.values %>
|
16
|
+
/// <summary>
|
17
|
+
/// <%= v.doc %>
|
18
|
+
/// </summary>
|
19
|
+
<%= v.name %> = <%= v.value %>,
|
20
|
+
<% end %>}
|
21
|
+
<% end %>
|
22
|
+
#endregion
|
23
|
+
|
24
|
+
#region Structs
|
25
|
+
<% for s in runtime.structs.values %>
|
26
|
+
/// <summary>
|
27
|
+
/// <%= s.doc %>
|
28
|
+
/// </summary>
|
29
|
+
public struct <%= s.name %> : IStruct
|
30
|
+
{<% for m in s.members %>
|
31
|
+
/// <summary>
|
32
|
+
/// <%= m.doc %>
|
33
|
+
/// </summary>
|
34
|
+
<%= m.unity_def %>
|
35
|
+
<% end %>
|
36
|
+
public <%= s.name %>( <%= s.members.map { |m| m.unity_param } .join ', ' %> )
|
37
|
+
{<% for m in s.members %>
|
38
|
+
this.<%= m.name %> = <%= m.name %>;<% end %>
|
39
|
+
}
|
40
|
+
|
41
|
+
public void ReadFromPacket( InPacket packet )
|
42
|
+
{<% for m in s.members %>
|
43
|
+
this.<%= m.unity_read %><% end %>
|
44
|
+
}
|
45
|
+
|
46
|
+
public void WriteToPacket( OutPacket packet )
|
47
|
+
{<% for m in s.members %>
|
48
|
+
<%= m.unity_write %><% end %>
|
49
|
+
}
|
50
|
+
}
|
51
|
+
<% end %>
|
52
|
+
#endregion
|
53
|
+
<% for node_direction in runtime.get_node_directions node, :client %>
|
54
|
+
public abstract class <%= node_direction.class_name %> : Client
|
55
|
+
{<% for m in node_direction.in_direction.messages.values %>
|
56
|
+
/// <summary>
|
57
|
+
/// <%= m.doc %>
|
58
|
+
/// </summary><% for p in m.members %>
|
59
|
+
/// <param name="<%= p.name %>"><%= p.doc %></param><% end %>
|
60
|
+
protected abstract <%= m.unity %>;<% end %>
|
61
|
+
|
62
|
+
public <%= node_direction.class_name %>()
|
63
|
+
{
|
64
|
+
}
|
65
|
+
|
66
|
+
private enum InMessage
|
67
|
+
{<% for m in node_direction.in_direction.messages.values %>
|
68
|
+
<%= m.name %> = <%= m.id %>,<% end %>
|
69
|
+
}
|
70
|
+
|
71
|
+
private enum OutMessage
|
72
|
+
{<% for m in node_direction.out_direction.messages.values %>
|
73
|
+
<%= m.name %> = <%= m.id %>,<% end %>
|
74
|
+
}
|
75
|
+
<% for m in node_direction.out_direction.messages.values %>
|
76
|
+
/// <summary>
|
77
|
+
/// <%= m.doc %>
|
78
|
+
/// </summary><% for p in m.members %>
|
79
|
+
/// <param name="<%= p.name %>"><%= p.doc %></param><% end %>
|
80
|
+
public <%= m.unity %>
|
81
|
+
{
|
82
|
+
var packet = new OutPacket( (int)OutMessage.<%= m.name %> );
|
83
|
+
<% for p in m.members %><%= p.unity_write %>
|
84
|
+
<% end %>this.SendPacket( packet );
|
85
|
+
}<% end %>
|
86
|
+
|
87
|
+
protected override void ProcessPacket( InPacket packet )
|
88
|
+
{
|
89
|
+
switch( (InMessage)packet.Header )
|
90
|
+
{<% for m in node_direction.in_direction.messages.values %>
|
91
|
+
case InMessage.<%= m.name %>:
|
92
|
+
{<% for p in m.members %>
|
93
|
+
var <%= p.unity_read %><% end %>
|
94
|
+
this.<%= m.name %>( <%= m.unity_param %> );
|
95
|
+
}
|
96
|
+
break;<% end %>
|
97
|
+
default:
|
98
|
+
break;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
<% end %>
|
103
|
+
}
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require_relative '../case_helper'
|
3
|
+
|
4
|
+
|
5
|
+
class BuiltinTypeDef
|
6
|
+
def unity
|
7
|
+
case @name
|
8
|
+
when 'UShort'
|
9
|
+
return 'ushort'
|
10
|
+
when 'UInt'
|
11
|
+
return 'uint'
|
12
|
+
when 'ULong'
|
13
|
+
return 'ulong'
|
14
|
+
when 'DateTime'
|
15
|
+
return 'DateTime'
|
16
|
+
when 'ByteBuffer'
|
17
|
+
return 'byte[]'
|
18
|
+
when 'List'
|
19
|
+
return 'List'
|
20
|
+
when 'Set'
|
21
|
+
return 'HashSet'
|
22
|
+
when 'Map'
|
23
|
+
return 'Dictionary'
|
24
|
+
when 'Vector2', 'Vector3', 'Color'
|
25
|
+
return @name
|
26
|
+
when 'Matrix4'
|
27
|
+
return 'Matrix4x4'
|
28
|
+
else
|
29
|
+
return @name.decapitalize
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
class EnumTypeDef
|
36
|
+
def unity
|
37
|
+
@name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class StructTypeDef
|
43
|
+
def unity
|
44
|
+
@name
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
class TypeInstanceDef
|
50
|
+
@@lambda_index = 0
|
51
|
+
|
52
|
+
def unity
|
53
|
+
if @params.empty?
|
54
|
+
return @type.unity
|
55
|
+
else
|
56
|
+
return "#{@type.unity}#{unity_type_param}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def unity_read is_top_scope
|
61
|
+
str = ''
|
62
|
+
if @type.is_a? StructTypeDef
|
63
|
+
str = "packet.ReadStruct( new #{@type.name}() )"
|
64
|
+
elsif @type.is_a? EnumTypeDef
|
65
|
+
str = "(#{@type.name})packet.ReadInt()"
|
66
|
+
else
|
67
|
+
str = "packet.Read#{unity_read_write}"
|
68
|
+
if @params.empty?
|
69
|
+
str += '()'
|
70
|
+
else
|
71
|
+
param_str = @params.map { |p| p.unity_read false } .join ', '
|
72
|
+
str += '( ' + param_str + ' )'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if is_top_scope == false
|
77
|
+
str = '() => ' + str
|
78
|
+
end
|
79
|
+
|
80
|
+
str
|
81
|
+
end
|
82
|
+
|
83
|
+
def unity_write member_name, is_top_scope
|
84
|
+
str = ''
|
85
|
+
if @type.is_a? StructTypeDef
|
86
|
+
str = "packet.WriteStruct( #{member_name} )"
|
87
|
+
elsif @type.is_a? EnumTypeDef
|
88
|
+
str = "packet.WriteInt( (int)#{member_name} )"
|
89
|
+
else
|
90
|
+
str = "packet.Write#{unity_read_write}"
|
91
|
+
if @params.empty?
|
92
|
+
str += "( #{member_name} )"
|
93
|
+
else
|
94
|
+
params_str = @params.map do |p|
|
95
|
+
@@lambda_index += 1
|
96
|
+
arg_name = '_' + @@lambda_index.to_s
|
97
|
+
p.unity_write arg_name, false
|
98
|
+
end
|
99
|
+
param_str = params_str.join ', '
|
100
|
+
str += "( #{member_name}, #{param_str} )"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
if is_top_scope == false
|
105
|
+
str = "( #{member_name} ) => " + str
|
106
|
+
end
|
107
|
+
|
108
|
+
str
|
109
|
+
end
|
110
|
+
|
111
|
+
def unity_read_write
|
112
|
+
if @params.empty?
|
113
|
+
return @type.name
|
114
|
+
else
|
115
|
+
return "#{@type.name}#{unity_type_param}"
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def unity_type_param
|
120
|
+
return '' if @params.empty?
|
121
|
+
param_str = @params.map { |p| p.unity } .join ', '
|
122
|
+
'<' + param_str + '>'
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
|
127
|
+
class MemberDef
|
128
|
+
def unity_def
|
129
|
+
"public #{unity_param};"
|
130
|
+
end
|
131
|
+
|
132
|
+
def unity_param
|
133
|
+
"#{@type.unity} #{@name}"
|
134
|
+
end
|
135
|
+
|
136
|
+
def unity_read
|
137
|
+
"#{@name} = #{@type.unity_read true};"
|
138
|
+
end
|
139
|
+
|
140
|
+
def unity_write
|
141
|
+
"#{@type.unity_write @name, true};"
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
class DirectionDef
|
147
|
+
def unity_name
|
148
|
+
"#{@client}#{@server}Connector"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
class MessageDef
|
154
|
+
def unity
|
155
|
+
param_str = members.map { |m| m.unity_param } .join ', '
|
156
|
+
"void #{@name}( #{param_str} )"
|
157
|
+
end
|
158
|
+
|
159
|
+
def unity_param
|
160
|
+
members.map { |m| m.name } .join ', '
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
|
165
|
+
class NodeDirection
|
166
|
+
def class_name
|
167
|
+
"#{@remote.name}ConnectorBase"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
172
|
+
class UnityClientGenerator < Generator
|
173
|
+
def initialize
|
174
|
+
super 'unity', :client
|
175
|
+
end
|
176
|
+
|
177
|
+
def generate node, runtime
|
178
|
+
folder = File.expand_path File.dirname __FILE__
|
179
|
+
erb_file = folder + '/unity_client_generator.cs.erb'
|
180
|
+
template = File.read erb_file
|
181
|
+
erb = ERB.new template
|
182
|
+
content = erb.result binding
|
183
|
+
File.write "#{node.name}.cs", content
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
|
188
|
+
Generator.add UnityClientGenerator.new
|
data/lib/lexer.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rltk'
|
2
|
+
|
3
|
+
|
4
|
+
class Lexer < RLTK::Lexer
|
5
|
+
# Whitespace
|
6
|
+
rule(/\s/)
|
7
|
+
|
8
|
+
# Keyword
|
9
|
+
rule(/namespace/) { :NAMESPACE }
|
10
|
+
rule(/include/) { :INCLUDE }
|
11
|
+
rule(/node/) { :NODE }
|
12
|
+
rule(/as/) { :AS }
|
13
|
+
rule(/struct/) { :STRUCT }
|
14
|
+
rule(/enum/) { :ENUM }
|
15
|
+
rule(/direction/) { :DIRECTION }
|
16
|
+
rule(/message/) { :MESSAGE }
|
17
|
+
rule(/sequence/) { :SEQUENCE }
|
18
|
+
rule(/end/) { :END }
|
19
|
+
|
20
|
+
# Operator
|
21
|
+
rule(/\./) { :DOT }
|
22
|
+
rule(/\=/) { :ASSIGN }
|
23
|
+
rule(/<-/) { :LARROW }
|
24
|
+
rule(/->/) { :RARROW }
|
25
|
+
rule(/:/) { :COLON }
|
26
|
+
rule(/</) { :LANGLE }
|
27
|
+
rule(/>/) { :RANGLE }
|
28
|
+
rule(/,/) { :COMMA }
|
29
|
+
|
30
|
+
# Number
|
31
|
+
rule(/(\+|-)?\d+/) { |t| [:NUMBER, t.to_i] }
|
32
|
+
rule(/0[xX][0-9a-fA-F]+/) { |t| [:NUMBER, t.hex] }
|
33
|
+
|
34
|
+
# String
|
35
|
+
rule(/'.+'/) { |t| [:STRING, t[1..-2]] }
|
36
|
+
|
37
|
+
# Identifier
|
38
|
+
rule(/[A-Za-z_][A-Za-z0-9_]*/) { |t| [:IDENT, t] }
|
39
|
+
|
40
|
+
# Document
|
41
|
+
rule(/#.*/) { |t| [:DOCUMENT, t[1..-1].strip] }
|
42
|
+
end
|
data/lib/parser.rb
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'rltk'
|
2
|
+
require_relative 'ast'
|
3
|
+
|
4
|
+
|
5
|
+
module RLTK
|
6
|
+
class Parser
|
7
|
+
class Environment
|
8
|
+
def position
|
9
|
+
Position.new @positions.first, @positions.last
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
class Parser < RLTK::Parser
|
17
|
+
@@enum_value = 0
|
18
|
+
|
19
|
+
list(:decl_list, :decl)
|
20
|
+
|
21
|
+
production(:decl) do
|
22
|
+
clause('include_decl') { |d| d }
|
23
|
+
clause('node_decl') { |d| d }
|
24
|
+
clause('struct_decl') { |d| d }
|
25
|
+
clause('enum_decl') { |d| d }
|
26
|
+
clause('direction_decl') { |d| d }
|
27
|
+
clause('sequence_decl') { |d| d }
|
28
|
+
end
|
29
|
+
|
30
|
+
production(:include_decl) do
|
31
|
+
clause('INCLUDE STRING') { |_, filename| IncludeDecl.new self.position, filename }
|
32
|
+
end
|
33
|
+
|
34
|
+
production(:node_decl) do
|
35
|
+
clause('NODE IDENT IDENT doc') { |_, language, name, doc| NodeDecl.new self.position, name, language, name, '', doc }
|
36
|
+
clause('NODE IDENT IDENT AS IDENT doc') { |_, language, name, _, nickname, doc| NodeDecl.new self.position, name, language, nickname, '', doc }
|
37
|
+
clause('NODE IDENT IDENT NAMESPACE namespace doc') { |_, language, name, _, namespace, doc| NodeDecl.new self.position, name, language, name, namespace, doc }
|
38
|
+
clause('NODE IDENT IDENT AS IDENT NAMESPACE namespace doc') { |_, language, name, _, nickname, _, namespace, doc| NodeDecl.new self.position, name, language, nickname, namespace, doc }
|
39
|
+
end
|
40
|
+
|
41
|
+
production(:namespace) do
|
42
|
+
clause('IDENT') { |name| name }
|
43
|
+
clause('IDENT DOT namespace') { |name, _, rest| name + '.' + rest }
|
44
|
+
end
|
45
|
+
|
46
|
+
production(:doc) do
|
47
|
+
clause('') { || '' }
|
48
|
+
clause('DOCUMENT') { |doc| doc }
|
49
|
+
end
|
50
|
+
|
51
|
+
production(:struct_decl) do
|
52
|
+
clause('STRUCT IDENT doc member_list END') { |_, name, doc, members, _| StructDecl.new self.position, name, doc, members }
|
53
|
+
end
|
54
|
+
|
55
|
+
list(:member_list, :member)
|
56
|
+
|
57
|
+
production(:member) do
|
58
|
+
clause('type IDENT doc') { |type, name, doc| MemberDecl.new self.position, type, name, doc }
|
59
|
+
end
|
60
|
+
|
61
|
+
production(:type) do
|
62
|
+
clause('IDENT') { |name| TypeDecl.new self.position, name, [] }
|
63
|
+
clause('IDENT LANGLE type_param_list RANGLE') { |name, _, params, _| TypeDecl.new self.position, name, params }
|
64
|
+
end
|
65
|
+
|
66
|
+
nonempty_list(:type_param_list, :type, :COMMA)
|
67
|
+
|
68
|
+
production(:enum_decl) do
|
69
|
+
clause('ENUM IDENT doc element_list END') { |_, name, doc, elements, _| @@enum_value = 0; EnumDecl.new self.position, name, doc, elements }
|
70
|
+
end
|
71
|
+
|
72
|
+
list(:element_list, :element)
|
73
|
+
|
74
|
+
production(:element) do
|
75
|
+
clause('IDENT doc') { |name, doc| @@enum_value += 1; EnumElementDecl.new self.position, name, @@enum_value - 1, doc }
|
76
|
+
clause('IDENT ASSIGN NUMBER doc') { |name, _, value, doc| @@enum_value = value + 1; EnumElementDecl.new self.position, name, @@enum_value - 1, doc }
|
77
|
+
end
|
78
|
+
|
79
|
+
production(:direction_decl) do
|
80
|
+
clause('DIRECTION IDENT arrow IDENT doc message_list END') { |_, client, direction, server, doc, messages, _| DirectionDecl.new self.position, client, direction, server, doc, messages }
|
81
|
+
end
|
82
|
+
|
83
|
+
production(:arrow) do
|
84
|
+
clause('LARROW') { |_| :left }
|
85
|
+
clause('RARROW') { |_| :right }
|
86
|
+
end
|
87
|
+
|
88
|
+
list(:message_list, :message)
|
89
|
+
|
90
|
+
production(:message) do
|
91
|
+
clause('MESSAGE IDENT doc member_list END') { |_, name, doc, members, _| MessageDecl.new self.position, name, doc, members }
|
92
|
+
end
|
93
|
+
|
94
|
+
production(:sequence_decl) do
|
95
|
+
clause('SEQUENCE IDENT doc step_list END') { |_, name, doc, steps, _| SequenceDecl.new self.position, name, doc, steps }
|
96
|
+
end
|
97
|
+
|
98
|
+
list(:step_list, :step)
|
99
|
+
|
100
|
+
production(:step) do
|
101
|
+
clause('IDENT arrow IDENT COLON IDENT doc') { |client, direction, server, _, message, doc| StepDecl.new self.position, client, direction, server, message, doc }
|
102
|
+
end
|
103
|
+
|
104
|
+
finalize
|
105
|
+
end
|