tp_plus 0.0.73 → 0.0.74
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.
- checksums.yaml +4 -4
- data/README.md +74 -65
- data/Rakefile +35 -21
- data/bin/tpp +73 -73
- data/lib/tp_plus/interpreter.rb +152 -129
- data/lib/tp_plus/namespace.rb +66 -66
- data/lib/tp_plus/nodes/abort_node.rb +9 -9
- data/lib/tp_plus/nodes/address_node.rb +22 -0
- data/lib/tp_plus/nodes/argument_node.rb +20 -19
- data/lib/tp_plus/nodes/assignment_node.rb +45 -45
- data/lib/tp_plus/nodes/call_node.rb +34 -34
- data/lib/tp_plus/nodes/case_condition_node.rb +26 -26
- data/lib/tp_plus/nodes/case_node.rb +33 -33
- data/lib/tp_plus/nodes/comment_node.rb +22 -22
- data/lib/tp_plus/nodes/conditional_node.rb +60 -54
- data/lib/tp_plus/nodes/definition_node.rb +22 -22
- data/lib/tp_plus/nodes/digit_node.rb +22 -21
- data/lib/tp_plus/nodes/empty_stmt_node.rb +9 -0
- data/lib/tp_plus/nodes/eval_node.rb +13 -13
- data/lib/tp_plus/nodes/expression_node.rb +68 -65
- data/lib/tp_plus/nodes/for_node.rb +20 -20
- data/lib/tp_plus/nodes/header_node.rb +27 -27
- data/lib/tp_plus/nodes/indirect_node.rb +51 -49
- data/lib/tp_plus/nodes/inline_conditional_node.rb +40 -40
- data/lib/tp_plus/nodes/io_method_node.rb +55 -55
- data/lib/tp_plus/nodes/io_node.rb +31 -30
- data/lib/tp_plus/nodes/jump_node.rb +23 -23
- data/lib/tp_plus/nodes/label_definition_node.rb +21 -21
- data/lib/tp_plus/nodes/motion_node.rb +62 -62
- data/lib/tp_plus/nodes/namespace_node.rb +16 -16
- data/lib/tp_plus/nodes/namespaced_var_node.rb +38 -38
- data/lib/tp_plus/nodes/numreg_node.rb +26 -25
- data/lib/tp_plus/nodes/offset_node.rb +27 -27
- data/lib/tp_plus/nodes/operator_node.rb +78 -72
- data/lib/tp_plus/nodes/paren_expression_node.rb +17 -0
- data/lib/tp_plus/nodes/pause_node.rb +9 -9
- data/lib/tp_plus/nodes/position_data_node.rb +64 -50
- data/lib/tp_plus/nodes/position_node.rb +26 -25
- data/lib/tp_plus/nodes/posreg_node.rb +64 -48
- data/lib/tp_plus/nodes/raise_node.rb +13 -13
- data/lib/tp_plus/nodes/real_node.rb +27 -27
- data/lib/tp_plus/nodes/set_skip_node.rb +14 -0
- data/lib/tp_plus/nodes/skip_node.rb +22 -22
- data/lib/tp_plus/nodes/speed_node.rb +29 -29
- data/lib/tp_plus/nodes/string_node.rb +13 -13
- data/lib/tp_plus/nodes/string_register_node.rb +26 -25
- data/lib/tp_plus/nodes/termination_node.rb +23 -18
- data/lib/tp_plus/nodes/terminator_node.rb +16 -16
- data/lib/tp_plus/nodes/time_node.rb +24 -24
- data/lib/tp_plus/nodes/timer_method_node.rb +37 -37
- data/lib/tp_plus/nodes/timer_node.rb +16 -21
- data/lib/tp_plus/nodes/units_node.rb +20 -20
- data/lib/tp_plus/nodes/use_node.rb +21 -21
- data/lib/tp_plus/nodes/user_alarm_node.rb +16 -15
- data/lib/tp_plus/nodes/var_method_node.rb +23 -23
- data/lib/tp_plus/nodes/var_node.rb +39 -39
- data/lib/tp_plus/nodes/vision_register_node.rb +22 -21
- data/lib/tp_plus/nodes/wait_for_node.rb +54 -54
- data/lib/tp_plus/nodes/wait_until_node.rb +65 -65
- data/lib/tp_plus/nodes/while_node.rb +42 -36
- data/lib/tp_plus/parser.rb +1682 -1592
- data/lib/tp_plus/scanner.rb +283 -383
- data/lib/tp_plus/token.rb +97 -0
- data/lib/tp_plus/version.rb +3 -3
- data/lib/tp_plus.rb +66 -62
- data/test/test_helper.rb +5 -5
- data/test/tp_plus/test_interpreter.rb +1309 -1168
- data/test/tp_plus/test_parser.rb +496 -489
- data/test/tp_plus/test_scanner.rb +577 -522
- data/tp_plus.gemspec +31 -28
- metadata +61 -14
- data/lib/tp_plus/nodes/set_node.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 145a37ef7d63642c1a654a9e804c0dc8ce21f1b0
|
4
|
+
data.tar.gz: 3229bc8c6be259a54326b1d83ff5cc295a443b6c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33068559319eff301cd865cef17e9db384ab30b50b7f59fa44659b4ba4ad87289a195ac500ce9105a7355a5561e9f483f6c9b22946c59e89458d5b85c395df9b
|
7
|
+
data.tar.gz: 0c4db71fa16f12d8fa0d244c0a1b59a25a492f9911049a3697c8fa33a5b46ee6387848928dcf0daaa8ce912b461d589e353c5214d4255f0ca2eec29f3a32a2cf
|
data/README.md
CHANGED
@@ -1,65 +1,74 @@
|
|
1
|
-
TP+
|
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
|
-
foo = 1
|
33
|
-
|
34
|
-
@loop
|
35
|
-
foo += 1
|
36
|
-
|
37
|
-
jump_to @
|
38
|
-
|
39
|
-
turn_on bar if foo == 5
|
40
|
-
toggle baz
|
41
|
-
|
42
|
-
linear_move.to(home).at(2000mm/s).term(0)
|
43
|
-
|
44
|
-
|
45
|
-
example_1.ls
|
46
|
-
|
47
|
-
/PROG example_1
|
48
|
-
/MN
|
49
|
-
1: R[1:foo] = 1 ;
|
50
|
-
1: ;
|
51
|
-
1: LBL[
|
52
|
-
1: R[1:foo]=R[1:foo]+1 ;
|
53
|
-
1: IF R[1:foo]<10,JMP LBL[
|
54
|
-
1: ;
|
55
|
-
1: IF (R[1:foo]=5),DO[1:bar]=(ON) ;
|
56
|
-
1: DO[2:baz]=(!DO[2:baz]) ;
|
57
|
-
1: ;
|
58
|
-
1: L PR[1:home] 2000mm/sec CNT0 ;
|
59
|
-
/END
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
1
|
+
TP+
|
2
|
+
===
|
3
|
+
|
4
|
+
[](https://travis-ci.org/onerobotics/tp_plus)
|
5
|
+
|
6
|
+
TP+ is a higher-level language abstraction that translates into FANUC
|
7
|
+
TP. It features many useful utilities that makes creating TP programs
|
8
|
+
easier:
|
9
|
+
|
10
|
+
* Identifiers for registers, position registers, IO, etc.
|
11
|
+
* Re-usable methods
|
12
|
+
* If-else blocks
|
13
|
+
* Readable motion statements
|
14
|
+
* Automatic label numbering
|
15
|
+
|
16
|
+
Of course adding another layer of abstraction takes you a step further
|
17
|
+
away from the code the robot is running. However, it's hoped that the
|
18
|
+
increased productivity and rigid syntax requirements will actually
|
19
|
+
improve your TP code.
|
20
|
+
|
21
|
+
Examples
|
22
|
+
--------
|
23
|
+
|
24
|
+
example_1.tpp
|
25
|
+
|
26
|
+
foo := R[1]
|
27
|
+
bar := DO[1]
|
28
|
+
baz := DO[2]
|
29
|
+
|
30
|
+
home := PR[1]
|
31
|
+
|
32
|
+
foo = 1
|
33
|
+
|
34
|
+
@loop
|
35
|
+
foo += 1
|
36
|
+
|
37
|
+
jump_to @loop if foo < 10
|
38
|
+
|
39
|
+
turn_on bar if foo == 5
|
40
|
+
toggle baz
|
41
|
+
|
42
|
+
linear_move.to(home).at(2000mm/s).term(0)
|
43
|
+
|
44
|
+
|
45
|
+
example_1.ls
|
46
|
+
|
47
|
+
/PROG example_1
|
48
|
+
/MN
|
49
|
+
1: R[1:foo] = 1 ;
|
50
|
+
1: ;
|
51
|
+
1: LBL[100:loop] ;
|
52
|
+
1: R[1:foo]=R[1:foo]+1 ;
|
53
|
+
1: IF R[1:foo]<10,JMP LBL[100] ;
|
54
|
+
1: ;
|
55
|
+
1: IF (R[1:foo]=5),DO[1:bar]=(ON) ;
|
56
|
+
1: DO[2:baz]=(!DO[2:baz]) ;
|
57
|
+
1: ;
|
58
|
+
1: L PR[1:home] 2000mm/sec CNT0 ;
|
59
|
+
/END
|
60
|
+
|
61
|
+
For a more extensive example and test environment, visit http://tp-plus.herokuapp.com/.
|
62
|
+
|
63
|
+
Usage
|
64
|
+
-----
|
65
|
+
|
66
|
+
1. `gem install tp_plus`
|
67
|
+
2. `tpp filename.tpp > filename.ls`
|
68
|
+
|
69
|
+
See `tpp --help` for options.
|
70
|
+
|
71
|
+
License
|
72
|
+
-------
|
73
|
+
|
74
|
+
TP+ is released under the [MIT License](http://www.opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,21 +1,35 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
task :
|
7
|
-
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
task compile: ["compile:parser"
|
12
|
-
|
13
|
-
require 'rake/testtask'
|
14
|
-
|
15
|
-
Rake::TestTask.new do |t|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
file "lib/tp_plus/parser.rb" => ["generators/parser.y"] do |t|
|
2
|
+
sh "racc -l -t -v -o lib/tp_plus/parser.rb generators/parser.y"
|
3
|
+
end
|
4
|
+
|
5
|
+
namespace :compile do
|
6
|
+
task :parser do
|
7
|
+
Rake::Task["lib/tp_plus/parser.rb"].invoke
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
task compile: ["compile:parser"]
|
12
|
+
|
13
|
+
require 'rake/testtask'
|
14
|
+
|
15
|
+
Rake::TestTask.new do |t|
|
16
|
+
# build the parser if necessary
|
17
|
+
Rake::Task["lib/tp_plus/parser.rb"].invoke
|
18
|
+
|
19
|
+
t.libs << "test"
|
20
|
+
t.test_files = FileList['test/**/test_*.rb']
|
21
|
+
t.verbose = true
|
22
|
+
end
|
23
|
+
|
24
|
+
task default: :test
|
25
|
+
|
26
|
+
|
27
|
+
desc "Run the TP+ benchmark"
|
28
|
+
task :benchmark do
|
29
|
+
ruby "./performance/benchmark.rb"
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Run the TP+ profiler"
|
33
|
+
task :profile do
|
34
|
+
ruby "./performance/profile.rb"
|
35
|
+
end
|
data/bin/tpp
CHANGED
@@ -1,73 +1,73 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'tp_plus'
|
3
|
-
require 'optparse'
|
4
|
-
|
5
|
-
options = {}
|
6
|
-
OptionParser.new do |opts|
|
7
|
-
opts.banner = "Usage: tpp [options] filename"
|
8
|
-
|
9
|
-
opts.on("-e", "--environment env_file.tpp", "Require an environment file before parsing files") do |e|
|
10
|
-
options[:environment] = e
|
11
|
-
end
|
12
|
-
|
13
|
-
opts.on_tail("-h", "--help", "Show this message") do
|
14
|
-
puts opts
|
15
|
-
exit
|
16
|
-
end
|
17
|
-
end.parse!
|
18
|
-
|
19
|
-
def contents(filename)
|
20
|
-
if !File.exist?(filename)
|
21
|
-
puts "File (#{filename}) does not exist"
|
22
|
-
exit
|
23
|
-
end
|
24
|
-
f = File.open(filename,'rb')
|
25
|
-
src = f.read
|
26
|
-
f.close
|
27
|
-
return src
|
28
|
-
end
|
29
|
-
|
30
|
-
scanner = TPPlus::Scanner.new
|
31
|
-
parser = TPPlus::Parser.new(scanner)
|
32
|
-
interpreter = parser.interpreter
|
33
|
-
if options[:environment]
|
34
|
-
interpreter.load_environment(contents(options[:environment]))
|
35
|
-
end
|
36
|
-
|
37
|
-
if ARGV.length != 1
|
38
|
-
puts "Must provide filename argument. See tpp --help for details"
|
39
|
-
exit
|
40
|
-
end
|
41
|
-
|
42
|
-
src = contents(ARGV[0])
|
43
|
-
|
44
|
-
scanner.scan_setup(src)
|
45
|
-
parser.parse
|
46
|
-
|
47
|
-
lines = interpreter.eval
|
48
|
-
|
49
|
-
tpp_filename = File.basename(ARGV[0],".*")
|
50
|
-
output = %(/PROG #{tpp_filename.upcase}
|
51
|
-
/ATTR
|
52
|
-
COMMENT = "#{interpreter.header_data[:comment] || tpp_filename.upcase}";
|
53
|
-
TCD: STACK_SIZE = 0,
|
54
|
-
TASK_PRIORITY = 50,
|
55
|
-
TIME_SLICE = 0,
|
56
|
-
BUSY_LAMP_OFF = 0,
|
57
|
-
ABORT_REQUEST = 0,
|
58
|
-
PAUSE_REQUEST = #{interpreter.header_data[:ignore_pause] ? "7" : "0"};
|
59
|
-
DEFAULT_GROUP = #{interpreter.header_data[:group_mask] || "1,*,*,*,*"};
|
60
|
-
/MN\n)
|
61
|
-
|
62
|
-
lines.each_line do |line|
|
63
|
-
output += " : " + line
|
64
|
-
end
|
65
|
-
|
66
|
-
if interpreter.pos_section != ""
|
67
|
-
output += "/POS\n"
|
68
|
-
output += interpreter.pos_section
|
69
|
-
end
|
70
|
-
|
71
|
-
output += %(/END\n)
|
72
|
-
|
73
|
-
print output
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'tp_plus'
|
3
|
+
require 'optparse'
|
4
|
+
|
5
|
+
options = {}
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: tpp [options] filename"
|
8
|
+
|
9
|
+
opts.on("-e", "--environment env_file.tpp", "Require an environment file before parsing files") do |e|
|
10
|
+
options[:environment] = e
|
11
|
+
end
|
12
|
+
|
13
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
14
|
+
puts opts
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
end.parse!
|
18
|
+
|
19
|
+
def contents(filename)
|
20
|
+
if !File.exist?(filename)
|
21
|
+
puts "File (#{filename}) does not exist"
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
f = File.open(filename,'rb')
|
25
|
+
src = f.read
|
26
|
+
f.close
|
27
|
+
return src
|
28
|
+
end
|
29
|
+
|
30
|
+
scanner = TPPlus::Scanner.new
|
31
|
+
parser = TPPlus::Parser.new(scanner)
|
32
|
+
interpreter = parser.interpreter
|
33
|
+
if options[:environment]
|
34
|
+
interpreter.load_environment(contents(options[:environment]))
|
35
|
+
end
|
36
|
+
|
37
|
+
if ARGV.length != 1
|
38
|
+
puts "Must provide filename argument. See tpp --help for details"
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
src = contents(ARGV[0])
|
43
|
+
|
44
|
+
scanner.scan_setup(src)
|
45
|
+
parser.parse
|
46
|
+
|
47
|
+
lines = interpreter.eval
|
48
|
+
|
49
|
+
tpp_filename = File.basename(ARGV[0],".*")
|
50
|
+
output = %(/PROG #{tpp_filename.upcase}
|
51
|
+
/ATTR
|
52
|
+
COMMENT = "#{interpreter.header_data[:comment] || tpp_filename.upcase}";
|
53
|
+
TCD: STACK_SIZE = 0,
|
54
|
+
TASK_PRIORITY = 50,
|
55
|
+
TIME_SLICE = 0,
|
56
|
+
BUSY_LAMP_OFF = 0,
|
57
|
+
ABORT_REQUEST = 0,
|
58
|
+
PAUSE_REQUEST = #{interpreter.header_data[:ignore_pause] ? "7" : "0"};
|
59
|
+
DEFAULT_GROUP = #{interpreter.header_data[:group_mask] || "1,*,*,*,*"};
|
60
|
+
/MN\n)
|
61
|
+
|
62
|
+
lines.each_line do |line|
|
63
|
+
output += " : " + line
|
64
|
+
end
|
65
|
+
|
66
|
+
if interpreter.pos_section != ""
|
67
|
+
output += "/POS\n"
|
68
|
+
output += interpreter.pos_section
|
69
|
+
end
|
70
|
+
|
71
|
+
output += %(/END\n)
|
72
|
+
|
73
|
+
print output
|
data/lib/tp_plus/interpreter.rb
CHANGED
@@ -1,129 +1,152 @@
|
|
1
|
-
require 'tp_plus/parser'
|
2
|
-
|
3
|
-
module TPPlus
|
4
|
-
class Interpreter
|
5
|
-
attr_accessor :line_count, :nodes, :position_data, :header_data
|
6
|
-
attr_reader :labels, :variables, :constants, :namespaces, :source_line_count
|
7
|
-
def initialize
|
8
|
-
@line_count = 0
|
9
|
-
@nodes = []
|
10
|
-
@labels = {}
|
11
|
-
@namespaces = {}
|
12
|
-
@variables = {}
|
13
|
-
@constants = {}
|
14
|
-
@position_data = {}
|
15
|
-
@header_data = {}
|
16
|
-
@current_label = 99
|
17
|
-
end
|
18
|
-
|
19
|
-
def load_environment(string)
|
20
|
-
scanner = TPPlus::Scanner.new
|
21
|
-
parser = TPPlus::Parser.new(scanner, self)
|
22
|
-
scanner.scan_setup(string)
|
23
|
-
parser.parse
|
24
|
-
eval
|
25
|
-
rescue RuntimeError => e
|
26
|
-
raise "Runtime error in environment on line #{@source_line_count}:\n#{e}"
|
27
|
-
end
|
28
|
-
|
29
|
-
def next_label
|
30
|
-
@current_label += 1
|
31
|
-
end
|
32
|
-
|
33
|
-
def add_namespace(name, block)
|
34
|
-
if @namespaces[name.to_sym].nil?
|
35
|
-
@namespaces[name.to_sym] = TPPlus::Namespace.new(name, block)
|
36
|
-
else
|
37
|
-
@namespaces[name.to_sym].reopen!(block)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def add_label(identifier)
|
42
|
-
raise "Label @#{identifier} already defined" if @labels[identifier.to_sym]
|
43
|
-
@labels[identifier.to_sym] = next_label
|
44
|
-
end
|
45
|
-
|
46
|
-
def add_var(identifier, node)
|
47
|
-
raise "Variable #{identifier} already defined" if @variables[identifier.to_sym]
|
48
|
-
|
49
|
-
@variables[identifier.to_sym] = node
|
50
|
-
node.comment = identifier
|
51
|
-
end
|
52
|
-
|
53
|
-
def add_constant(identifier, node)
|
54
|
-
raise "Constant #{identifier} already defined" if @constants[identifier.to_sym]
|
55
|
-
|
56
|
-
@constants[identifier.to_sym] = node
|
57
|
-
end
|
58
|
-
|
59
|
-
def get_namespace(identifier)
|
60
|
-
if ns = @namespaces[identifier.to_sym]
|
61
|
-
return ns
|
62
|
-
end
|
63
|
-
|
64
|
-
false
|
65
|
-
end
|
66
|
-
|
67
|
-
def get_var(identifier)
|
68
|
-
raise "Variable (#{identifier}) not defined" if @variables[identifier.to_sym].nil?
|
69
|
-
|
70
|
-
@variables[identifier.to_sym]
|
71
|
-
end
|
72
|
-
|
73
|
-
def get_constant(identifier)
|
74
|
-
raise "Constant (#{identifier}) not defined" if @constants[identifier.to_sym].nil?
|
75
|
-
|
76
|
-
@constants[identifier.to_sym]
|
77
|
-
end
|
78
|
-
|
79
|
-
def define_labels
|
80
|
-
@nodes.select {|n| n.is_a? Nodes::LabelDefinitionNode}.each do |n|
|
81
|
-
add_label(n.identifier)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def pos_section
|
86
|
-
return "" if @position_data.empty?
|
87
|
-
return "" if @position_data[:positions].empty?
|
88
|
-
|
89
|
-
@position_data[:positions].inject("") do |s,p|
|
90
|
-
s << %(P[#{p[:id]}:"#{p[:comment]}"]{
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
s
|
116
|
-
end
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
1
|
+
require 'tp_plus/parser'
|
2
|
+
|
3
|
+
module TPPlus
|
4
|
+
class Interpreter
|
5
|
+
attr_accessor :line_count, :nodes, :position_data, :header_data
|
6
|
+
attr_reader :labels, :variables, :constants, :namespaces, :source_line_count
|
7
|
+
def initialize
|
8
|
+
@line_count = 0
|
9
|
+
@nodes = []
|
10
|
+
@labels = {}
|
11
|
+
@namespaces = {}
|
12
|
+
@variables = {}
|
13
|
+
@constants = {}
|
14
|
+
@position_data = {}
|
15
|
+
@header_data = {}
|
16
|
+
@current_label = 99
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_environment(string)
|
20
|
+
scanner = TPPlus::Scanner.new
|
21
|
+
parser = TPPlus::Parser.new(scanner, self)
|
22
|
+
scanner.scan_setup(string)
|
23
|
+
parser.parse
|
24
|
+
eval
|
25
|
+
rescue RuntimeError => e
|
26
|
+
raise "Runtime error in environment on line #{@source_line_count}:\n#{e}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def next_label
|
30
|
+
@current_label += 1
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_namespace(name, block)
|
34
|
+
if @namespaces[name.to_sym].nil?
|
35
|
+
@namespaces[name.to_sym] = TPPlus::Namespace.new(name, block)
|
36
|
+
else
|
37
|
+
@namespaces[name.to_sym].reopen!(block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def add_label(identifier)
|
42
|
+
raise "Label @#{identifier} already defined" if @labels[identifier.to_sym]
|
43
|
+
@labels[identifier.to_sym] = next_label
|
44
|
+
end
|
45
|
+
|
46
|
+
def add_var(identifier, node)
|
47
|
+
raise "Variable #{identifier} already defined" if @variables[identifier.to_sym]
|
48
|
+
|
49
|
+
@variables[identifier.to_sym] = node
|
50
|
+
node.comment = identifier
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_constant(identifier, node)
|
54
|
+
raise "Constant #{identifier} already defined" if @constants[identifier.to_sym]
|
55
|
+
|
56
|
+
@constants[identifier.to_sym] = node
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_namespace(identifier)
|
60
|
+
if ns = @namespaces[identifier.to_sym]
|
61
|
+
return ns
|
62
|
+
end
|
63
|
+
|
64
|
+
false
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_var(identifier)
|
68
|
+
raise "Variable (#{identifier}) not defined" if @variables[identifier.to_sym].nil?
|
69
|
+
|
70
|
+
@variables[identifier.to_sym]
|
71
|
+
end
|
72
|
+
|
73
|
+
def get_constant(identifier)
|
74
|
+
raise "Constant (#{identifier}) not defined" if @constants[identifier.to_sym].nil?
|
75
|
+
|
76
|
+
@constants[identifier.to_sym]
|
77
|
+
end
|
78
|
+
|
79
|
+
def define_labels
|
80
|
+
@nodes.select {|n| n.is_a? Nodes::LabelDefinitionNode}.each do |n|
|
81
|
+
add_label(n.identifier)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def pos_section
|
86
|
+
return "" if @position_data.empty?
|
87
|
+
return "" if @position_data[:positions].empty?
|
88
|
+
|
89
|
+
@position_data[:positions].inject("") do |s,p|
|
90
|
+
s << %(P[#{p[:id]}:"#{p[:comment]}"]{\n)
|
91
|
+
|
92
|
+
p[:mask].each do |q|
|
93
|
+
s << pos_return(q)
|
94
|
+
end
|
95
|
+
|
96
|
+
s << %(\n};\n)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def pos_return(position_hash)
|
101
|
+
s = ""
|
102
|
+
if position_hash[:config].is_a?(Hash)
|
103
|
+
s << %( GP#{position_hash[:group]}:
|
104
|
+
UF : #{position_hash[:uframe]}, UT : #{position_hash[:utool]}, CONFIG : '#{position_hash[:config][:flip] ? 'F' : 'N'} #{position_hash[:config][:up] ? 'U' : 'D'} #{position_hash[:config][:top] ? 'T' : 'B'}, #{position_hash[:config][:turn_counts].join(', ')}',
|
105
|
+
X = #{position_hash[:components][:x]} mm, Y = #{position_hash[:components][:y]} mm, Z = #{position_hash[:components][:z]} mm,
|
106
|
+
W = #{position_hash[:components][:w]} deg, P = #{position_hash[:components][:p]} deg, R = #{position_hash[:components][:r]} deg)
|
107
|
+
else
|
108
|
+
s << %( GP#{position_hash[:group]}:
|
109
|
+
UF : #{position_hash[:uframe]}, UT : #{position_hash[:utool]})
|
110
|
+
if position_hash[:components].is_a?(Hash)
|
111
|
+
position_hash[:components].each_with_index do |key, joint|
|
112
|
+
s << %(, \n)
|
113
|
+
s << %(\tJ#{key} = #{joint[1]} deg)
|
114
|
+
end
|
115
|
+
s << %(\n)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
return s
|
120
|
+
end
|
121
|
+
|
122
|
+
def eval
|
123
|
+
s = ""
|
124
|
+
last_node = nil
|
125
|
+
|
126
|
+
define_labels
|
127
|
+
|
128
|
+
@source_line_count = 0
|
129
|
+
|
130
|
+
@nodes.each do |n|
|
131
|
+
@source_line_count += 1 unless n.is_a?(Nodes::TerminatorNode) && !last_node.is_a?(Nodes::TerminatorNode)
|
132
|
+
raise if n.is_a?(String)
|
133
|
+
|
134
|
+
res = n.eval(self)
|
135
|
+
|
136
|
+
# preserve whitespace
|
137
|
+
if n.is_a?(Nodes::TerminatorNode) && last_node.is_a?(Nodes::TerminatorNode)
|
138
|
+
s += " ;\n"
|
139
|
+
end
|
140
|
+
last_node = n
|
141
|
+
# end preserve whitespace
|
142
|
+
|
143
|
+
next if res.nil?
|
144
|
+
|
145
|
+
s += "#{res} ;\n"
|
146
|
+
end
|
147
|
+
s
|
148
|
+
rescue RuntimeError => e
|
149
|
+
raise "Runtime error on line #{@source_line_count}:\n#{e}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|