rakko 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 41b3dbeb8f6ae81b9c7ac6a260a652dbfdf26426
4
- data.tar.gz: e63bbd9c298fa5a8f8e6585022aaeb72531cf92d
3
+ metadata.gz: d3211f0c674ab78099d9cec919b29f26a69cd1d9
4
+ data.tar.gz: 045de341aec2ff82bc6cc5b0793b4d89ebab31cd
5
5
  SHA512:
6
- metadata.gz: 933f163d4de80a81e31faf0a09da5bb57c6ebed30a970df64bc8c335b44e3cd5fef7d5ab7a53d5302f7e710015c7fe5b253f838f861a8a15382ed9dc4027e600
7
- data.tar.gz: 53bab179c50f3b3ce74b3a251829bc0c5f1ff523c2c1de21d67358d4f3491a0f185c9def84d5f65de15f343b99ab3b85ee906de98d2427c27db2221c0a475d22
6
+ metadata.gz: 40f17518bf37127f109c24799cf8fe04407be5c06ff9977d4f042014531d63405a8488b55e76849b0fabc804f3d6fb4f8f83c4dcec203b791ce49121c96536fd
7
+ data.tar.gz: d6024fb9ecedcd2cbd7e4a653e90219121d0e263de027456a9ad7c6629d5daa1d37f1b36d5d8d91b25a0ebd1a6a4779730b6edf3d23880c9318e2240ed188fc0
@@ -0,0 +1 @@
1
+ -m markdown
@@ -0,0 +1,165 @@
1
+ require 'rakko/token'
2
+
3
+ module Rakko
4
+
5
+ # Hand-coded scanner which transforms a stream of
6
+ # characters into a stream of tokens in the Rakko language.
7
+ #
8
+ # ### Syntax
9
+ #
10
+ # Comment :: #.*\n
11
+ # Integer :: 0|[1-9][0-9]*
12
+ # Identifier :: [a-zA-Z_][0-9a-zA-Z_]*
13
+ # String :: "([^"]|\")*"
14
+ #
15
+ class Scanner
16
+ include Enumerable
17
+
18
+ attr_reader :lineno, :columnno
19
+
20
+ # @!attribute [r] lineno
21
+ # @return [Integer] The current line position pointed by the scanner (`0` base)
22
+ #
23
+ # @!attribute [r] columnno
24
+ # @return [Integer] The current column position pointed by the scanner (`0` base)
25
+
26
+ # Creates a new Scanner instance from `input` stream.
27
+ #
28
+ # The `input` parameter must be an instance of `String` or I/O object can respond to
29
+ # `#getc` method. If the `input` is an instance of `String`, it will be converted to
30
+ # an instance of `StringIO` internally.
31
+ #
32
+ # @param input [String, #getc] A stream of characters.
33
+ def initialize(input)
34
+ @nextc = nil
35
+
36
+ @columnno = 0
37
+ @lineno = 0
38
+
39
+ @input =
40
+ case input
41
+ when String
42
+ StringIO.new(input)
43
+ else
44
+ unless input.respond_to?(:getc)
45
+ raise ArgumentError, '`input` must be String or IO like object.'
46
+ else
47
+ input
48
+ end
49
+ end
50
+ end
51
+
52
+ # Reads the next token from the input stream.
53
+ #
54
+ # @return [Token] The token read, or `nil` if called at end of the input stream.
55
+ def next_token
56
+ # Read the first character if needed.
57
+ advance unless @nextc
58
+
59
+ loop do
60
+ line = self.lineno
61
+ column = self.columnno
62
+
63
+ return case @nextc
64
+ when nil # EOS
65
+ nil
66
+ when "\t", "\f", "\n", "\r", " " # Skip white spaces
67
+ advance
68
+ next
69
+ when '#' # Skip line comment
70
+ advance
71
+ until @nextc == "\n" || @nextc == nil
72
+ advance
73
+ end
74
+ redo
75
+ when "0"
76
+ # TODO octadecimal integer
77
+ # TODO hexadecimal integer
78
+ advance
79
+ Token.new(0, lineno: line, columnno: column)
80
+ when "1".."9" # decimal integer
81
+ n = @nextc.ord - "0".ord
82
+ loop do
83
+ advance
84
+ case @nextc
85
+ when "0".."9"
86
+ n = n * 10 + (@nextc.ord - "0".ord)
87
+ else
88
+ break Token.new(n, lineno: line, columnno: column)
89
+ end
90
+ end
91
+ when "a".."z", "A".."Z", "_" # identifier
92
+ name = @nextc
93
+ loop do
94
+ advance
95
+ case @nextc
96
+ when "0".."9", "a".."z", "A".."Z", "_"
97
+ name << @nextc
98
+ else
99
+ break Token.new(name.to_sym, lineno: line, columnno: column)
100
+ end
101
+ end
102
+ when "+", "-", "*", "/", "%", "=", ".", "!",
103
+ "(", ")", "[", "]", "{", "}" # operator
104
+ op = @nextc
105
+ advance
106
+ Token.new(op.to_sym, lineno: line, columnno: column)
107
+ when '"' # string
108
+ str = ''
109
+ loop do
110
+ advance
111
+ case @nextc
112
+ when nil
113
+ raise "Premature end of quoted string"
114
+ when '\\' # Escape sequence
115
+ advance
116
+ case @nextc
117
+ when 't'; str << "\t"
118
+ when 'n'; str << "\n"
119
+ when 'r'; str << "\r"
120
+ when 'f'; str << "\f"
121
+ when '\\'; str << "\\"
122
+ when '"'; str << "\""
123
+ when nil
124
+ raise "Premature end of escape sequence"
125
+ else
126
+ raise %Q{Unrecognized escape sequence: "\\#{@nextc}"}
127
+ end
128
+ when '"'
129
+ advance
130
+ break Token.new(str, lineno: line, columnno: column)
131
+ else
132
+ str << @nextc
133
+ end
134
+ end
135
+ else
136
+ raise "Unrecognized token"
137
+ end
138
+ end
139
+ end
140
+
141
+ def each(&block)
142
+ while t = next_token
143
+ block.yield(t)
144
+ end
145
+ end
146
+
147
+ private
148
+
149
+ def advance
150
+ # Update lineno and columnno of _next character_
151
+ if @nextc
152
+ if @nextc == $/
153
+ @lineno += 1
154
+ @columnno = 0
155
+ else
156
+ @columnno += 1
157
+ end
158
+ end
159
+
160
+ @nextc = @input.getc
161
+ end
162
+
163
+ end # Scanner
164
+
165
+ end
@@ -0,0 +1,35 @@
1
+ module Rakko
2
+
3
+ # `Token` is a terminal symbol in grammer context.
4
+ #
5
+ # Its `value` attribute represents token's value and its syntactic category.
6
+ # If `Token#value` is an instance of `Symbol`, its syntactic category is `Ident`.
7
+ class Token
8
+ attr_reader :lineno, :columnno, :value
9
+
10
+ # @!attribute [r] lineno
11
+ # @return [Integer] The line position of the token (`0` base).
12
+ #
13
+ # @!attribute [r] columnno
14
+ # @return [Integer] The column position of the token (`0` base).
15
+
16
+ # Creates a new Token instance.
17
+ #
18
+ # @param value token's value. If the value is `String`, it will be duplicated and frozen.
19
+ # @param columnno [Integer] The column number of token position. number is `0` based.
20
+ # @param lineno [Integer] The line number of token position. number is `0` based.
21
+ def initialize(value, columnno: 0, lineno: 0)
22
+ @columnno = columnno
23
+ @lineno = lineno
24
+ @value =
25
+ case value
26
+ when String
27
+ value.dup.freeze
28
+ else
29
+ value
30
+ end
31
+ end
32
+
33
+ end # Token
34
+
35
+ end
@@ -1,3 +1,3 @@
1
1
  module Rakko
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -4,25 +4,28 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'rakko/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "rakko"
7
+ spec.name = 'rakko'
8
8
  spec.version = Rakko::VERSION
