loxxy 0.0.4 → 0.0.5

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
  SHA256:
3
- metadata.gz: f5383d6eb1725f5c53bb343e46d763f18d9d69f6b010241dbc4a93c18f949a6f
4
- data.tar.gz: 286f213ab01ebec8061a9f25c86c6f28be064891880e06942a0d6d86b4210fcb
3
+ metadata.gz: 5db00fee0e8e7ef89a48cacc4e9ad0baf7ae5ee2cb419ba76964199bd7552199
4
+ data.tar.gz: ddb8e9c7ac267f32bed3f77ada05a6af38a872b5f892452a496b17522b608977
5
5
  SHA512:
6
- metadata.gz: 32d447c7dbe6593ad0002ad383a917561c82da22cbf70b4102d0eaa389cf92196e03ee14ab1cc160f530b1c96a1e259db8e7923e2de81322fc854898fa306d49
7
- data.tar.gz: 245d4c9e255b7bb9d8602ab103367d7f83baf516db61f5a9192945ffa689027eb9f5f7a282e7052bca6b9e904cd6f6ed956d61ea949e02b7916f100033ebd9ec
6
+ metadata.gz: 44e0049b0bc01e5d35bed7b91c32a7a3b977e6ba4e806439958bad2dc8aae7ead017a310c8523bd4cb628c14951946981bee42f4001d68b701159fcdaff53419
7
+ data.tar.gz: c90236a82f0a4872b209b8462d5f13377815fd4fc41babf256ff4894ea6900e343c6f192194e1b713cb9f8a8d2bffc326e7ea4f00726193e0a792dc9e1457e41
@@ -1,6 +1,7 @@
1
1
  AllCops:
2
2
  Exclude:
3
3
  - 'exp/**/*'
4
+ - 'demo/**/*'
4
5
 
5
6
  Layout/ArgumentAlignment:
6
7
  Enabled: false
@@ -55,6 +56,9 @@ Layout/MultilineMethodCallBraceLayout:
55
56
 
56
57
  Layout/SpaceAroundOperators:
57
58
  Enabled: true
59
+
60
+ Layout/SpaceBeforeBrackets:
61
+ Enabled: true
58
62
 
59
63
  Layout/SpaceInsideParens:
60
64
  Enabled: true
@@ -70,6 +74,9 @@ Layout/TrailingEmptyLines:
70
74
 
71
75
  Layout/TrailingWhitespace:
72
76
  Enabled: true
77
+
78
+ Lint/AmbiguousAssignment:
79
+ Enabled: true
73
80
 
74
81
  Lint/DuplicateBranch:
75
82
  Enabled: true
@@ -226,6 +233,9 @@ Style/GuardClause:
226
233
 
227
234
  Style/HashEachMethods:
228
235
  Enabled: true
236
+
237
+ Style/HashExcept:
238
+ Enabled: true
229
239
 
230
240
  Style/HashTransformKeys:
231
241
  Enabled: true
@@ -0,0 +1,6 @@
1
+ --exclude examples --exclude features --exclude spec
2
+ --no-private
3
+ --markup markdown
4
+ -
5
+ CHANGELOG.md
6
+ LICENSE.txt
@@ -1,3 +1,10 @@
1
+ ## [0.0.5] - 2021-01-02
2
+ - Improved example in `README.md`, code re-styling to please `Rubocop` 1.7
3
+
4
+ ## Changed
5
+ - Code re-styling to please `Rubocop` 1.7
6
+ - File `README.md` Improved example with better parse tree visualization.
7
+
1
8
  ## [0.0.4] - 2021-01-01
2
9
  - A first parser implementation able to parse Lox source code.
3
10
 
data/README.md CHANGED
@@ -13,6 +13,8 @@ a simple language used in Bob Nystrom's online book [Crafting Interpreters](http
13
13
  - [DONE] Scanner (tokenizer)
14
14
  - [DONE] Raw parser. It parses Lox programs and generates a parse tree.
15
15
  - [TODO] Tailored parser for generating AST (Abstract Syntax Tree)
