lumb 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: d04469fb5b0430d7325228a3328c35e22f4135d7
4
- data.tar.gz: 57278168ccc84c5b95e644819de2d64b53053c2e
3
+ metadata.gz: 902575b84bd52419a99e856ea05a00ab9e4f652f
4
+ data.tar.gz: ec05125ec3a9349bdd68d8a83314d0d1ed85035d
5
5
  SHA512:
6
- metadata.gz: e36397b790b4292e8b17b7b5d76b5ec5f9a68a5cf5879df3dd10eef6ab20b885eacca7d9844b2eb555063024a1af16f65a3f8950a79213b15a0c7dfc42eb2993
7
- data.tar.gz: d7df30d72062ae9b332def6994e07603eb8ec9328539f417eae298266f36b194fcb2be96b8fbafb3ffe8f40ed9093a2eb8371603a491691d4f1a2351cce9f68e
6
+ metadata.gz: 691e0ca905584e8b8be064f185100382fe0e05fa9cf7183679ab5c4985599d7c04dce9f7b55129a6997db92d95761e6dfc05ef2bb0a4fb5a682a22c389f3fddd
7
+ data.tar.gz: 4a7b70db605483b2124e9e5ac124734d0b69aab491792d5b8b813839dfe311dac9127f9890ff6c12471a3539c83046d0df14ec89be939ef10959703e408f365c
@@ -1,124 +1,9 @@
1
- require 'parslet'
1
+ require 'lumb/table'
2
+ require 'lumb/structure'
3
+ require 'lumb/entry'
4
+ require 'lumb/value'
5
+ require 'lumb/parser'
2
6
 
3
7
  module Lumb
4
- class Parser < Parslet::Parser
5
- rule(:newlines) { match['\r\n'].repeat(1) }
6
- rule(:space) { match[' \t\r\n'].repeat(1) }
7
- rule(:hspace) { match[' \t'].repeat(1) }
8
- rule(:delim_space) { hspace | newlines.present? }
9
-
10
- rule(:identifier) { match['a-z'] >> match['a-z0-9_-'].repeat }
11
- rule(:type) { match['A-Z'] >> match['a-z'].repeat }
12
- rule(:number) { match['0-9'].repeat(1) }
13
-
14
- rule(:struct_item) {
15
- identifier.as(:field) >>
16
- str('=') >>
17
- type.as(:type) >>
18
- delim_space.as(:ws)
19
- }
20
-
21
- rule(:entry_item) {
22
- identifier.as(:field) >>
23
- str('=') >>
24
- number.as(:value) >>
25
- delim_space.as(:ws)
26
- }
27
-
28
- rule(:struct) {
29
- struct_item.repeat(1).as(:items) >>
30
- newlines.as(:ws)
31
- }
32
-
33
- rule(:entry) {
34
- entry_item.repeat(1).as(:items) >>
35
- newlines.as(:ws)
36
- }
37
-
38
- rule(:file) {
39
- space.maybe.as(:ws_pre) >>
40
- struct.as(:struct) >>
41
- space.maybe.as(:ws_mid) >>
42
- entry.repeat.as(:entries) >>
43
- space.maybe.as(:ws_post)
44
- }
45
-
46
- root(:file)
47
- end
48
-
49
- class Transform < Parslet::Transform
50
- rule(:field => simple(:field), :type => simple(:type), :ws => simple(:ws)) {
51
- StructItem.new(field, type, ws)
52
- }
53
- rule(:field => simple(:field), :value => simple(:value), :ws => simple(:ws)) {
54
- EntryItem.new(field, value, ws)
55
- }
56
- rule(:items => sequence(:items), :ws => simple(:ws)) {
57
- if items.first.is_a? StructItem
58
- LogStruct.new(items, ws)
59
- else
60
- LogEntry.new(items, ws)
61
- end
62
- }
63
- rule(:ws_pre => simple(:ws_pre), :struct => simple(:struct), :ws_mid => simple(:ws_mid), :entries => sequence(:entries), :ws_post => simple(:ws_post)) {
64
- LogFile.new(struct, entries, ws_pre, ws_mid, ws_post)
65
- }
66
- end
67
-
68
- class StructItem
69
- def initialize(field, type, ws)
70
- @field, @type, @ws = field, type, ws
71
- end
72
-
73
- def to_s
74
- "#{@field}=#{@type}#{@ws}"
75
- end
76
- end
77
-
78
- class EntryItem
79
- def initialize(field, value, ws)
80
- @field, @value, @ws = field, value, ws
81
- end
82
-
83
- def to_s
84
- "#{@field}=#{@value}#{@ws}"
85
- end
86
- end
87
-
88
- class LogStruct
89
- def initialize(items, ws)
90
- @items, @ws = items, ws
91
- end
92
-
93
- def to_s
94
- "#{@items.join}#{@ws}"
95
- end
96
- end
97
-
98
- class LogEntry
99
- def initialize(items, ws)
100
- @items, @ws = items, ws
101
- end
102
-
103
- def to_s
104
- "#{@items.join}#{@ws}"
105
- end
106
- end
107
-
108
- class LogFile
109
- def initialize(struct, entries, ws_pre, ws_mid, ws_post)
110
- @struct, @entries, @ws_pre, @ws_mid, @ws_post = struct, entries, ws_pre, ws_mid, ws_post
111
- end
112
-
113
- def to_s
114
- "#{@ws_pre}#{@struct}#{@ws_mid}#{@entries.join}#{@ws_post}"
115
- end
116
- end
117
-
118
- def self.parse(str)
119
- Transform.new.apply(Parser.new.parse(str))
120
- rescue Parslet::ParseFailed => failure
121
- puts failure.cause.ascii_tree
122
- end
123
8
  end