9
- spec.authors = ["Takanori Ishikawa"]
10
- spec.email = ["takanori.ishikawa@gmail.com"]
9
+ spec.authors = ['Takanori Ishikawa']
10
+ spec.email = ['takanori.ishikawa@gmail.com']
11
11
 
12
12
  spec.summary = %q{A toy language.}
13
- spec.description = %q{Writing my own homebrew toy programming language to learn compiler technology.}
14
- spec.homepage = "https://github.com/ishikawa/rakko"
15
- spec.license = "MIT"
13
+ spec.description = %q{Writing my own homebrew toy programming language to learn about compiler construction.}
14
+ spec.homepage = 'https://github.com/ishikawa/rakko'
15
+ spec.license = 'MIT'
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
18
  f.match(%r{^(test|spec|features)/})
19
19
  end
20
- spec.bindir = "exe"
20
+ spec.bindir = 'exe'
21
21
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
22
+ spec.require_paths = ['lib']
23
23
 
24
- spec.add_development_dependency "bundler", "~> 1.13"
25
- spec.add_development_dependency "rake", "~> 10.0"
26
- spec.add_development_dependency "minitest", "~> 5.0"
27
- spec.add_development_dependency "yard", "~> 0.9.5"
24
+ spec.required_ruby_version = '>= 2.4.0'
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.13'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'minitest', '~> 5.0'
29
+ spec.add_development_dependency 'minitest-spec-context', '~> 0.0.3'
30
+ spec.add_development_dependency 'yard', '~> 0.9.5'
28
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rakko
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takanori Ishikawa
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-01-02 00:00:00.000000000 Z
11
+ date: 2017-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '5.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: minitest-spec-context
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.0.3
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.0.3
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: yard
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +80,8 @@ dependencies:
66
80
  - - "~>"
67
81
  - !ruby/object:Gem::Version
68
82
  version: 0.9.5
69
- description: Writing my own homebrew toy programming language to learn compiler technology.
83
+ description: Writing my own homebrew toy programming language to learn about compiler
84
+ construction.
70
85
  email:
71
86
  - takanori.ishikawa@gmail.com
72
87
  executables:
@@ -77,6 +92,7 @@ files:
77
92
  - ".gitignore"
78
93
  - ".ruby-version"
79
94
  - ".travis.yml"
95
+ - ".yardopts"
80
96
  - Gemfile
81
97
  - LICENSE.txt
82
98
  - README.md
@@ -85,6 +101,8 @@ files:
85
101
  - bin/setup
86
102
  - exe/rakko
87
103
  - lib/rakko.rb
104
+ - lib/rakko/scanner.rb
105
+ - lib/rakko/token.rb
88
106
  - lib/rakko/version.rb
89
107
  - rakko.gemspec
90
108
  homepage: https://github.com/ishikawa/rakko
@@ -99,7 +117,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
99
117
  requirements:
100
118
  - - ">="
101
119
  - !ruby/object:Gem::Version
102
- version: '0'
120
+ version: 2.4.0
103
121
  required_rubygems_version: !ruby/object:Gem::Requirement
104
122
  requirements:
105
123
  - - ">="