robolson-simplesem 0.1.2 → 0.1.3
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/README.textile +16 -3
- data/Rakefile +1 -1
- data/bin/simplesem +44 -4
- data/lib/simplesem/simple_sem.treetop +17 -3
- data/lib/simplesem/simplesem_program.rb +12 -0
- data/simplesem.gemspec +3 -3
- data/test/simplesem_test.rb +40 -21
- data/test/test_helper.rb +10 -0
- metadata +3 -2
data/README.textile
CHANGED
@@ -6,7 +6,7 @@ h2. Description
|
|
6
6
|
|
7
7
|
Interpreter for the SIMPLESEM language.
|
8
8
|
|
9
|
-
SIMPLESEM is used in the CS141 Programming Languages course taught by Professor "Shannon Tauro":http://www.ics.uci.edu/~stauro/ at UC Irvine. This Rubygem was created out of my desire to execute SIMPLESEM programs.
|
9
|
+
SIMPLESEM is used in the CS141 Programming Languages course taught by Professor "Shannon Tauro":http://www.ics.uci.edu/~stauro/ at UC Irvine. This Rubygem was created out of my desire to execute SIMPLESEM programs.
|
10
10
|
|
11
11
|
This interpreter utilizes Nathan Sobo's "Treetop":http://github.com/nathansobo/treetop gem to create a parsing expression grammar for parsing SIMPLESEM commands.
|
12
12
|
|
@@ -20,6 +20,16 @@ Execute a SIMPLESEM program using the simplesem command. Pass the filename of th
|
|
20
20
|
|
21
21
|
$ simplesem simplesem_file.txt
|
22
22
|
|
23
|
+
h3. Command Line Options
|
24
|
+
|
25
|
+
The simplesem executable accepts a couple command line options which will display the values in the Data array at the time the program exits.
|
26
|
+
|
27
|
+
-h Print help message
|
28
|
+
-t Print Data array on exit
|
29
|
+
-v Print Data array with change history on exit. Supersedes -t if it is also specified.
|
30
|
+
|
31
|
+
Use -t if you only want to see the ending value at each position in the Data array, otherwise use -v to see each data location's history. If neither -t or -v is used the program will not display the data array.
|
32
|
+
|
23
33
|
h2. Introduction to SIMPLESEM
|
24
34
|
|
25
35
|
SIMPLESEM is an abstract semantic processor that is based on the Von Neumann model of the fetch-execute cycle.
|
@@ -127,11 +137,14 @@ jump 8
|
|
127
137
|
</code></pre>
|
128
138
|
|
129
139
|
<pre>
|
130
|
-
$ simplesem sample_programs/gcd.txt
|
140
|
+
$ simplesem -v sample_programs/gcd.txt
|
131
141
|
input: 15
|
132
142
|
input: 35
|
133
143
|
5
|
134
144
|
|
135
|
-
DATA:
|
145
|
+
DATA:
|
146
|
+
0: [15, 10, 5]
|
147
|
+
1: [35, 20, 5]
|
148
|
+
2: [4]
|
136
149
|
</pre>
|
137
150
|
|
data/Rakefile
CHANGED
data/bin/simplesem
CHANGED
@@ -1,15 +1,55 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
#= Overview
|
3
|
+
#
|
4
|
+
# Interpreter for the SIMPLESEM language
|
5
|
+
#
|
6
|
+
#= Usage
|
7
|
+
#
|
8
|
+
# simplesem [-t|-v] filename
|
9
|
+
#
|
10
|
+
# Options:
|
11
|
+
# -h Print this message
|
12
|
+
# -t Print Data array on exit
|
13
|
+
# -v Print Data array with change history on exit. Supersedes -t
|
14
|
+
# if it is also specified.
|
15
|
+
#
|
16
|
+
|
2
17
|
require 'rubygems'
|
18
|
+
require 'rdoc/usage'
|
19
|
+
require 'getoptlong'
|
3
20
|
|
4
21
|
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
|
5
22
|
require 'simplesem'
|
6
23
|
|
7
|
-
|
8
|
-
|
9
|
-
|
24
|
+
opts = GetoptLong.new(
|
25
|
+
[ '-h', '--help', GetoptLong::NO_ARGUMENT ],
|
26
|
+
[ '-t', GetoptLong::NO_ARGUMENT ],
|
27
|
+
[ '-v', GetoptLong::NO_ARGUMENT ]
|
28
|
+
)
|
29
|
+
|
30
|
+
verbosity = 0 # by default do not print what is in Data
|
31
|
+
|
32
|
+
opts.each do |opt, arg|
|
33
|
+
case opt
|
34
|
+
when '-h'
|
35
|
+
RDoc::usage
|
36
|
+
when '-t'
|
37
|
+
verbosity = 1
|
38
|
+
when '-v'
|
39
|
+
verbosity = 2
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
if ARGV.length != 1
|
44
|
+
puts "Missing filename argument (try --help)"
|
45
|
+
exit 0
|
10
46
|
end
|
11
47
|
|
12
48
|
ssp = SimpleSemProgram.new(ARGV.shift)
|
13
49
|
ssp.run
|
14
50
|
|
15
|
-
|
51
|
+
if (verbosity == 1)
|
52
|
+
puts "\nDATA: \n" + ssp.inspect_data
|
53
|
+
elsif (verbosity == 2)
|
54
|
+
puts "\nDATA: \n" + ssp.inspect_data_with_history
|
55
|
+
end
|
@@ -20,7 +20,13 @@ grammar SimpleSem
|
|
20
20
|
rule set_stmt_assign
|
21
21
|
'set' space loc:additive comma value:additive {
|
22
22
|
def execute(env)
|
23
|
-
|
23
|
+
evaled_loc = loc.eval(env)
|
24
|
+
evaled_value = value.eval(env)
|
25
|
+
if env.data[evaled_loc].nil?
|
26
|
+
env.data[evaled_loc] = Array[evaled_value]
|
27
|
+
else
|
28
|
+
env.data[evaled_loc] << evaled_value
|
29
|
+
end
|
24
30
|
end
|
25
31
|
}
|
26
32
|
end
|
@@ -43,7 +49,15 @@ grammar SimpleSem
|
|
43
49
|
'set' space loc:additive comma 'read' {
|
44
50
|
def execute(env)
|
45
51
|
print "input: "
|
46
|
-
|
52
|
+
|
53
|
+
evaled_loc = loc.eval(env)
|
54
|
+
input_value = $stdin.gets.strip.to_i
|
55
|
+
|
56
|
+
if env.data[evaled_loc].nil?
|
57
|
+
env.data[evaled_loc] = Array[input_value]
|
58
|
+
else
|
59
|
+
env.data[evaled_loc] << input_value
|
60
|
+
end
|
47
61
|
end
|
48
62
|
}
|
49
63
|
end
|
@@ -83,7 +97,7 @@ grammar SimpleSem
|
|
83
97
|
rule data_lookup
|
84
98
|
'D[' expr:additive ']' {
|
85
99
|
def eval(env)
|
86
|
-
env.data[expr.eval(env)]
|
100
|
+
env.data[expr.eval(env)].last
|
87
101
|
end
|
88
102
|
}
|
89
103
|
end
|
@@ -42,4 +42,16 @@ class SimpleSemProgram
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
46
|
+
def inspect_data
|
47
|
+
res = String.new
|
48
|
+
@data.each_with_index {|loc, i| res += "#{i}: #{loc.last}\n" }
|
49
|
+
res
|
50
|
+
end
|
51
|
+
|
52
|
+
def inspect_data_with_history
|
53
|
+
res = String.new
|
54
|
+
@data.each_with_index {|loc, i| res += "#{i}: #{loc.inspect}\n" }
|
55
|
+
res
|
56
|
+
end
|
45
57
|
end
|
data/simplesem.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{simplesem}
|
5
|
-
s.version = "0.1.
|
5
|
+
s.version = "0.1.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Rob Olson"]
|
9
|
-
s.date = %q{2009-
|
9
|
+
s.date = %q{2009-04-01}
|
10
10
|
s.default_executable = %q{simplesem}
|
11
11
|
s.description = %q{SIMPLESEM Interpreter}
|
12
12
|
s.email = %q{rko618@gmail.com}
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.files = ["LICENSE", "Manifest", "README.textile", "Rakefile", "bin/simplesem", "lib/simplesem/arithmetic.treetop", "lib/simplesem/arithmetic_node_classes.rb", "lib/simplesem/simple_sem.treetop", "lib/simplesem/simplesem_program.rb", "lib/simplesem.rb", "sample_programs/case-statement.txt", "sample_programs/gcd.txt", "sample_programs/hello-world.txt", "sample_programs/while-loop.txt", "simplesem.gemspec", "simplesem.tmproj", "test/simplesem_test.rb", "test/test_helper.rb"]
|
16
16
|
s.has_rdoc = true
|
17
17
|
s.homepage = %q{http://github.com/robolson/simplesem}
|
18
|
-
s.rdoc_options = ["--line-numbers", "--title", "Simplesem", "--main", "README.textile"]
|
18
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Simplesem", "--main", "README.textile"]
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
s.rubyforge_project = %q{simplesem}
|
21
21
|
s.rubygems_version = %q{1.3.1}
|
data/test/simplesem_test.rb
CHANGED
@@ -9,16 +9,37 @@ class SimpleSemParserTest < Test::Unit::TestCase
|
|
9
9
|
def setup
|
10
10
|
@parser = SimpleSemParser.new
|
11
11
|
@ssp = SimpleSemProgram.new
|
12
|
-
@ssp.data[0] = 1
|
12
|
+
@ssp.data[0] = [1]
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_set_stmt_assign
|
16
16
|
parse('set 1, D[0]').execute(@ssp)
|
17
|
-
assert_equal [1, 1], @ssp.data
|
17
|
+
assert_equal [[1], [1]], @ssp.data
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def test_set_stmt_write_string
|
21
|
+
out = capture_stdout do
|
22
|
+
parse('set write, "Hello World!"').execute(@ssp)
|
23
|
+
end
|
24
|
+
assert_equal "Hello World!\n", out.string
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_set_stmt_write_expr
|
28
|
+
out = capture_stdout do
|
29
|
+
parse('set write, 2 > 1').execute(@ssp)
|
30
|
+
end
|
31
|
+
assert_equal "true\n", out.string
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_set_stmt_read
|
35
|
+
fake_in = StringIO.new("2\n3\n")
|
36
|
+
$stdin = fake_in
|
37
|
+
|
38
|
+
capture_stdout do # capture_stdout because we do not want "input:"'s in the test output
|
39
|
+
parse('set 1, read').execute(@ssp)
|
40
|
+
parse('set 1, read').execute(@ssp)
|
41
|
+
end
|
42
|
+
assert_equal [2, 3], @ssp.data[1]
|
22
43
|
end
|
23
44
|
|
24
45
|
def test_jump_stmt
|
@@ -28,56 +49,54 @@ class SimpleSemParserTest < Test::Unit::TestCase
|
|
28
49
|
|
29
50
|
def test_set_to_data_loc
|
30
51
|
parse('set D[0], 2').execute(@ssp)
|
31
|
-
assert_equal 2, @ssp.data[1]
|
52
|
+
assert_equal 2, @ssp.data[1].last
|
32
53
|
end
|
33
54
|
|
34
55
|
def test_complex_expr
|
35
|
-
@ssp.data[1] = 2
|
56
|
+
@ssp.data[1] = [2]
|
36
57
|
parse('set 2, D[0]+D[1]*2').execute(@ssp)
|
37
|
-
assert_equal 5, @ssp.data[2]
|
58
|
+
assert_equal 5, @ssp.data[2].last
|
38
59
|
end
|
39
60
|
|
40
61
|
def test_parenthesis
|
41
|
-
@ssp.data[1] = 2
|
62
|
+
@ssp.data[1] = [2]
|
42
63
|
parse('set 2, (D[0]+D[1])*2').execute(@ssp)
|
43
|
-
assert_equal 6, @ssp.data[2]
|
64
|
+
assert_equal 6, @ssp.data[2].last
|
44
65
|
end
|
45
66
|
|
46
67
|
def test_set_increment_instr
|
47
68
|
parse('set 0, D[0]+1').execute(@ssp)
|
48
|
-
assert_equal 2, @ssp.data[0]
|
69
|
+
assert_equal 2, @ssp.data[0].last
|
49
70
|
end
|
50
71
|
|
51
72
|
def test_nested_data_lookup
|
52
|
-
@ssp.data[0] = 0
|
53
|
-
@ssp.data[1] = 1
|
73
|
+
@ssp.data[0] = [0]
|
74
|
+
@ssp.data[1] = [1]
|
54
75
|
parse('set 2, D[D[0]+1]').execute(@ssp)
|
55
|
-
assert_equal 1, @ssp.data[2]
|
76
|
+
assert_equal 1, @ssp.data[2].last
|
56
77
|
end
|
57
78
|
|
58
79
|
def test_instruction_pointer
|
59
|
-
#
|
80
|
+
# manually incrementing the program counter is required here
|
60
81
|
@ssp.pc = 1
|
61
|
-
parse('set 0, 0').execute(@ssp)
|
62
|
-
@ssp.pc = 2
|
63
82
|
parse('set 0, ip').execute(@ssp)
|
64
|
-
assert_equal
|
83
|
+
assert_equal 1, @ssp.data[0].last # checking that the parser was able to evaluate ip correctly
|
65
84
|
end
|
66
85
|
|
67
86
|
def test_jump_to_data_loc
|
68
|
-
@ssp.data[0] = 2
|
87
|
+
@ssp.data[0] = [2]
|
69
88
|
parse('jump D[0]').execute(@ssp)
|
70
89
|
assert_equal 2, @ssp.pc
|
71
90
|
end
|
72
91
|
|
73
92
|
def test_jumpt_stmt_true
|
74
|
-
@ssp.data[0] = 1
|
93
|
+
@ssp.data[0] = [1]
|
75
94
|
parse('jumpt 5, D[0]=D[0]').execute(@ssp)
|
76
95
|
assert_equal 5, @ssp.pc
|
77
96
|
end
|
78
97
|
|
79
98
|
def test_jumpt_stmt_false
|
80
|
-
@ssp.data[0] = 1
|
99
|
+
@ssp.data[0] = [1]
|
81
100
|
parse('jumpt 5, D[0]=2').execute(@ssp)
|
82
101
|
assert_equal 0, @ssp.pc # pc should not have changed
|
83
102
|
end
|
@@ -108,7 +127,7 @@ class SimpleSemParserTest < Test::Unit::TestCase
|
|
108
127
|
|
109
128
|
def test_negative_number
|
110
129
|
parse('set 0, -1').execute(@ssp)
|
111
|
-
assert_equal -1, @ssp.data[0]
|
130
|
+
assert_equal -1, @ssp.data[0].last
|
112
131
|
end
|
113
132
|
|
114
133
|
def test_halt
|
data/test/test_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: robolson-simplesem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rob Olson
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-04-01 00:00:00 -07:00
|
13
13
|
default_executable: simplesem
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -61,6 +61,7 @@ homepage: http://github.com/robolson/simplesem
|
|
61
61
|
post_install_message:
|
62
62
|
rdoc_options:
|
63
63
|
- --line-numbers
|
64
|
+
- --inline-source
|
64
65
|
- --title
|
65
66
|
- Simplesem
|
66
67
|
- --main
|