take 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2637d99ba8ea1bef3aece18d26f31ed73e8585d5
4
- data.tar.gz: 82017635983468566a4e66f433e70e5d8dec765f
3
+ metadata.gz: 451dc9d6ef5b89807d396e55d0320fa2432991a1
4
+ data.tar.gz: 32ee53bde93419d3cc52adc9a41b6fbbda8a4aa9
5
5
  SHA512:
6
- metadata.gz: 52a5a3ffb71977e50388eed3e02344d0fe0caa2bdbcb117affc54409f344b4cb89e9f88d27933d4623ebdfd4f82f293c3a00e6682ebd779fab7fc37f8472ac16
7
- data.tar.gz: f25c40d35046001fed6393a98425dbb86cd7ec9c5c49bdf531d208bafaf2fb0a74319ba8ccee686b7c1779704222c4043ab88c6125c6fe43e59e350740518d71
6
+ metadata.gz: 8d8fddbd0da58bdc641c81190139ed31aeeab39d1d879bd4403997f7ac95e2378bac1007c87d4fa8d0385dad291f5a631ed7d6725d61d5cfab64535888fe7591
7
+ data.tar.gz: 32faa1c8b86163b1d3181efde2c9ac9a5992f605aeef4fbab9653d07fe0e1ea65c9b727c55911267327d1ca580a63ab53c514acf4d74c1b684273a9adc8a3db8
data/.gitignore CHANGED
@@ -12,3 +12,6 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ .project
16
+ .project.rb
17
+ test.*
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class After < Node
5
+
6
+ def after?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Before < Node
5
+
6
+ def before?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Block < Node
5
+ attribute :body, String
6
+
7
+ def block?
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Group < Node
5
+
6
+ def group?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require "virtus"
2
+
3
+ module Take
4
+ class Unit
5
+ module AST
6
+ class Node
7
+
8
+ include Virtus.model
9
+
10
+ attribute :children, Array[Node], default: proc { [] }
11
+ attribute :name, String
12
+ attribute :source, Source
13
+
14
+ [:block?, :group?, :parent?, :test?, :before?, :after?, :prefix?].each do |m|
15
+ define_method(m) { false }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Parent < Node
5
+
6
+ def parent?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Prefix < Node
5
+
6
+ def prefix?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ require "virtus"
2
+
3
+ module Take
4
+ class Unit
5
+ module AST
6
+ class Source
7
+ include Virtus.model
8
+
9
+ attribute :file, String
10
+ attribute :line, Integer
11
+ attribute :column, Integer
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require "take/unit/ast/source"
2
+ require "take/unit/ast/node"
3
+ require "take/unit/ast/group"
4
+ require "take/unit/ast/test"
5
+ require "take/unit/ast/block"
6
+ require "take/unit/ast/parent"
7
+ require "take/unit/ast/after"
8
+ require "take/unit/ast/before"
9
+ require "take/unit/ast/prefix"
10
+
11
+ module Take
12
+ class Unit
13
+ module AST
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,119 @@
1
+ module Take
2
+ class Unit
3
+ class Compiler
4
+
5
+ include PredictMatch
6
+
7
+ attr_reader :parent
8
+
9
+ def initialize(file, tokens)
10
+ @file = file
11
+ @tokens = tokens
12
+ @enum = tokens.each
13
+ @parent = nil
14
+ end
15
+
16
+ def compile
17
+ @parent ||= begin
18
+ @parent = AST::Parent.new(name: @file.
19
+ gsub(/\..*\z/, "").gsub(/[\W]/, "_"))
20
+ while peek do
21
+ @parent.children << compile_group
22
+ end
23
+
24
+ @parent.source = sourcify([0, 0])
25
+ @parent
26
+ end
27
+ end
28
+
29
+ def compile_group
30
+ group = match(:group)
31
+ node = AST::Group.new(name: group[1], source: sourcify(group))
32
+
33
+ until peek == :group_end
34
+ part = compile_part
35
+ node.children << part if part
36
+ end
37
+
38
+ match(:group_end)
39
+
40
+ node
41
+ end
42
+
43
+ def compile_part
44
+ predict :group => :group,
45
+ :test => :test,
46
+ :before => :before,
47
+ :after => :after,
48
+ :prefix => :prefix,
49
+ :macro => :macro
50
+ end
51
+
52
+ def compile_test
53
+ test = match(:test)
54
+ body = match(:block)
55
+ AST::Test.new(name: test[1],
56
+ children: [AST::Block.new({
57
+ body: body[1],
58
+ source: sourcify(body)
59
+ })],
60
+ source: sourcify(test))
61
+ end
62
+
63
+ def compile_before
64
+ before = match(:before)
65
+ body = match(:block)
66
+
67
+ AST::Before.new(name: before[1],
68
+ children: [AST::Block.new({
69
+ body: body[1],
70
+ source: sourcify(body)
71
+ })],
72
+ source: sourcify(before))
73
+ end
74
+
75
+ def compile_after
76
+ after = match(:after)
77
+ body = match(:block)
78
+
79
+ AST::After.new(name: after[1],
80
+ children: [AST::Block.new({
81
+ body: body[1],
82
+ source: sourcify(body)
83
+ })],
84
+ source: sourcify(after))
85
+ end
86
+
87
+ def compile_prefix
88
+ prefix = match(:prefix)
89
+ body = match(:block)
90
+
91
+ @parent.children << AST::Prefix.new(
92
+ name: prefix[1],
93
+ children: [AST::Block.new({
94
+ body: body[1],
95
+ source: sourcify(body)
96
+ })],
97
+ source: sourcify(prefix))
98
+
99
+ nil
100
+ end
101
+
102
+ def compile_macro
103
+
104
+ end
105
+
106
+ private
107
+
108
+ def input
109
+ @enum
110
+ end
111
+
112
+ def sourcify(token)
113
+ hash = Hash[[:line, :column].zip(token[-2..-1])]
114
+ hash.merge(file: @file)
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,136 @@
1
+ module Take
2
+ class Unit
3
+ class Generator
4
+
5
+ def initialize(parent, options)
6
+ @parent = parent
7
+ @groups = [@parent]
8
+ @options = options
9
+ end
10
+
11
+ def generate
12
+ @output ||= begin
13
+ @output = ""
14
+ walk(@parent)
15
+ @output
16
+ end
17
+ end
18
+
19
+ def write_file
20
+ File.open("#{@parent.name}.c", "w") do |f|
21
+ f.write generate
22
+ end
23
+ end
24
+
25
+ def walk(node, *opts)
26
+ case
27
+ when node.group?
28
+ walk_group(node, *opts)
29
+ when node.test?
30
+ walk_test(node, *opts)
31
+ when node.block?
32
+ walk_block(node, *opts)
33
+ when node.parent?
34
+ walk_parent(node, *opts)
35
+ when node.before?
36
+ walk_before(node, *opts)
37
+ when node.after?
38
+ walk_after(node, *opts)
39
+ when node.prefix?
40
+ walk_prefix(node, *opts)
41
+ else
42
+ raise ArgumentError, "Invalid argument given: #{node.class} (#{node})"
43
+ end
44
+ end
45
+
46
+ def walk_group(node)
47
+ @groups << node
48
+ group.children.select(&:test?).
49
+ each { |child| walk(child) }
50
+
51
+ @output << "// group #{group_name}\n"
52
+ @output << "void group_#{group_name}()\n{\n"
53
+ befores.each { |child| walk(child) }
54
+ @output << group.children.select(&:test?).
55
+ map { |child| " test_#{group_name(child)}();" }.
56
+ join("\n")
57
+ @output << "\n"
58
+ afters.each { |child| walk(child) }
59
+ @output << "}\n\n"
60
+ @groups.pop
61
+ end
62
+
63
+ def walk_test(node)
64
+ @output << "void test_#{group_name(node)}()\n{\n"
65
+ node.children.select(&:block?).each { |child| walk(child) }
66
+ @output << "}\n\n"
67
+ end
68
+
69
+ def walk_block(node, indent = 2)
70
+ @output << "#line \"#{node.source.file}\" #{node.source.line + 2}"
71
+ lines = node.body.each_line
72
+ deindent = if scan = node.body.scan(/^[ \t]*(?=\S)/).min
73
+ scan.size
74
+ else
75
+ 0
76
+ end
77
+
78
+ body = lines.map { |l| l.gsub(/^[ \t]{#{deindent}}/, "") }.
79
+ map { |l| (" " * indent) << l }.join("").rstrip.gsub(/^[ \t]+$/, "")
80
+
81
+ @output << body << "\n"
82
+ reset
83
+ end
84
+
85
+ def walk_parent(node)
86
+ node.children.select(&:prefix?).each { |child| walk(child) }
87
+ node.children.reject(&:prefix?).each { |child| walk(child) }
88
+ end
89
+
90
+ def walk_node(node)
91
+ if node.name
92
+ @output << "// #{node.class.name.gsub(/\A.*::/, "").downcase} #{node.name}\n"
93
+ end
94
+
95
+ node.children.each { |child| walk(child) }
96
+ @output << "\n"
97
+ end
98
+
99
+ def walk_prefix(node)
100
+ @output << "// prefix #{node.name}\n"
101
+ node.children.select(&:block?).each { |child| walk(child, 0) }
102
+ @output << "\n"
103
+ end
104
+
105
+ alias_method :walk_before, :walk_node
106
+ alias_method :walk_after, :walk_node
107
+
108
+ private
109
+
110
+ def group
111
+ @groups.last
112
+ end
113
+
114
+ def line
115
+ @output.count("\n") + 2
116
+ end
117
+
118
+ def reset
119
+ @output << "#line \"#{@parent.name}.c\" #{line}\n"
120
+ end
121
+
122
+ def befores
123
+ @groups.map(&:children).flatten.select(&:before?)
124
+ end
125
+
126
+ def afters
127
+ @groups.map(&:children).flatten.select(&:after?)
128
+ end
129
+
130
+ def group_name(test = nil)
131
+ [*@groups[1..-1], test].compact.map(&:name).
132
+ map { |n| n.gsub(/[\W]/, "_") }.join("_")
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,51 @@
1
+ module Take
2
+ class Unit
3
+ module PredictMatch
4
+
5
+ # Makes a prediction based on a set of actions. If the peek token
6
+ # doesn't have an action, it will try the special action `:_`, and
7
+ # then give up. If it finds a corresponding action either time, it
8
+ # will run the action.
9
+ #
10
+ # @param actions [Hash<Symbol => Symbol>]
11
+ # @return [Object] the result of the compiliation.
12
+ def predict(*params, actions)
13
+
14
+ action = actions.fetch(peek) do
15
+ actions.fetch(:_)
16
+ end
17
+
18
+ if action.respond_to?(:call)
19
+ action.call(*params)
20
+ else
21
+ send(:"compile_#{action}", *params)
22
+ end
23
+ end
24
+
25
+ # Matches the next token of the input. If it is not of the
26
+ # expected type, it raises a SyntaxError. Otherwise, it returns
27
+ # the token.
28
+ #
29
+ # @param name [Symbol] the token to match.
30
+ # @return [Array] the token.
31
+ # @raise SyntaxError if the peeked token is invalid.
32
+ def match(name)
33
+ if name == peek
34
+ input.next
35
+ else
36
+ raise SyntaxError, "Unexpected token #{peek}"
37
+ end
38
+ end
39
+
40
+ # Returns the type of the next token.
41
+ #
42
+ # @return [Symbol] the type of the next token.
43
+ def peek
44
+ input.peek[0]
45
+ rescue StopIteration
46
+ nil
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,149 @@
1
+ require "strscan"
2
+
3
+ module Take
4
+ class Unit
5
+ class Scanner
6
+
7
+ attr_reader :tokens
8
+
9
+ def initialize(input)
10
+ @input = "\n" << input
11
+ @scanner = StringScanner.new(input)
12
+ end
13
+
14
+ def scan
15
+ @tokens ||= begin
16
+ @tokens = []
17
+ until @scanner.eos?
18
+ scan_group_body { error! }
19
+ end
20
+ @tokens
21
+ end
22
+ end
23
+
24
+ def scan_group_body
25
+ pre_scan
26
+ scan_nested or
27
+ scan_group or
28
+ scan_body or
29
+ scan_whitespace or
30
+ yield
31
+ end
32
+
33
+ def scan_nested
34
+ if scan_group(/group/)
35
+ scan_whitespace
36
+ @scanner.scan(/\{/) or error!
37
+ loop do
38
+ scan_group_body do
39
+ if @scanner.scan(/\}/)
40
+ pre_scan
41
+ return emit(:group_end)
42
+ else
43
+ error!
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def scan_group(scan = /macro|test|before|after|prefix/)
51
+ if @scanner.scan(scan)
52
+ group_type = @scanner[0]
53
+ @scanner.scan(/ ([A-Za-z0-9_.-]+)\(/) or error!
54
+ group_name = @scanner[1]
55
+
56
+ @scanner.scan(/\s*\;/)
57
+
58
+ emit group_type.intern,
59
+ group_name,
60
+ _scan_arguments(/\s*\)/, /,\s+/)
61
+ end
62
+ end
63
+
64
+ def scan_body
65
+ if @scanner.check(/\s*\{/)
66
+ emit :block, _scan_block
67
+ end
68
+ end
69
+
70
+ def scan_whitespace(newlines = true)
71
+ if newlines
72
+ @scanner.scan(/\s+/)
73
+ else
74
+ @scanner.scan(/[ \t]+/)
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def pre_scan
81
+ @pos = @scanner.pos
82
+ end
83
+
84
+ def line
85
+ @input[0..@pos].count("\n")
86
+ end
87
+
88
+ def column
89
+ last_newline = @input[0..@pos].rindex("\n") || 0
90
+ @pos - last_newline
91
+ end
92
+
93
+ def emit(*args)
94
+ @tokens << args.concat([line, column])
95
+ true
96
+ end
97
+
98
+ def _scan_block
99
+ brack = 1
100
+ body = @scanner.scan(/\s*\{/)
101
+ scan_for = %r{
102
+ (
103
+ (?: " ( \\\\ | \\" | [^"] )* "? )
104
+ | (?: ' ( \\\\ | \\' | [^'] )* '? )
105
+ | (?: // .*? \n )
106
+ | (?: \# .*? \n )
107
+ | (?: /\* [\s\S]+? \*/ )
108
+ | (?: \} )
109
+ | (?: \{ )
110
+ )
111
+ }x
112
+
113
+ until brack.zero?
114
+ if part = @scanner.scan_until(scan_for)
115
+ body << part
116
+
117
+
118
+ if @scanner[1] == "}"
119
+ brack -= 1
120
+ elsif @scanner[1] == "{"
121
+ brack += 1
122
+ end
123
+ else
124
+ @scanner.scan(/(.+)/m)
125
+ error!
126
+ end
127
+ end
128
+
129
+ body.gsub(/\A\n*/, "").gsub(/\A\s*\{([\s\S]*)\}\z/, "\\1")
130
+ end
131
+
132
+ def _scan_arguments(ending, seperator)
133
+ arguments = []
134
+ until @scanner.scan(ending)
135
+ @scanner.scan(/(&?[A-Za-z0-9_-]+)/)
136
+ arguments << @scanner[1]
137
+ @scanner.scan(seperator) or @scanner.check(ending) or error!
138
+ end
139
+
140
+ arguments
141
+ end
142
+
143
+ def error!
144
+ p @tokens
145
+ raise SyntaxError, "Unexpected `#{@scanner.check(/./)}' on line #{line} (column #{column})"
146
+ end
147
+ end
148
+ end
149
+ end
data/lib/take/unit.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "take/unit/predict_match"
2
+ require "take/unit/ast"
3
+ require "take/unit/compiler"
4
+ require "take/unit/scanner"
5
+ require "take/unit/generator"
6
+
7
+ module Take
8
+
9
+ # A unit test. This is used to generate c files for tests.
10
+ class Unit
11
+
12
+ def create(file)
13
+ file = File.open(file, "r")
14
+ scanner = Scanner.new(file.read)
15
+ compiler = Compiler.new(file.path, scanner.scan)
16
+ generator = Generator.new(compiler.compile).generate
17
+ end
18
+
19
+ end
20
+ end
data/lib/take/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Take
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.0.2".freeze
3
3
  end
data/lib/take.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require "take/version"
2
+ require "take/unit"
3
+ require "take/project"
2
4
 
3
5
  module Take
4
6
  # Your code goes here...
data/take.gemspec CHANGED
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_dependency "virtus", "~> 1.0"
23
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: take
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Rodi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-31 00:00:00.000000000 Z
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: virtus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
41
55
  description: Manage your C projects better.
42
56
  email:
43
57
  - redjazz96@gmail.com
@@ -51,8 +65,20 @@ files:
51
65
  - README.md
52
66
  - Rakefile
53
67
  - lib/take.rb
54
- - lib/take/project.rb
55
- - lib/take/project/builder.rb
68
+ - lib/take/unit.rb
69
+ - lib/take/unit/ast.rb
70
+ - lib/take/unit/ast/after.rb
71
+ - lib/take/unit/ast/before.rb
72
+ - lib/take/unit/ast/block.rb
73
+ - lib/take/unit/ast/group.rb
74
+ - lib/take/unit/ast/node.rb
75
+ - lib/take/unit/ast/parent.rb
76
+ - lib/take/unit/ast/prefix.rb
77
+ - lib/take/unit/ast/source.rb
78
+ - lib/take/unit/compiler.rb
79
+ - lib/take/unit/generator.rb
80
+ - lib/take/unit/predict_match.rb
81
+ - lib/take/unit/scanner.rb
56
82
  - lib/take/version.rb
57
83
  - take.gemspec
58
84
  homepage: ''
File without changes
data/lib/take/project.rb DELETED
@@ -1,22 +0,0 @@
1
-
2
- module Take
3
-
4
- # Handles project information for a specific project. Tends to represent
5
- # an entire directory.
6
- class Project
7
-
8
- # The name of the project. This is normally guessed from the directory
9
- # name.
10
- #
11
- # @return [String]
12
- attr_accessor :name
13
-
14
- # Initialize the project.
15
- def initialize(name = nil, &block)
16
- raise ArgumentError, "Projects require blocks" unless block_given?
17
- @block = block
18
- @name = name
19
- end
20
-
21
- end
22
- end