oryx 0.1.1 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/README.md +4 -9
- data/Rakefile +0 -1
- data/lib/oryx/ast.rb +74 -0
- data/lib/oryx/parser.rb +116 -0
- data/lib/oryx/runner.rb +3 -0
- data/lib/oryx/version.rb +1 -1
- data/lib/oryx.rb +2 -1
- data/oryx.gemspec +0 -4
- data/test/lib/oryx/parser_test.rb +8 -0
- metadata +8 -42
- data/bin/oryx.markdown +0 -29
- data/lib/oryx/preprocessor.rb +0 -21
- data/man/man1/oryx.1 +0 -21
- data/test/lib/oryx/preprocessor_test.rb +0 -65
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -12,17 +12,11 @@ C-Flat is a working subset of C designed for use in compilers courses. C-flat in
|
|
12
12
|
|
13
13
|
## Installation
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
gem 'oryx'
|
18
|
-
|
19
|
-
And then execute:
|
20
|
-
|
21
|
-
$ bundle
|
15
|
+
$ gem install oryx
|
22
16
|
|
23
|
-
|
17
|
+
## Requirements
|
24
18
|
|
25
|
-
|
19
|
+
- Ruby >= 1.9.3
|
26
20
|
|
27
21
|
## Usage
|
28
22
|
|
@@ -35,6 +29,7 @@ For more details try
|
|
35
29
|
## See Also
|
36
30
|
`bin/oryx.markdown`
|
37
31
|
|
32
|
+
|
38
33
|
## Contributing
|
39
34
|
As this is a course project pull requests will be ignored.
|
40
35
|
|
data/Rakefile
CHANGED
data/lib/oryx/ast.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rltk/ast'
|
2
|
+
|
3
|
+
module Oryx
|
4
|
+
class Expression < RLTK::ASTNode; end
|
5
|
+
|
6
|
+
class Number < Expression
|
7
|
+
value :value, Integer
|
8
|
+
end
|
9
|
+
|
10
|
+
class Variable < Expression
|
11
|
+
value :name, String
|
12
|
+
end
|
13
|
+
|
14
|
+
class Binary < Expression
|
15
|
+
child :left, Expression
|
16
|
+
child :right, Expression
|
17
|
+
end
|
18
|
+
|
19
|
+
class Assign < Expression
|
20
|
+
value :name, String
|
21
|
+
child :right, Expression
|
22
|
+
end
|
23
|
+
|
24
|
+
class Add < Binary; end
|
25
|
+
class Sub < Binary; end
|
26
|
+
class Mul < Binary; end
|
27
|
+
class Div < Binary; end
|
28
|
+
|
29
|
+
class GE < Binary; end
|
30
|
+
class GEQ < Binary; end
|
31
|
+
class LE < Binary; end
|
32
|
+
class LEQ < Binary; end
|
33
|
+
class EQ < Binary; end
|
34
|
+
class NEQ < Binary; end
|
35
|
+
|
36
|
+
class Return < Expression
|
37
|
+
child :right, Expression
|
38
|
+
end
|
39
|
+
|
40
|
+
class If < Expression
|
41
|
+
child :cond, Expression
|
42
|
+
child :then, Expression
|
43
|
+
child :else, Expression
|
44
|
+
end
|
45
|
+
|
46
|
+
class CodeBlock < Expression
|
47
|
+
child :statements, [Expression]
|
48
|
+
end
|
49
|
+
|
50
|
+
class ParamList < RLTK::ASTNode
|
51
|
+
child :params, [Expression]
|
52
|
+
end
|
53
|
+
|
54
|
+
class Function < RLTK::ASTNode
|
55
|
+
value :i, String
|
56
|
+
child :params, ParamList
|
57
|
+
child :body, CodeBlock
|
58
|
+
end
|
59
|
+
|
60
|
+
class While < Expression
|
61
|
+
child :condition, Expression
|
62
|
+
child :body, CodeBlock
|
63
|
+
end
|
64
|
+
|
65
|
+
class Type < Expression
|
66
|
+
value :t, String
|
67
|
+
end
|
68
|
+
|
69
|
+
class Boolean < Type; end
|
70
|
+
class Char < Type; end
|
71
|
+
class Int < Type; end
|
72
|
+
class Str < Type; end
|
73
|
+
|
74
|
+
end
|
data/lib/oryx/parser.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'rltk'
|
2
|
+
require_relative "../oryx"
|
3
|
+
|
4
|
+
module Oryx
|
5
|
+
class Parser < RLTK::Parser
|
6
|
+
|
7
|
+
left :ASSIGN, :RETURN
|
8
|
+
left :EQ, :NEQ
|
9
|
+
left :GE, :GEQ, :LE, :LEQ
|
10
|
+
left :PLUS, :MINUS
|
11
|
+
left :TIMES, :DIV
|
12
|
+
|
13
|
+
production(:input) do
|
14
|
+
clause('') { || [] }
|
15
|
+
clause('ext_dec_list') { |edl| edl }
|
16
|
+
end
|
17
|
+
|
18
|
+
production(:external_declaration) do
|
19
|
+
clause('vdecl') { |v| v }
|
20
|
+
clause('vinit') { |v| v }
|
21
|
+
clause('fdecl') { |f| f }
|
22
|
+
end
|
23
|
+
|
24
|
+
production(:ext_dec_list) do
|
25
|
+
clause('ext_dec_list external_declaration') { |edl, ed| edl + Array(ed)}
|
26
|
+
clause('external_declaration') { |ed| [ed] }
|
27
|
+
end
|
28
|
+
|
29
|
+
production(:vdecl) do
|
30
|
+
clause('type_spec IDENT SEMI') { |t, i, _| Variable.new i}
|
31
|
+
end
|
32
|
+
|
33
|
+
production(:vinit) do
|
34
|
+
clause('type_spec IDENT ASSIGN constant SEMI') { |t, i, _, c, _| Assign.new i, c}
|
35
|
+
end
|
36
|
+
|
37
|
+
production(:fdecl) do
|
38
|
+
clause('type_spec IDENT LPAREN opt_param_list RPAREN code_block') { |t, i, _, opl, _, c| Function.new i, opl, c }
|
39
|
+
end
|
40
|
+
|
41
|
+
production(:opt_param_list) do
|
42
|
+
clause('') { || ParamList.new [] }
|
43
|
+
clause('param_list') { |pl| ParamList.new pl}
|
44
|
+
end
|
45
|
+
|
46
|
+
production(:param_list) do
|
47
|
+
clause('param') { |p| [p] }
|
48
|
+
clause('param COMMA param_list') { |p, _, pl| Array(p) + pl }
|
49
|
+
end
|
50
|
+
|
51
|
+
production(:param) do
|
52
|
+
clause('type_spec IDENT') { |t, i| Variable.new i }
|
53
|
+
end
|
54
|
+
|
55
|
+
production(:constant) do
|
56
|
+
clause('NUM') { |n| Number.new n.to_i }
|
57
|
+
clause('STRCON') { |s| Cstring.new s}
|
58
|
+
clause('CHARCON') { |c| Char.new c }
|
59
|
+
end
|
60
|
+
|
61
|
+
production(:type_spec) do
|
62
|
+
clause('BOOLEAN') { |_| Boolean.new 'bool'}
|
63
|
+
clause('CHAR') { |_| Char.new 'char'}
|
64
|
+
clause('INT') { |_| Int.new 'int'}
|
65
|
+
clause('STRING') { |_| Str.new 'str'}
|
66
|
+
clause('VOID') { |_| }
|
67
|
+
end
|
68
|
+
|
69
|
+
production(:code_block) do
|
70
|
+
clause('LCURLY statement_list RCURLY') { |_, sl, _| CodeBlock.new(sl) }
|
71
|
+
end
|
72
|
+
|
73
|
+
production(:statement_list) do
|
74
|
+
clause('') { || [] }
|
75
|
+
clause('statement_list statement') { |sl, s| sl + Array(s) }
|
76
|
+
clause('statement') { |s| [s] }
|
77
|
+
end
|
78
|
+
|
79
|
+
production(:statement) do
|
80
|
+
clause('e SEMI') { |e, _| e }
|
81
|
+
clause('if_statement') { |i| i}
|
82
|
+
clause('WHILE LPAREN e RPAREN code_block') {|_,_,e,_,c| While.new(e,c) }
|
83
|
+
end
|
84
|
+
|
85
|
+
production(:if_statement) do
|
86
|
+
clause('IF LPAREN e RPAREN statement') { |_, _, e, _, s| If.new(e, s, nil) }
|
87
|
+
clause('IF LPAREN e RPAREN statement ELSE statement') { |_,_,e,_,ts,_,fs| If.new(e, ts, fs) }
|
88
|
+
clause('IF LPAREN e RPAREN code_block ELSE code_block') {|_,_,e,_,tc,_,fc| If.new(e, tc, fc) }
|
89
|
+
end
|
90
|
+
|
91
|
+
production(:e) do
|
92
|
+
clause('LPAREN e RPAREN') { |_, e, _| e }
|
93
|
+
|
94
|
+
clause('IDENT') { |i| Variable.new i }
|
95
|
+
clause('constant') { |c| c }
|
96
|
+
clause('IDENT ASSIGN e') { |e0, _, e1| Assign.new e0, e1 }
|
97
|
+
|
98
|
+
clause('e PLUS e') { |e0, _, e1| Add.new(e0, e1) }
|
99
|
+
clause('e MINUS e') { |e0, _, e1| Sub.new(e0, e1) }
|
100
|
+
clause('e TIMES e') { |e0, _, e1| Mul.new(e0, e1) }
|
101
|
+
clause('e DIV e') { |e0, _, e1| Div.new(e0, e1) }
|
102
|
+
clause('e GE e') { |e0, _, e1| GE.new(e0, e1) }
|
103
|
+
clause('e GEQ e') { |e0, _, e1| GEQ.new(e0, e1) }
|
104
|
+
clause('e LE e') { |e0, _, e1| LE.new(e0, e1) }
|
105
|
+
clause('e LEQ e') { |e0, _, e1| LEQ.new(e0, e1) }
|
106
|
+
clause('e EQ e') { |e0, _, e1| EQ.new(e0, e1) }
|
107
|
+
clause('e NEQ e') { |e0, _, e1| NEQ.new(e0, e1) }
|
108
|
+
|
109
|
+
|
110
|
+
clause('RETURN e') { |_, e| Return.new e }
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
finalize explain: 'explain.out'
|
115
|
+
end
|
116
|
+
end
|
data/lib/oryx/runner.rb
CHANGED
@@ -18,6 +18,9 @@ module Oryx
|
|
18
18
|
l = Lexer.new
|
19
19
|
output_filename.open('w:UTF-8') { |f| f.write(tabularize_output l.lex_file(input_filename.to_s)) }
|
20
20
|
puts "complete".green
|
21
|
+
|
22
|
+
p = Parser.new
|
23
|
+
p.parse(l.lex_file(input_filename.to_s), parse_tree: 'tree.dot', verbose: 'parse.out')
|
21
24
|
end
|
22
25
|
|
23
26
|
private
|
data/lib/oryx/version.rb
CHANGED
data/lib/oryx.rb
CHANGED
data/oryx.gemspec
CHANGED
@@ -6,7 +6,6 @@ require 'oryx/version'
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
7
|
gem.name = "oryx"
|
8
8
|
gem.version = Oryx::VERSION
|
9
|
-
gem.date = Date.today.to_s
|
10
9
|
gem.authors = ["Casey Robinson"]
|
11
10
|
gem.email = ["kc@rampantmonkey.com"]
|
12
11
|
gem.description = %q{C-Flat to x86 compiler}
|
@@ -14,15 +13,12 @@ Gem::Specification.new do |gem|
|
|
14
13
|
gem.homepage = "http://github.com/rampantmonkey/oryx"
|
15
14
|
|
16
15
|
gem.files = `git ls-files`.split($/)
|
17
|
-
gem.files += Dir['man/man?/*.?']
|
18
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) unless !f and f["markdown"]}
|
19
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
20
18
|
gem.require_paths = ["lib"]
|
21
19
|
|
22
20
|
gem.add_development_dependency 'rake', '~>0.9.2.2'
|
23
21
|
gem.add_development_dependency 'shoulda', '~>3.3.2'
|
24
|
-
gem.add_development_dependency 'md2man', '~>1.4'
|
25
|
-
gem.add_development_dependency 'binman', '~>3.2.0'
|
26
22
|
|
27
23
|
gem.add_dependency 'rltk', '~>2.2.1'
|
28
24
|
gem.add_dependency 'colorize', '~>0.5.8'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oryx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02
|
12
|
+
date: 2013-04-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -43,38 +43,6 @@ dependencies:
|
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: 3.3.2
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: md2man
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ~>
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: '1.4'
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.4'
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: binman
|
64
|
-
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
|
-
requirements:
|
67
|
-
- - ~>
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: 3.2.0
|
70
|
-
type: :development
|
71
|
-
prerelease: false
|
72
|
-
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
|
-
requirements:
|
75
|
-
- - ~>
|
76
|
-
- !ruby/object:Gem::Version
|
77
|
-
version: 3.2.0
|
78
46
|
- !ruby/object:Gem::Dependency
|
79
47
|
name: rltk
|
80
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -112,7 +80,6 @@ email:
|
|
112
80
|
- kc@rampantmonkey.com
|
113
81
|
executables:
|
114
82
|
- oryx
|
115
|
-
- oryx.markdown
|
116
83
|
extensions: []
|
117
84
|
extra_rdoc_files: []
|
118
85
|
files:
|
@@ -123,19 +90,18 @@ files:
|
|
123
90
|
- README.md
|
124
91
|
- Rakefile
|
125
92
|
- bin/oryx
|
126
|
-
- bin/oryx.markdown
|
127
93
|
- lib/oryx.rb
|
94
|
+
- lib/oryx/ast.rb
|
128
95
|
- lib/oryx/lexer.rb
|
129
96
|
- lib/oryx/options.rb
|
130
|
-
- lib/oryx/
|
97
|
+
- lib/oryx/parser.rb
|
131
98
|
- lib/oryx/runner.rb
|
132
99
|
- lib/oryx/version.rb
|
133
100
|
- oryx.gemspec
|
134
101
|
- test/lib/oryx/lexer_test.rb
|
135
|
-
- test/lib/oryx/
|
102
|
+
- test/lib/oryx/parser_test.rb
|
136
103
|
- test/lib/oryx/version_test.rb
|
137
104
|
- test/test_helper.rb
|
138
|
-
- man/man1/oryx.1
|
139
105
|
homepage: http://github.com/rampantmonkey/oryx
|
140
106
|
licenses: []
|
141
107
|
post_install_message:
|
@@ -150,7 +116,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
150
116
|
version: '0'
|
151
117
|
segments:
|
152
118
|
- 0
|
153
|
-
hash:
|
119
|
+
hash: 730399691837607602
|
154
120
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
121
|
none: false
|
156
122
|
requirements:
|
@@ -159,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
159
125
|
version: '0'
|
160
126
|
segments:
|
161
127
|
- 0
|
162
|
-
hash:
|
128
|
+
hash: 730399691837607602
|
163
129
|
requirements: []
|
164
130
|
rubyforge_project:
|
165
131
|
rubygems_version: 1.8.23
|
@@ -168,6 +134,6 @@ specification_version: 3
|
|
168
134
|
summary: Take a program written in C-Flat and convert it to x86 assembly
|
169
135
|
test_files:
|
170
136
|
- test/lib/oryx/lexer_test.rb
|
171
|
-
- test/lib/oryx/
|
137
|
+
- test/lib/oryx/parser_test.rb
|
172
138
|
- test/lib/oryx/version_test.rb
|
173
139
|
- test/test_helper.rb
|
data/bin/oryx.markdown
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
=begin===
|
2
|
-
# ORYX 2013-2-20 0.1.0
|
3
|
-
|
4
|
-
## NAME
|
5
|
-
|
6
|
-
oryx - cflat tokenizer
|
7
|
-
|
8
|
-
## SYNOPSIS
|
9
|
-
|
10
|
-
`oryx` [-o output-file] input-file
|
11
|
-
|
12
|
-
## DESCRIPTION
|
13
|
-
|
14
|
-
[oryx] produces a table of tokens representing the source code contained in `input-file`. If invalid characters/strings are found they are returned as error tokens and lexing continues. Oryx can even handle (in other words not throw an exception) when given random input, as shown by the test suite.
|
15
|
-
|
16
|
-
## OPTIONS
|
17
|
-
|
18
|
-
`-h`, `--help`
|
19
|
-
Show list of options and usage
|
20
|
-
|
21
|
-
`-o`, `--output` [*FILE*]
|
22
|
-
Specify the filename in which to write the token table
|
23
|
-
|
24
|
-
|
25
|
-
## SEE ALSO
|
26
|
-
|
27
|
-
clang(1), gcc(1)
|
28
|
-
|
29
|
-
=end===
|
data/lib/oryx/preprocessor.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
module Oryx
|
2
|
-
class Preprocessor
|
3
|
-
def initialize
|
4
|
-
end
|
5
|
-
|
6
|
-
def parse content
|
7
|
-
content = remove_comment content
|
8
|
-
remove_outer_whitespace content
|
9
|
-
end
|
10
|
-
|
11
|
-
def remove_comment content
|
12
|
-
content.gsub /\/\*.*?\*\//, ''
|
13
|
-
end
|
14
|
-
|
15
|
-
def remove_outer_whitespace content
|
16
|
-
content.lstrip.rstrip
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
data/man/man1/oryx.1
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
.TH ORYX 2013\-2\-20 0.1.0
|
2
|
-
.SH NAME
|
3
|
-
.PP
|
4
|
-
oryx \- cflat tokenizer
|
5
|
-
.SH SYNOPSIS
|
6
|
-
.PP
|
7
|
-
\fB\fCoryx\fR [\-o output\-file] input\-file
|
8
|
-
.SH DESCRIPTION
|
9
|
-
.PP
|
10
|
-
[oryx] produces a table of tokens representing the source code contained in \fB\fCinput-file\fR. If invalid characters/strings are found they are returned as error tokens and lexing continues. Oryx can even handle (in other words not throw an exception) when given random input, as shown by the test suite.
|
11
|
-
.SH OPTIONS
|
12
|
-
.PP
|
13
|
-
\fB\fC-h\fR, \fB\fC--help\fR
|
14
|
-
Show list of options and usage
|
15
|
-
.PP
|
16
|
-
\fB\fC-o\fR, \fB\fC--output\fR [\fIFILE\fP]
|
17
|
-
Specify the filename in which to write the token table
|
18
|
-
.SH SEE ALSO
|
19
|
-
.PP
|
20
|
-
.BR clang (1),
|
21
|
-
.BR gcc (1)
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require_relative '../../test_helper'
|
2
|
-
|
3
|
-
module Oryx
|
4
|
-
class TestPreprocessor < Test::Unit::TestCase
|
5
|
-
context "one line inputs" do
|
6
|
-
setup do
|
7
|
-
@preprocessor = Preprocessor.new
|
8
|
-
end
|
9
|
-
|
10
|
-
should "not modify empty input" do
|
11
|
-
test_input = ""
|
12
|
-
assert_equal test_input, @preprocessor.parse(test_input)
|
13
|
-
end
|
14
|
-
|
15
|
-
should "not modify simple assignment" do
|
16
|
-
test_input = "int length=7;"
|
17
|
-
assert_equal test_input, @preprocessor.parse(test_input)
|
18
|
-
end
|
19
|
-
|
20
|
-
should "remove block comment" do
|
21
|
-
test_input = "/* this is a block comment in c */"
|
22
|
-
assert_equal "", @preprocessor.parse(test_input)
|
23
|
-
end
|
24
|
-
|
25
|
-
should "remove trailing comment" do
|
26
|
-
test_input = "int a = 5; /* a */"
|
27
|
-
assert_equal "int a = 5;", @preprocessor.parse(test_input)
|
28
|
-
end
|
29
|
-
|
30
|
-
should "remove starting comment" do
|
31
|
-
test_input = "/* a */ int a = 5;"
|
32
|
-
assert_equal "int a = 5;", @preprocessor.parse(test_input)
|
33
|
-
end
|
34
|
-
|
35
|
-
should "remove both comments" do
|
36
|
-
test_input = "/* a */ int a = 5; /* b */"
|
37
|
-
assert_equal "int a = 5;", @preprocessor.parse(test_input)
|
38
|
-
end
|
39
|
-
|
40
|
-
should "remove tons of comments" do
|
41
|
-
test_input = "/* a */"*700 + " int a = 5; " + "/* b */"*107
|
42
|
-
assert_equal "int a = 5;", @preprocessor.parse(test_input)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
context "multi line test" do
|
47
|
-
setup do
|
48
|
-
@preprocessor = Preprocessor.new
|
49
|
-
end
|
50
|
-
|
51
|
-
should "remove extra newline" do
|
52
|
-
test_input = "\n"
|
53
|
-
assert_equal "", @preprocessor.parse(test_input)
|
54
|
-
end
|
55
|
-
|
56
|
-
should "do nothing" do
|
57
|
-
test_input = "int a=5;\na++"
|
58
|
-
assert_equal test_input, @preprocessor.parse(test_input)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|