ast_ast 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
22
+ doc/
23
+ cov/
24
+ .yardoc/
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Joshua Hawxwell
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,51 @@
1
+ # AstAst
2
+
3
+
4
+ sSSSSs
5
+ saaAAA Tttttts
6
+ sa tT t TT tt
7
+ saaaaaaA t tT t TT Ts
8
+ sa tt T tT t TT Ts
9
+ AaaaaaaAaaaaAAt TsssssTs
10
+ tT t tSTSsssSTt tt
11
+ t tt t tt
12
+ /t tt /t tt
13
+ ( t tt ( t tt
14
+ \t tt \t tt
15
+ t tt t tt
16
+ t tt\ t tts
17
+ S tS.`. S tS ss
18
+ tsssst-' tsssstSSS
19
+
20
+
21
+
22
+
23
+ __VERY IMPORTANT:__ it is probably a very bad idea to use this in something that relies on it. It will change without warning!
24
+
25
+ ## Goals/Ideas
26
+
27
+ Crazy simple string -> token converting, using regular expression rules and optional blocks. Some of the finer points of this still need working out, mainly should you be able to affect the name of the token within the block.
28
+
29
+ class MyTokeniser < Ast::Tokeniser
30
+ rule :long, /--[a-zA-Z0-9]+/
31
+ rule :short, /-[a-zA-Z0-9]+/
32
+ rule :word, /[a-zA-Z0-9]+/
33
+ end
34
+ input = "--along -sh aword"
35
+ MyTokeniser.tokenise(input)
36
+ #=> #<Ast::Tokens [[:long, "--along"], [:short, "-sh"], [:word, "aword"]]>
37
+
38
+ # Use blocks to change results, passes matches
39
+ class MyTokeniser < Ast::Tokeniser
40
+ rule :long, /--([a-zA-Z0-9]+)/ {|i| i[1]}
41
+ rule :short, /-([a-zA-Z0-9]+)/ {|i| i[1].split} # creates an array so splits into multiple tokens
42
+ rule :word, /[a-zA-Z0-9]+/
43
+ end
44
+ input = "--along -sh aword"
45
+ MyTokeniser.tokenise(input)
46
+ #=> #<Ast::Tokens [[:long, "along"], [:short, "s"], [:short, "h"], [:word, "aword"]]>
47
+
48
+
49
+ ## Copyright
50
+
51
+ Copyright (c) 2010 Joshua Hawxwell. See LICENSE for details.
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "ast_ast"
8
+ gem.summary = %Q{String -> Tokens -> AST}
9
+ gem.description = %Q{Easily convert strings to Tokens and then on to an Abstract Syntax Tree easily. (Very far from finished!)}
10
+ gem.email = "m@hawx.me"
11
+ gem.homepage = "http://github.com/hawx/ast_ast"
12
+ gem.authors = ["Joshua Hawxwell"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_development_dependency "yard", ">= 0"
15
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ begin
47
+ require 'yard'
48
+ YARD::Rake::YardocTask.new
49
+ rescue LoadError
50
+ task :yardoc do
51
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
52
+ end
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,10 @@
1
+ # Loads everything
2
+ $:.unshift File.dirname(__FILE__)
3
+
4
+ require 'strscan'
5
+
6
+ require 'ast_ast/ast'
7
+ require 'ast_ast/tree'
8
+ require 'ast_ast/tokeniser'
9
+ require 'ast_ast/tokens'
10
+ require 'ast_ast/token'
@@ -0,0 +1,5 @@
1
+ module Ast
2
+ class Ast
3
+
4
+ end
5
+ end
@@ -0,0 +1,35 @@
1
+ module Ast
2
+ class Token
3
+ attr_accessor :type, :value
4
+
5
+ def initialize(type, value)
6
+ @type = type.to_sym
7
+ @value = value
8
+ end
9
+
10
+ # Check whether an array given is valid, ie. it has a symbol
11
+ # then an object only.
12
+ #
13
+ # @example
14
+ #
15
+ # Ast::Token.valid? [:type, 'val'] #=> true
16
+ # Ast::Token.valid? ['wrong', 'val'] #=> false
17
+ # Ast::Token.valid? ['too', 'long', 1] #=> false
18
+ #
19
+ def self.valid?(arr)
20
+ if arr.is_a? Array
21
+ if arr.nil? || arr.size != 2
22
+ return false
23
+ elsif !arr[0].is_a?(Symbol)
24
+ return false
25
+ else
26
+ return true
27
+ end
28
+ elsif arr.is_a? Ast::Token
29
+ return true
30
+ else
31
+ return false
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,95 @@
1
+ # @abstract
2
+ module Ast
3
+ class Tokeniser
4
+ attr_accessor :rules, :scanner
5
+
6
+ # Describes a single rule created within the Ast::Tokeniser subclass
7
+ class Rule
8
+ attr_accessor :name, :regex, :block
9
+
10
+ # Creates a new Rule instance
11
+ #
12
+ # @param [Symbol] name name of the token to be created
13
+ # @param [Regexp] regex regular expression to be matched
14
+ # @param [Proc] block optional block to be executed with match(es)
15
+ def initialize(name, regex, &block)
16
+ @name = name
17
+ @regex = regex
18
+ @block = block || Proc.new {|i| i}
19
+ end
20
+
21
+ # Runs the block that was given using either, the full match if there
22
+ # were no captures in the regex, or an array of the captures.
23
+ #
24
+ # If a String is returned, which will be the case most of the time, a
25
+ # single token is created with the value that is returned. But if an
26
+ # Array is returned then multiple tokens will be created for each item
27
+ # in the Array. See the examples for a better explanation.
28
+ #
29
+ # @param [String] val the string that was matched to +@regex+
30
+ # @return [String, Array]
31
+ #
32
+ # @example Single tokens created (returns String)
33
+ #
34
+ # class Klass < Ast::Tokeniser
35
+ # rule(:word, /[a-z]+/) {|i| i.reverse}
36
+ # end
37
+ #
38
+ # Klass.tokenise("backwards sdrawrof")
39
+ # #=> [[:word, "sdrawkcab"], [:word, "forwards"]]
40
+ #
41
+ # @example Multiple tokens created (returns Array)
42
+ #
43
+ # class Klass < Ast::Tokeniser
44
+ # rule(:letter, /[a-z]+/) {|i| i.split('')}
45
+ # end
46
+ #
47
+ # Klass.tokenise("split up")
48
+ # #=> [[:letter, "s"], [:letter, "p"], [:letter, "l"], [:letter, "i"], [:letter, "t"], [:letter, "u"], [:letter, "p"]]
49
+ #
50
+ #
51
+ def run(val)
52
+ arr = val.match(@regex).to_a
53
+ val = arr unless arr.empty?
54
+ val = arr[0] if arr.size == 1
55
+ @block.call val
56
+ end
57
+ end
58
+
59
+ # Creates a new Rule and adds to the +@rules+ list.
60
+ # @see Ast::Tokeniser::Rule#initialize
61
+ def self.rule(name, regex, &block)
62
+ @rules ||= []
63
+ @rules << Rule.new(name, regex, &block)
64
+ end
65
+
66
+ # Takes the input and uses the rules that were created to scan it.
67
+ #
68
+ # @param [String] input string to scan
69
+ # @return [Array]
70
+ def self.tokenise(input)
71
+ @scanner = StringScanner.new(input)
72
+
73
+ result = []
74
+ until @scanner.eos?
75
+ @rules.each do |i|
76
+ a = @scanner.scan(i.regex)
77
+ unless a.nil?
78
+ ran = i.run(a)
79
+ # split array into separate tokens, *not* values
80
+ if ran.is_a? Array
81
+ ran.each {|a| result << [i.name, a]}
82
+ else
83
+ result << [i.name, ran]
84
+ end
85
+ end
86
+ end
87
+ # obviously no rule matches this so ignore it
88
+ # could add verbose mode where this throws an exception!
89
+ @scanner.pos += 1 unless @scanner.eos?
90
+ end
91
+ result
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,69 @@
1
+ module Ast
2
+ class Tokens < Array
3
+
4
+ def <<(val)
5
+ raise "value given #{val} is invalid" unless Ast::Token.valid?(val)
6
+ if val.is_a? Array
7
+ self << Ast::Token.new(val[0], val[1])
8
+ else
9
+ super
10
+ end
11
+ end
12
+
13
+ # @group Enumeration
14
+
15
+ alias_method :_each, :each
16
+ # Loops through the types and contents of each tag separately, passing them
17
+ # to the block given.
18
+ #
19
+ # @return [Ast::Tokens] returns self
20
+ # @yield [Symbol, Object] gives the type and content of each block in turn
21
+ #
22
+ # @example
23
+ #
24
+ # tokens = Ast::Tokens.new
25
+ # tokens << [:a, 1] << [:b, 2] << [:c, 3] << [:d, 4]
26
+ #
27
+ # sa.each do |t, v|
28
+ # puts "#{t} -> #{v}"
29
+ # end
30
+ # #=> a -> 1
31
+ # #=> b -> 2
32
+ # #=> c -> 3
33
+ # #=> d -> 4
34
+ #
35
+ def each(&blck)
36
+ self._each do |i|
37
+ yield(i.type, i.value)
38
+ end
39
+ self
40
+ end
41
+
42
+ # Evalute block given for the type of each token
43
+ # @see #each
44
+ def each_type(&blck)
45
+ self._each do |i|
46
+ yield(i.type)
47
+ end
48
+ end
49
+
50
+ # Evaluate block given for the value of each token
51
+ # @see each
52
+ def each_value(&blck)
53
+ self._each do |i|
54
+ yield(i.value)
55
+ end
56
+ end
57
+
58
+ # Evaluate block given for each token instance
59
+ # @see each
60
+ def each_token(&blck)
61
+ self._each do |i|
62
+ yield(i)
63
+ end
64
+ end
65
+
66
+ # @endgroup
67
+
68
+ end
69
+ end
@@ -0,0 +1,5 @@
1
+ module Ast
2
+ class Tree
3
+
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ # Loads only token stuff
2
+ $:.unshift File.dirname(__FILE__)
3
+
4
+ require 'strscan'
5
+
6
+ require 'ast_ast/tokeniser'
7
+ require 'ast_ast/tokens'
8
+ require 'ast_ast/token'
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'ast_ast'
8
+
9
+ class Test::Unit::TestCase
10
+ end
@@ -0,0 +1,5 @@
1
+ require 'helper'
2
+
3
+ class TestAstAst < Test::Unit::TestCase
4
+
5
+ end
@@ -0,0 +1,13 @@
1
+ require 'helper'
2
+
3
+ class TestTokeniser < Test::Unit::TestCase
4
+ context "When trying examples" do
5
+ should "run first" do
6
+ class Klass < Ast::Tokeniser
7
+ rule(:word, /[a-z]+/) {|i| i.reverse}
8
+ end
9
+ result = [[:word, "sdrawkcab"], [:word, "forwards"]]
10
+ assert_equal result, Klass.tokenise("backwards sdrawrof")
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,112 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ast_ast
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Joshua Hawxwell
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-28 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: thoughtbot-shoulda
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :development
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: yard
37
+ prerelease: false
38
+ requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ hash: 3
44
+ segments:
45
+ - 0
46
+ version: "0"
47
+ type: :development
48
+ version_requirements: *id002
49
+ description: Easily convert strings to Tokens and then on to an Abstract Syntax Tree easily. (Very far from finished!)
50
+ email: m@hawx.me
51
+ executables: []
52
+
53
+ extensions: []
54
+
55
+ extra_rdoc_files:
56
+ - LICENSE
57
+ - README.md
58
+ files:
59
+ - .document
60
+ - .gitignore
61
+ - LICENSE
62
+ - README.md
63
+ - Rakefile
64
+ - VERSION
65
+ - lib/ast_ast.rb
66
+ - lib/ast_ast/ast.rb
67
+ - lib/ast_ast/token.rb
68
+ - lib/ast_ast/tokeniser.rb
69
+ - lib/ast_ast/tokens.rb
70
+ - lib/ast_ast/tree.rb
71
+ - lib/ast_tokens.rb
72
+ - test/helper.rb
73
+ - test/test_ast_ast.rb
74
+ - test/test_tokeniser.rb
75
+ has_rdoc: true
76
+ homepage: http://github.com/hawx/ast_ast
77
+ licenses: []
78
+
79
+ post_install_message:
80
+ rdoc_options:
81
+ - --charset=UTF-8
82
+ require_paths:
83
+ - lib
84
+ required_ruby_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ required_rubygems_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ hash: 3
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ requirements: []
103
+
104
+ rubyforge_project:
105
+ rubygems_version: 1.3.7
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: String -> Tokens -> AST
109
+ test_files:
110
+ - test/helper.rb
111
+ - test/test_ast_ast.rb
112
+ - test/test_tokeniser.rb