tp_plus 0.0.73 → 0.0.74
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/onerobotics/tp_plus.svg?branch=master)](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
|