lumb 0.1.0 → 0.2.0

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: 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
-