trac_lang 0.1.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.
@@ -0,0 +1,88 @@
1
+
2
+ module TracLang
3
+
4
+ # TRAC octal number. Unlike the TracLang::Decimal, any
5
+ # string prefix is discarded. Bit size is saved so that
6
+ # operations can retain the size.
7
+ class Octal
8
+
9
+ # Number of octal digits in this number.
10
+ attr_accessor :size
11
+
12
+ # Numeric value of this number.
13
+ attr_accessor :value
14
+
15
+ # Creates a TRAC octal. Any leading non-numeric characters are ignored.
16
+ # If there are no octal characters, zero is assumed.
17
+ def initialize(str = '')
18
+ raise ArgumentError unless str.is_a? String
19
+ b = str.partition(/[0-7]*$/)
20
+ @value = b[1].to_i(8)
21
+ @size = b[1].length
22
+ end
23
+
24
+ # Tests for equality. This is different from numeric equality,
25
+ # because size is also tested.
26
+ def ==(o)
27
+ return super unless o.is_a? TracLang::Octal
28
+ o.value == @value && o.size == @size
29
+ end
30
+
31
+ # Converts octal number to string. Returns a string <size> digits long.
32
+ def to_s
33
+ if value < 0
34
+ sprintf("%0*.*o", size + 3, size + 3, value).slice(3..-1)
35
+ else
36
+ sprintf("%0*.*o", size, size, value)
37
+ end
38
+ end
39
+
40
+ # Bit or. Result bit size is maximum of bit size of parameters.
41
+ define_method(:|) do |other|
42
+ result = Octal.new
43
+ result.size = [self.size, other.size].max
44
+ result.value = self.value | other.value
45
+ result
46
+ end
47
+
48
+ # Bitwise and. Result bit size is minimum of bit size of parameters.
49
+ define_method(:&) do |other|
50
+ result = Octal.new
51
+ result.size = [self.size, other.size].min
52
+ result.value = self.value & other.value
53
+ result
54
+ end
55
+
56
+ # Bit complement.
57
+ def ~
58
+ result = Octal.new
59
+ result.size = size
60
+ result.value = ~value
61
+ result
62
+ end
63
+
64
+ # Shifts octal bits by the given amount.
65
+ def shift(n)
66
+ result = Octal.new
67
+ result.size = size
68
+ result.value = n.value < 0 ? value >> -n.value : value << n.value
69
+ result
70
+ end
71
+
72
+ # Rotates octal bits by the given amount.
73
+ def rotate(n)
74
+ result = Octal.new
75
+ result.size = size
76
+ bits = 3 * size
77
+ bit_mask = 2 ** bits - 1
78
+ if n.value < 0
79
+ result.value = ((value >> -n.value) | (value << (bits + n.value))) & bit_mask
80
+ else
81
+ result.value = ((value << n.value) | (value >> (bits - n.value))) & bit_mask
82
+ end
83
+ result
84
+ end
85
+
86
+ end
87
+
88
+ end
@@ -0,0 +1,114 @@
1
+
2
+ module TracLang
3
+
4
+ # Parser for TRAC input. Given the input a character at a time, it
5
+ # creates an active string and then executes it when the string is
6
+ # completed.
7
+ class Parser
8
+
9
+ # Parses the given string and executes it, until the
10
+ # active string is empty.
11
+ def parse(str, &blk)
12
+ @active = str
13
+ @handler = :reading
14
+ @expressions = []
15
+ loop do
16
+ if @active.empty?
17
+ # if handler is parens, we've read a open paren w/o a matching closing one
18
+ throw :reset if @handler == :parens
19
+ # if handler if reading, and expressions is not empty
20
+ # we've read #( without a matching end paren
21
+ throw :reset if @handler == :reading && !@expressions.empty?
22
+ # if hander is :start_proc, we've just read a bunch of #s
23
+ # so we can ignore them without throwing an error
24
+ return
25
+ end
26
+ self.send(@handler, @active.slice!(0), &blk)
27
+ end
28
+ end
29
+
30
+ # Add character to current expression, ignore if no expression exists
31
+ def concat(c)
32
+ unless @expressions.empty?
33
+ @expressions.last.concat(c)
34
+ end
35
+ end
36
+
37
+ # Handler while actively reading the active string. If you start an expression,
38
+ # switch to the start_proc handler. If you see an open parenthesis, switch
39
+ # to the parens handler. Comma marks a new argument in the current expression, and
40
+ # end parenthesis marks the end of an expression. When an expression is ended, execute it
41
+ # and handle the results.
42
+ def reading(c, &blk)
43
+ case c
44
+ when '#'
45
+ @expressions.push Expression.new
46
+ @handler = :start_proc
47
+ when '('
48
+ @nesting = 1
49
+ @handler = :parens
50
+ when ','
51
+ unless @expressions.empty?
52
+ @expressions.last.newarg
53
+ end
54
+ when ')'
55
+ throw :reset if @expressions.empty?
56
+ expression = @expressions.pop
57
+ result = blk.call(expression)
58
+ if result[:force] || expression.active?
59
+ @active.prepend(result[:value])
60
+ else
61
+ concat(result[:value])
62
+ end
63
+ when "\n", "\r"
64
+ # ignore cr and lf
65
+ else
66
+ concat(c)
67
+ end
68
+ end
69
+
70
+ # Handler while reading inside protective parentheses. Copies all
71
+ # characters to current expression while keeping track of current parentheses
72
+ # nesting. When a matching parenthesis is found, go back to reading
73
+ # handler.
74
+ def parens(c)
75
+ case c
76
+ when '('
77
+ @nesting += 1
78
+ when ')'
79
+ @nesting -= 1
80
+ if @nesting == 0
81
+ @handler = :reading
82
+ return
83
+ end
84
+ end
85
+ concat(c)
86
+ end
87
+
88
+ # Handler for the start of an expression. Mark the expression as active or not,
89
+ # depending on whether it starts with #(...) or ##(...).
90
+ def start_proc(c, &blk)
91
+ case c
92
+ when '#'
93
+ throw :reset if @expressions.empty?
94
+ if @expressions.last.active?
95
+ @expressions.last.active = false
96
+ else
97
+ unless @expressions.size == 1
98
+ @expressions[-2].concat(c)
99
+ end
100
+ end
101
+ when '('
102
+ @handler = :reading
103
+ else
104
+ throw :reset if @expressions.empty?
105
+ discard = @expressions.pop
106
+ concat(discard.active? ? '#' : '##')
107
+ @handler = :reading
108
+ reading(c, &blk)
109
+ end
110
+ end
111
+
112
+ end
113
+
114
+ end
@@ -0,0 +1,4 @@
1
+ module TracLang
2
+ # Version number of TRAC Language processor.
3
+ VERSION = '0.1.0'
4
+ end
data/trac_lang.gemspec ADDED
@@ -0,0 +1,42 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'trac_lang/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "trac_lang"
8
+ spec.version = TracLang::VERSION
9
+ spec.authors = ["David Stanley"]
10
+ spec.email = ["dstanley1994@yahoo.com"]
11
+
12
+ spec.summary = %q{Ruby implementation of the TRAC computer language.}
13
+ spec.description = %q{TRAC is a macro language invented in the 1950s.}
14
+ spec.homepage = %q(https://github.com/dstanley1994/trac_lang)
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
21
+ else
22
+ raise "RubyGems 2.0 or newer is required to protect against " \
23
+ "public gem pushes."
24
+ end
25
+
26
+ spec.require_paths = ["lib"]
27
+ spec.bindir = "exe"
28
+ spec.executables = ['trac_lang']
29
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
30
+ f.match(%r{^(test|spec|features)/})
31
+ end
32
+ spec.has_rdoc = true
33
+ spec.rdoc_options << '--include' << 'lib/trac_lang'
34
+
35
+ spec.add_runtime_dependency "highline", "~> 1.7", ">= 1.7.8"
36
+
37
+ spec.add_development_dependency "bundler", "~> 1.14"
38
+ spec.add_development_dependency "rake", "~> 10.0"
39
+ spec.add_development_dependency "rspec", "~> 3.0"
40
+ spec.add_development_dependency "cucumber", '~> 2.4', '>= 2.4.0'
41
+ spec.add_development_dependency "aruba", "~> 0.14.2"
42
+ end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trac_lang
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - David Stanley
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-10-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: highline
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 1.7.8
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '1.7'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 1.7.8
33
+ - !ruby/object:Gem::Dependency
34
+ name: bundler
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.14'
40
+ type: :development
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.14'
47
+ - !ruby/object:Gem::Dependency
48
+ name: rake
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '10.0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '10.0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: rspec
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '3.0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '3.0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: cucumber
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '2.4'
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: 2.4.0
85
+ type: :development
86
+ prerelease: false
87
+ version_requirements: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '2.4'
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 2.4.0
95
+ - !ruby/object:Gem::Dependency
96
+ name: aruba
97
+ requirement: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - "~>"
100
+ - !ruby/object:Gem::Version
101
+ version: 0.14.2
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - "~>"
107
+ - !ruby/object:Gem::Version
108
+ version: 0.14.2
109
+ description: TRAC is a macro language invented in the 1950s.
110
+ email:
111
+ - dstanley1994@yahoo.com
112
+ executables:
113
+ - trac_lang
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - ".gitignore"
118
+ - ".rspec"
119
+ - ".travis.yml"
120
+ - CODE_OF_CONDUCT.md
121
+ - Gemfile
122
+ - LICENSE.txt
123
+ - README.md
124
+ - Rakefile
125
+ - bin/console
126
+ - bin/setup
127
+ - examples/README.trl
128
+ - examples/golf.trl
129
+ - examples/list.trl
130
+ - examples/math.trl
131
+ - examples/meta.trl
132
+ - examples/ratio.trl
133
+ - examples/struct.trl
134
+ - examples/term.trl
135
+ - examples/util.trl
136
+ - exe/trac_lang
137
+ - lib/trac_lang.rb
138
+ - lib/trac_lang/bindings.rb
139
+ - lib/trac_lang/block.rb
140
+ - lib/trac_lang/decimal.rb
141
+ - lib/trac_lang/dispatch.rb
142
+ - lib/trac_lang/executor.rb
143
+ - lib/trac_lang/expression.rb
144
+ - lib/trac_lang/form.rb
145
+ - lib/trac_lang/immediate_read.rb
146
+ - lib/trac_lang/octal.rb
147
+ - lib/trac_lang/parser.rb
148
+ - lib/trac_lang/version.rb
149
+ - trac_lang.gemspec
150
+ homepage: https://github.com/dstanley1994/trac_lang
151
+ licenses:
152
+ - MIT
153
+ metadata:
154
+ allowed_push_host: https://rubygems.org
155
+ post_install_message:
156
+ rdoc_options:
157
+ - "--include"
158
+ - lib/trac_lang
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.6.13
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Ruby implementation of the TRAC computer language.
177
+ test_files: []