16
+ - [TODO] Custom AST builder class
17
+ - [TODO] Hierarchy classes for representing Lox expressions in AST
16
18
  - [TODO] Interpreter or transpiler
17
19
 
18
20
 
@@ -34,11 +36,45 @@ base_parser = Loxxy::FrontEnd::RawParser.new
34
36
  # Now parse the input into a concrete parse tree...
35
37
  ptree = base_parser.parse(lox_input)
36
38
 
37
- # Dump the parse tree contents...
38
- p ptree # Lengthy (unwieldy) output
39
+ # Display the parse tree thanks to Rley formatters...
40
+ visitor = Rley::ParseTreeVisitor.new(ptree)
41
+ tree_formatter = Rley::Formatter::Asciitree.new($stdout)
42
+ tree_formatter.render(visitor)
39
43
  ```
40
44
 
41
- Soon, the `loxxy`will host another, tailored parser, that will generate
45
+ This is the output produced by the above example:
46
+ ```
47
+ program
48
+ +-- declaration_star
49
+ | +-- declaration_star
50
+ | +-- declaration
51
+ | +-- statement
52
+ | +-- printStmt
53
+ | +-- PRINT: 'print'
54
+ | +-- expression
55
+ | | +-- assignment
56
+ | | +-- logic_or
57
+ | | +-- logic_and
58
+ | | | +-- equality
59
+ | | | | +-- comparison
60
+ | | | | | +-- term
61
+ | | | | | | +-- factor
62
+ | | | | | | | +-- unary
63
+ | | | | | | | | +-- call
64
+ | | | | | | | | +-- primary
65
+ | | | | | | | | | +-- STRING: '"Hello, world!"'
66
+ | | | | | | | | +-- refinement_star
67
+ | | | | | | | +-- multiplicative_star
68
+ | | | | | | +-- additive_star
69
+ | | | | | +-- comparisonTest_star
70
+ | | | | +-- equalityTest_star
71
+ | | | +-- conjunct_star
72
+ | | +-- disjunct_star
73
+ | +-- SEMICOLON: ';'
74
+ +-- EOF: ''
75
+ ```
76
+
77
+ Soon, the `loxxy` will host another, tailored parser, that will generate
42
78
  abstract syntax tree which much more convenient for further processing
43
79
  (like implementing an interpreter).
44
80
 
@@ -8,15 +8,14 @@ module Loxxy
8
8
  class BuiltinDatatype
9
9
  # @return [Object] The Ruby representation
10
10
  attr_reader :value
11
-
11
+
12
12
  # Constructor. Initialize a Lox value from one of its built-in data type.
13
13
  def initialize(aValue)
14
14
  @value = validated_value(aValue)
15
15
  end
16
-
17
-
16
+
18
17
  protected
19
-
18
+
20
19
  def validated_value(aValue)
21
20
  aValue
22
21
  end
@@ -8,13 +8,13 @@ module Loxxy
8
8
  # Class for representing a Lox false value.
9
9
  class False < Boolean
10
10
  include Singleton # Make a singleton class
11
-
11
+
12
12
  # Build the sole instance
13
13
  def initialize
14
14
  super(false)
15
15
  end
16
16
  end # class
17
-
18
- False.instance.freeze # Make the sole instance immutable
17
+
18
+ False.instance.freeze # Make the sole instance immutable
19
19
  end # module
20
20
  end # module
@@ -6,12 +6,6 @@ module Loxxy
6
6
  module Datatype
7
7
  # Class for representing a Lox string of characters value.
8
8
  class LXString < BuiltinDatatype
9
-
10
- # Build the sole instance
11
- def initialize(aValue)
12
- super(aValue)
13
- end
14
-
15
9
  # Compare a Lox String with another Lox (or genuine Ruby) String
16
10
  # @param other [Datatype::LxString, String]
17
11
  # @return [Boolean]
@@ -22,7 +16,8 @@ module Loxxy
22
16
  when String
23
17
  value == other
24
18
  else
25
- raise StandardError, 'Cannot compare a #{self.class} with #{other.class}'
19
+ err_msg = "Cannot compare a #{self.class} with #{other.class}"
20
+ raise StandardError, err_msg
26
21
  end
27
22
  end
28
23
 
@@ -34,8 +29,8 @@ module Loxxy
34
29
  end
35
30
 
36
31
  # Remove double quotes delimiter
37
- aValue.gsub(/(^")|("$)/, '')
32
+ aValue.gsub(/(^")|("$)/, '')
38
33
  end
39
34
  end # class
40
35
  end # module
41
- end # module
36
+ end # module
@@ -8,13 +8,13 @@ module Loxxy
8
8
  # Class for representing a Lox nil "value".
9
9
  class Nil < BuiltinDatatype
10
10
  include Singleton # Make a singleton class
11
-
11
+
12
12
  # Build the sole instance
13
13
  def initialize
14
14
  super(nil)
15
15
  end
16
16
  end # class
17
-
18
- Nil.instance.freeze # Make the sole instance immutable
17
+
18
+ Nil.instance.freeze # Make the sole instance immutable
19
19
  end # module
20
20
  end # module
@@ -6,19 +6,11 @@ module Loxxy
6
6
  module Datatype
7
7
  # Class for representing a Lox numeric value.
8
8
  class Number < BuiltinDatatype
9
-
10
- # Build the sole instance
11
- def initialize(aValue)
12
- super(aValue)
13
- end
14
-
15
9
  protected
16
10
 
17
11
  def validated_value(aValue)
18
12
  case aValue
19
- when Integer
20
- result = aValue
21
- when Numeric
13
+ when Integer, Numeric
22
14
  result = aValue
23
15
  when /^-?\d+$/
24
16
  result = aValue.to_i
@@ -32,4 +24,4 @@ module Loxxy
32
24
  end
33
25
  end # class
34
26
  end # module
35
- end # module
27
+ end # module
@@ -8,13 +8,13 @@ module Loxxy
8
8
  # Class for representing a Lox true value.
9
9
  class True < Boolean
10
10
  include Singleton # Make a singleton class
11
-
11
+
12
12
  # Build the sole instance
13
13
  def initialize
14
14
  super(true)
15
- end
15
+ end
16
16
  end # class
17
-
18
- True.instance.freeze # Make the sole instance immutable
17
+
18
+ True.instance.freeze # Make the sole instance immutable
19
19
  end # module
20
20
  end # module
@@ -131,7 +131,7 @@ module Loxxy
131
131
  rule('primary' => 'IDENTIFIER')
132
132
  rule('primary' => 'LEFT_PAREN expression RIGHT_PAREN')
133
133
  rule('primary' => 'SUPER DOT IDENTIFIER')
134
-
134
+
135
135
  # Utility rules
136
136
  rule('function' => 'IDENTIFIER LEFT_PAREN params_opt RIGHT_PAREN block')
137
137
  rule('params_opt' => 'parameters')
@@ -142,11 +142,10 @@ module Loxxy
142
142
  rule('arguments_opt' => [])
143
143
  rule('arguments' => 'arguments COMMA expression')
144
144
  rule('arguments' => 'expression')
145
-
146
145
  end
147
146
 
148
- # And now build the grammar and make it accessible via a constant
149
- # @return [Rley::Syntax::Grammar]
150
- Grammar = builder.grammar
147
+ # And now build the grammar and make it accessible via a constant
148
+ # @return [Rley::Syntax::Grammar]
149
+ Grammar = builder.grammar
151
150
  end # module
152
151
  end # module
@@ -14,7 +14,7 @@ module Loxxy
14
14
  # @param theLexeme [String] the lexeme (= piece of text from input)
15
15
  # @param aTerminal [Rley::Syntax::Terminal, String]
16
16
  # The terminal symbol corresponding to the lexeme.
17
- # @param aPosition [Rley::Lexical::Position] The position of lexeme
17
+ # @param aPosition [Rley::Lexical::Position] The position of lexeme
18
18
  # in input text.
19
19
  def initialize(aValue, aLexeme, aTerminal, aPosition)
20
20
  super(aLexeme, aTerminal, aPosition)
@@ -15,7 +15,7 @@ module Loxxy
15
15
  # A TerminalNode is leaf node, that is, it has no child node.
16
16
  # While concrete parse tree nodes can be generated out of the box,
17
17
  # they have the following drawbacks:
18
- # - Generic node classes that aren't always suited for the needs of
18
+ # - Generic node classes that aren't always suited for the needs of
19
19
  # the language being processing.
20
20
  # - Concrete parse tree tend to be deeply nested, which may complicate
21
21
  # further processing.
@@ -27,7 +27,6 @@ module Loxxy
27
27
  # Create a Rley facade object
28
28
  @engine = Rley::Engine.new do |cfg|
29
29
  cfg.diagnose = true
30
- # cfg.repr_builder = SkmBuilder
31
30
  end
32
31
 
33
32
  # Step 1. Load Lox grammar
@@ -52,4 +51,4 @@ module Loxxy
52
51
  end
53
52
  end # class
54
53
  end # module
55
- end # module
54
+ end # module
@@ -50,7 +50,7 @@ module Loxxy
50
50
  '>' => 'GREATER',
51
51
  '>=' => 'GREATER_EQUAL',
52
52
  '<' => 'LESS',
53
- '<=' => 'LESS_EQUAL',
53
+ '<=' => 'LESS_EQUAL'
54
54
  }.freeze
55
55
 
56
56
  # Here are all the implemented Lox keywords (in uppercase)
@@ -99,7 +99,7 @@ module Loxxy
99
99
 
100
100
  token = nil
101
101
 
102
- if "(){},.;/*".include? curr_ch
102
+ if '(){},.;/*'.include? curr_ch
103
103
  # Single delimiter or separator character
104
104
  token = build_token(@@lexeme2name[curr_ch], scanner.getch)
105
105
  elsif (lexeme = scanner.scan(/[+\-](?!\d)/))
@@ -150,7 +150,7 @@ module Loxxy
150
150
  when 'FALSE'
151
151
  value = Datatype::False.instance
152
152
  when 'NIL'
153
- value = Datatype::Nil.instance
153
+ value = Datatype::Nil.instance
154
154
  when 'NUMBER'
155
155
  value = Datatype::Number.new(aLexeme)
156
156
  when 'STRING'
@@ -167,8 +167,6 @@ module Loxxy
167
167
  # Skip non-significant whitespaces and comments.
168
168
  # Advance the scanner until something significant is found.
169
169
  def skip_intertoken_spaces
170
- pre_pos = scanner.pos
171
-
172
170
  loop do
173
171
  ws_found = scanner.skip(/[ \t\f]+/) ? true : false
174
172
  nl_found = scanner.skip(/(?:\r\n)|\r|\n/)
@@ -191,7 +189,7 @@ module Loxxy
191
189
  break unless ws_found || cmt_found
192
190
  end
193
191
 
194
- curr_pos = scanner.pos
192
+ scanner.pos
195
193
  end
196
194
 
197
195
  def skip_block_comment
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Loxxy
4
- VERSION = '0.0.4'
4
+ VERSION = '0.0.5'
5
5
  end
@@ -40,8 +40,8 @@ Gem::Specification.new do |spec|
40
40
  spec.version = Loxxy::VERSION
41
41
  spec.authors = ['Dimitri Geshef']
42
42
  spec.email = ['famished.tiger@yahoo.com']
43
- spec.summary = %q{An implementation of the Lox programming language. WIP}
44
- spec.description = %q{An implementation of the Lox programming language. WIP}
43
+ spec.summary = 'An implementation of the Lox programming language. WIP'
44
+ spec.description = 'An implementation of the Lox programming language. WIP'
45
45
  spec.homepage = 'https://github.com/famished-tiger/loxxy'
46
46
  spec.license = 'MIT'
47
47
  spec.required_ruby_version = '~> 2.4'
@@ -1,35 +1,35 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper' # Use the RSpec framework
4
-
5
- # Load the class under test
6
- require_relative '../../lib/loxxy/datatype/lx_string'
7
-
8
- module Loxxy
9
- module Datatype
10
- describe LXString do
11
- let(:sample_text) { 'some_text' }
12
- subject { LXString.new(sample_text) }
13
-
14
- context 'Initialization:' do
15
- it 'should accept a String value at initialization' do
16
- expect { LXString.new(sample_text) }.not_to raise_error
17
- end
18
-
19
- it 'should know its value' do
20
- expect(subject.value).to eq(sample_text)
21
- end
22
- end
23
-
24
- context 'Provided services:' do
25
- it 'compares with another string' do
26
- expect(subject).to eq(sample_text)
27
- expect(subject).to eq(LXString.new(sample_text.dup))
28
-
29
- expect(subject).not_to eq('')
30
- expect(subject).not_to eq('other-text')
31
- end
32
- end
33
- end # describe
34
- end # module
35
- end # module
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../spec_helper' # Use the RSpec framework
4
+
5
+ # Load the class under test
6
+ require_relative '../../lib/loxxy/datatype/lx_string'
7
+
8
+ module Loxxy
9
+ module Datatype
10
+ describe LXString do
11
+ let(:sample_text) { 'some_text' }
12
+ subject { LXString.new(sample_text) }
13
+
14
+ context 'Initialization:' do
15
+ it 'should accept a String value at initialization' do
16
+ expect { LXString.new(sample_text) }.not_to raise_error
17
+ end
18
+
19
+ it 'should know its value' do
20
+ expect(subject.value).to eq(sample_text)
21
+ end
22
+ end
23
+
24
+ context 'Provided services:' do
25
+ it 'compares with another string' do
26
+ expect(subject).to eq(sample_text)
27
+ expect(subject).to eq(LXString.new(sample_text.dup))
28
+
29
+ expect(subject).not_to eq('')
30
+ expect(subject).not_to eq('other-text')
31
+ end
32
+ end
33
+ end # describe
34
+ end # module
35
+ end # module
@@ -92,8 +92,10 @@ LOX_END
92
92
  expect(leaf_node.token.value).to eq('Hello, world!')
93
93
  expect(prnt_stmt.subnodes[2]).to be_kind_of(Rley::PTree::TerminalNode)
94
94
  expect(prnt_stmt.subnodes[2].symbol.name).to eq('SEMICOLON')
95
+ expect(eof).to be_kind_of(Rley::PTree::TerminalNode)
96
+ expect(eof.symbol.name).to eq('EOF')
95
97
  end
96
98
  end
97
99
  end # describe
98
100
  end # module
99
- end # module
101
+ end # module
@@ -78,7 +78,7 @@ module Loxxy
78
78
  end
79
79
 
80
80
  it 'should recognize non-datatype keywords' do
81
- keywords =<<-LOX_END
81
+ keywords = <<-LOX_END
82
82
  and class else fun for if or
83
83
  print return super this var while
84
84
  LOX_END
@@ -167,7 +167,7 @@ LOX_END
167
167
  end
168
168
 
169
169
  it 'should recognize string values' do
170
- input =<<-LOX_END
170
+ input = <<-LOX_END
171
171
  ""
172
172
  "string"
173
173
  "123"
@@ -3,7 +3,7 @@
3
3
  require_relative '../lib/loxxy/version/'
4
4
 
5
5
  RSpec.describe Loxxy do
6
- it "has a version number" do
6
+ it 'has a version number' do
7
7
  expect(Loxxy::VERSION).not_to be nil
8
8
  end
9
9
  end
@@ -1,9 +1,11 @@
1
- require "bundler/setup"
2
- require "loxxy"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'loxxy'
3
5
 
4
6
  RSpec.configure do |config|
5
7
  # Enable flags like --only-failures and --next-failure
6
- config.example_status_persistence_file_path = ".rspec_status"
8
+ config.example_status_persistence_file_path = '.rspec_status'
7
9
 
8
10
  config.expect_with :rspec do |c|
9
11
  # Disable the `should` syntax
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: loxxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitri Geshef
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-01 00:00:00.000000000 Z
11
+ date: 2021-01-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rley
@@ -77,6 +77,7 @@ files:
77
77
  - ".rspec"
78
78
  - ".rubocop.yml"
79
79
  - ".travis.yml"
80
+ - ".yardopts"
80
81
  - CHANGELOG.md
81
82
  - Gemfile
82
83
  - LICENSE.txt