124
9
 
@@ -0,0 +1,35 @@
1
+ module Lumb
2
+ class Entry
3
+ attr_reader :items, :ws
4
+
5
+ def initialize(structure, items, ws)
6
+ @structure, @items, @ws = structure, items, ws
7
+
8
+ @slots = []
9
+ @items.each do |item|
10
+ @slots[@structure.slot_index(item.slot)] = item.value
11
+ end
12
+
13
+ @structure.items.each.with_index do |item, idx|
14
+ if @slots[idx].nil?
15
+ raise "slot '#{item.slot}' is missing from entry"
16
+ elsif @slots[idx].type != item.type
17
+ raise "type mismatch: expected '#{item.type}', got '#{@slots[idx].type}'"
18
+ end
19
+ end
20
+ end
21
+
22
+ def slot(name)
23
+ @slots[@structure.slot_index(name)]
24
+ end
25
+ end
26
+
27
+ class EntryItem
28
+ attr_reader :slot, :value, :ws
29
+
30
+ def initialize(slot, value, ws)
31
+ @slot, @value, @ws = slot.to_sym, value, ws
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,98 @@
1
+ require 'parslet'
2
+
3
+ module Lumb
4
+ class Parser < Parslet::Parser
5
+ rule(:newlines) { match['\r\n'].repeat(1) }
6
+ rule(:space) { match[' \t\r\n'].repeat(1) }
7
+ rule(:hspace) { match[' \t'].repeat(1) }
8
+ rule(:delim_space) { hspace | newlines.present? }
9
+
10
+ rule(:slot) { match['a-z'] >> match['a-zA-Z0-9_-'].repeat }
11
+ rule(:type) { match['A-Z'] >> match['a-z'].repeat }
12
+ rule(:number) { (match['+-'].maybe >> match['0-9'].repeat(1)).as(:number) }
13
+ rule(:symbol) { (str(':') >> match['\S'].repeat(1)).as(:symbol) }
14
+ rule(:date) {
15
+ (match['0-9'].repeat(4, 4) >>
16
+ str('-') >>
17
+ match['0-9'].repeat(2, 2) >>
18
+ str('-') >>
19
+ match['0-9'].repeat(2, 2)).as(:date)
20
+ }
21
+
22
+ rule(:value) {
23
+ date | number | symbol
24
+ }
25
+
26
+ rule(:struct_item) {
27
+ slot.as(:slot) >>
28
+ str('=') >>
29
+ type.as(:type) >>
30
+ delim_space.as(:ws)
31
+ }
32
+
33
+ rule(:entry_item) {
34
+ slot.as(:slot) >>
35
+ str('=') >>
36
+ value.as(:value) >>
37
+ delim_space.as(:ws)
38
+ }
39
+
40
+ rule(:struct) {
41
+ struct_item.repeat(1).as(:items) >>
42
+ newlines.as(:ws)
43
+ }
44
+
45
+ rule(:entry) {
46
+ entry_item.repeat(1).as(:items) >>
47
+ newlines.as(:ws)
48
+ }
49
+
50
+ rule(:table) {
51
+ space.maybe.as(:ws_pre) >>
52
+ struct.as(:struct) >>
53
+ space.maybe.as(:ws_mid) >>
54
+ entry.repeat.as(:entries) >>
55
+ space.maybe.as(:ws_post)
56
+ }
57
+
58
+ root(:table)
59
+ end
60
+
61
+ class Transform < Parslet::Transform
62
+ rule(:number => simple(:number)) {
63
+ Value.new(:Num, number)
64
+ }
65
+ rule(:symbol => simple(:symbol)) {
66
+ Value.new(:Sym, symbol)
67
+ }
68
+ rule(:date => simple(:date)) {
69
+ Value.new(:Date, date)
70
+ }
71
+ rule(:slot => simple(:slot), :type => simple(:type), :ws => simple(:ws)) {
72
+ StructureItem.new(slot, type, ws)
73
+ }
74
+ rule(:slot => simple(:slot), :value => simple(:value), :ws => simple(:ws)) {
75
+ EntryItem.new(slot, value, ws)
76
+ }
77
+ rule(:items => sequence(:items), :ws => simple(:ws)) { |dict|
78
+ items, ws = dict[:items], dict[:ws]
79
+
80
+ if items.first.is_a? StructureItem
81
+ @structure = Structure.new(items, ws)
82
+ else
83
+ Entry.new(@structure, items, ws)
84
+ end
85
+ }
86
+ rule(:ws_pre => simple(:ws_pre), :struct => simple(:struct), :ws_mid => simple(:ws_mid), :entries => sequence(:entries), :ws_post => simple(:ws_post)) {
87
+ Table.new(struct, entries, ws_pre, ws_mid, ws_post)
88
+ }
89
+ end
90
+
91
+ def self.parse(str)
92
+ Transform.new.apply(Parser.new.parse(str))
93
+ rescue Parslet::ParseFailed => failure
94
+ puts failure.cause.ascii_tree
95
+ raise
96
+ end
97
+ end
98
+
@@ -0,0 +1,36 @@
1
+ module Lumb
2
+ class Structure
3
+ attr_reader :items, :ws
4
+
5
+ def initialize(items, ws)
6
+ @items, @ws = items, ws
7
+
8
+ @slots = {}
9
+ @items.map.with_index do |item, idx|
10
+ @slots[item.slot] = idx
11
+ end
12
+ end
13
+
14
+ def slot_index(name)
15
+ @slots[name.to_sym]
16
+ end
17
+
18
+ def slot_type(name_or_index)
19
+ name_or_index = slot_index(name_or_index) unless name_or_index.is_a? Fixnum
20
+ @items[name_or_index].type
21
+ end
22
+ end
23
+
24
+ class StructureItem
25
+ attr_reader :slot, :type, :ws
26
+
27
+ def initialize(slot, type, ws)
28
+ @slot, @type, @ws = slot.to_sym, type.to_sym, ws
29
+
30
+ if not [:Num, :Sym, :Date].include? @type
31
+ raise "unrecognized type #{@type}"
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -0,0 +1,4 @@
1
+ module Lumb
2
+ Table = Struct.new(:structure, :entries, :ws_pre, :ws_mid, :ws_post)
3
+ end
4
+
@@ -0,0 +1,23 @@
1
+ require 'date'
2
+
3
+ module Lumb
4
+ class Value
5
+ attr_reader :type, :value, :raw
6
+
7
+ def initialize(type, raw)
8
+ @type = type
9
+ @value = nil
10
+ @raw = raw
11
+
12
+ case @type
13
+ when :Num
14
+ @value = @raw.to_i
15
+ when :Sym
16
+ @value = @raw.to_s[1..-1].to_sym
17
+ when :Date
18
+ @value = Date.parse(@raw)
19
+ end
20
+ end
21
+ end
22
+ end
23
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lumb
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
  - Jeremy Ruten
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-21 00:00:00.000000000 Z
11
+ date: 2016-09-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -26,13 +26,16 @@ dependencies:
26
26
  version: '1.7'
27
27
  description:
28
28
  email: jeremy.ruten@gmail.com
29
- executables:
30
- - lumb
29
+ executables: []
31
30
  extensions: []
32
31
  extra_rdoc_files: []
33
32
  files:
34
- - bin/lumb
35
33
  - lib/lumb.rb
34
+ - lib/lumb/entry.rb
35
+ - lib/lumb/parser.rb
36
+ - lib/lumb/structure.rb
37
+ - lib/lumb/table.rb
38
+ - lib/lumb/value.rb
36
39
  homepage: https://github.com/yjerem/lumb
37
40
  licenses:
38
41
  - MIT
data/bin/lumb DELETED
@@ -1,6 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'lumb'
4
-
5
- print Lumb.parse(File.read(ARGV.first)).to_s
6
-