automotive-ecu 0.2.0 → 0.2.2
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 +4 -4
- data/bin/sandbox +16 -0
- data/lib/ecu/combined_list.rb +9 -0
- data/lib/ecu/interfaces/dcm/dcm_parser.rb +5 -5
- data/lib/ecu/interfaces/dcm/label_list.rb +7 -0
- data/lib/ecu/interfaces/json/label_list.rb +9 -0
- data/lib/ecu/interfaces/lab/combined_list.rb +1 -1
- data/lib/ecu/interfaces/lab/lab_lexer.rb +57 -0
- data/lib/ecu/interfaces/lab/lab_parser.rb +119 -48
- data/lib/ecu/interfaces/lab/lab_parser_error.rb +38 -0
- data/lib/ecu/interfaces/lab/label.rb +0 -14
- data/lib/ecu/interfaces/lab/label_list.rb +1 -1
- data/lib/ecu/interfaces/lab/signal.rb +0 -8
- data/lib/ecu/interfaces/lab/signal_list.rb +1 -1
- data/lib/ecu/labels/label_list.rb +1 -0
- data/lib/ecu/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75ae19b7bbf77cd45e42cc9e6b5138d19e85101df900fe844e3102bf18ac2c79
|
4
|
+
data.tar.gz: ecbc4929534d9245169ca0eaa7518df4fb18a08727b66244f4b6382a053af827
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff02d2b04386b8129d249be984934bcda8d53bd5f24057541f36c555152cbda2b008ac9ee1d4bdfec90d67fdcbc2c0455c0eaac2d5df524f44b857d21cad0cf2
|
7
|
+
data.tar.gz: fef42ccdfe5947851955aad5fc2655cabd047576268310da2cc1b6606e3c4390f6db91907a21b24710140149dfafd8b74670ac2aa701009a9ba8c9f4625d872b
|
data/bin/sandbox
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative "../lib/ecu/combined_list"
|
4
|
+
|
5
|
+
begin
|
6
|
+
list = Ecu::CombinedList.from_file('spec/fixtures/lab/advanced.lab')
|
7
|
+
list.labels.each do |item|
|
8
|
+
puts item
|
9
|
+
end
|
10
|
+
list.signals.each do |item|
|
11
|
+
puts item.description
|
12
|
+
end
|
13
|
+
rescue Ecu::LabParserError => e
|
14
|
+
puts e.message
|
15
|
+
puts e.context
|
16
|
+
end
|
data/lib/ecu/combined_list.rb
CHANGED
@@ -6,6 +6,15 @@ require_relative "interfaces/lab/combined_list"
|
|
6
6
|
class Ecu
|
7
7
|
class CombinedList
|
8
8
|
|
9
|
+
def self.from_file(file_path)
|
10
|
+
case File.extname(file_path)
|
11
|
+
when ".lab" then self.from_lab(File.read_encoded(file_path))
|
12
|
+
when ".a2l" then self.from_a2l(File.read_encoded(file_path))
|
13
|
+
when ".dbc" then self.from_dbc(File.read_encoded(file_path))
|
14
|
+
else fail "Unknown file extension: #{file_path}!"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
9
18
|
def initialize(signals=SignalList.new, labels=LabelList.new, headers=[], subheaders=[])
|
10
19
|
@signals = signals
|
11
20
|
@labels = labels
|
@@ -39,7 +39,7 @@ class Ecu
|
|
39
39
|
case tok
|
40
40
|
in :HEADER then next_state(:POST_HEADER)
|
41
41
|
in :COMMENT then add_header(lexer.token_value)
|
42
|
-
in :NEWLINE
|
42
|
+
in :NEWLINE then # noop
|
43
43
|
end
|
44
44
|
in :POST_HEADER
|
45
45
|
case tok
|
@@ -77,11 +77,7 @@ class Ecu
|
|
77
77
|
end
|
78
78
|
in :LABEL_CONTENT
|
79
79
|
case tok
|
80
|
-
in :"ST/X" then start_property(:"ST/X", :NUMERIC_PROPERTY)
|
81
|
-
in :"ST/Y" then start_property(:"ST/Y", :NUMERIC_PROPERTY)
|
82
80
|
in :WERT then start_property(:WERT, :NUMERIC_PROPERTY)
|
83
|
-
in :"ST_TX/X" then start_property(:"ST_TX/X", :TEXT_PROPERTY)
|
84
|
-
in :"ST_TX/Y" then start_property(:"ST_TX/Y", :TEXT_PROPERTY)
|
85
81
|
in :TEXT then start_property(:TEXT, :TEXT_PROPERTY)
|
86
82
|
in :EINHEIT_X then start_property(:EINHEIT_X, :TEXT_PROPERTY)
|
87
83
|
in :EINHEIT_Y then start_property(:EINHEIT_Y, :TEXT_PROPERTY)
|
@@ -90,6 +86,10 @@ class Ecu
|
|
90
86
|
in :FUNKTION then start_property(:FUNKTION, :ID_PROPERTY)
|
91
87
|
in :DISPLAYNAME then start_property(:DISPLAYNAME, :ID_PROPERTY)
|
92
88
|
in :END then labels << finish_label
|
89
|
+
in :"ST/X" then start_property(:"ST/X", :NUMERIC_PROPERTY)
|
90
|
+
in :"ST/Y" then start_property(:"ST/Y", :NUMERIC_PROPERTY)
|
91
|
+
in :"ST_TX/X" then start_property(:"ST_TX/X", :TEXT_PROPERTY)
|
92
|
+
in :"ST_TX/Y" then start_property(:"ST_TX/Y", :TEXT_PROPERTY)
|
93
93
|
in :NEWLINE then # noop, DCM badly formatted
|
94
94
|
in :COMMENT then # noop, some programs add SST in comments
|
95
95
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "strscan"
|
2
|
+
|
3
|
+
class Ecu
|
4
|
+
class LabLexer
|
5
|
+
attr_reader :doc
|
6
|
+
def initialize(doc)
|
7
|
+
@doc = doc
|
8
|
+
@scan = StringScanner.new(doc)
|
9
|
+
end
|
10
|
+
|
11
|
+
KEYWORDS = [
|
12
|
+
"[SETTINGS]",
|
13
|
+
"[RAMCELL]",
|
14
|
+
"[Label]",
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
NEWLINE = %r{ \r\n|\n }x
|
18
|
+
SETTINGS_HEADER = %r{ \[SETTINGS\]\s*#{NEWLINE} }x
|
19
|
+
LABELS_HEADER = %r{ \[Label\]\s*#{NEWLINE} }x
|
20
|
+
SIGNALS_HEADER = %r{ \[RAMCELL\]\s*#{NEWLINE} }x
|
21
|
+
STRING = %r{ [^\r\n;]+ }x
|
22
|
+
WHITESPACE = %r{ [ \t]+ }x
|
23
|
+
SEPARATOR = %r{ [;] }x
|
24
|
+
COMMENT = %r{ ^[;].*$ }x
|
25
|
+
|
26
|
+
def next_token(state)
|
27
|
+
@scan.skip(WHITESPACE)
|
28
|
+
|
29
|
+
return if @scan.eos?
|
30
|
+
|
31
|
+
case
|
32
|
+
when @scan.skip(SETTINGS_HEADER) then :SETTINGS_HEADER
|
33
|
+
when @scan.skip(LABELS_HEADER) then :LABELS_HEADER
|
34
|
+
when @scan.skip("[LABEL]\n") then :LABELS_HEADER
|
35
|
+
when @scan.skip(SIGNALS_HEADER) then :SIGNALS_HEADER
|
36
|
+
when @scan.skip(STRING) then :STRING
|
37
|
+
when @scan.beginning_of_line? && @scan.skip(COMMENT) then :COMMENT
|
38
|
+
when @scan.skip(SEPARATOR) then :SEPARATOR
|
39
|
+
when @scan.skip(NEWLINE) then :NEWLINE
|
40
|
+
when @scan.skip(ANYTHING) then :ANYTHING
|
41
|
+
|
42
|
+
else
|
43
|
+
@scan.getch
|
44
|
+
:UNKNOWN_CHAR
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def token_value
|
49
|
+
@doc.byteslice(@scan.pos - @scan.matched_size, @scan.matched_size)
|
50
|
+
end
|
51
|
+
|
52
|
+
def lineno
|
53
|
+
@doc.byteslice(0, @scan.pos).count("\n") +
|
54
|
+
(@scan.beginning_of_line? ? 0 : 1)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,61 +1,132 @@
|
|
1
1
|
require_relative "../../labels"
|
2
2
|
require_relative "../../signals"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
lines = str.lines
|
7
|
-
|
8
|
-
[
|
9
|
-
extract_signals(block_bounded_by(lines, "[RAMCELL]", /\A\[/)),
|
10
|
-
extract_labels(block_bounded_by(lines, "[Label]", /\A\[/)),
|
11
|
-
extract_headers(block_bounded_by(lines, 0, "[SETTINGS]")),
|
12
|
-
extract_headers(block_bounded_by(lines, "[SETTINGS]", /\A\[/)),
|
13
|
-
]
|
14
|
-
end
|
4
|
+
require_relative "lab_lexer"
|
5
|
+
require_relative "lab_parser_error"
|
15
6
|
|
16
|
-
|
17
|
-
|
18
|
-
reject { |l| l.blank? }.
|
19
|
-
reject { |l| l.start_with?(";") }.
|
20
|
-
map { |l| Ecu::Label.from_lab(l) }
|
21
|
-
end
|
7
|
+
class Ecu
|
8
|
+
class LabParser
|
22
9
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
10
|
+
attr_reader :lexer, :state, :labels, :signals, :headers, :subheaders
|
11
|
+
def initialize(doc)
|
12
|
+
@lexer = LabLexer.new(doc)
|
13
|
+
@state = :NO_SECTION
|
14
|
+
@signals = []
|
15
|
+
@labels = []
|
16
|
+
@headers = []
|
17
|
+
@subheaders = []
|
18
|
+
reset_entry!
|
19
|
+
end
|
29
20
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
map { |l| l[2..-1].chomp }
|
34
|
-
end
|
21
|
+
def reset_entry!
|
22
|
+
@properties = {}
|
23
|
+
end
|
35
24
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
25
|
+
def call
|
26
|
+
while tok = lexer.next_token(state)
|
27
|
+
begin
|
28
|
+
case state
|
29
|
+
in :NO_SECTION
|
30
|
+
case tok
|
31
|
+
in :SETTINGS_HEADER then next_state(:SETTINGS)
|
32
|
+
in :SIGNALS_HEADER then next_state(:SIGNALS)
|
33
|
+
in :LABELS_HEADER then next_state(:LABELS)
|
34
|
+
in :COMMENT then add_header(lexer.token_value)
|
35
|
+
in :NEWLINE then # noop
|
36
|
+
end
|
37
|
+
in :SETTINGS
|
38
|
+
case tok
|
39
|
+
in :SIGNALS_HEADER then next_state(:SIGNALS)
|
40
|
+
in :LABELS_HEADER then next_state(:LABELS)
|
41
|
+
in :COMMENT then add_subheader(lexer.token_value)
|
42
|
+
in :STRING then # save that shit?
|
43
|
+
in :SEPARATOR then # now comes the value
|
44
|
+
in :NEWLINE then # next setting
|
45
|
+
end
|
46
|
+
in :LABELS
|
47
|
+
case tok
|
48
|
+
in :SIGNALS_HEADER then next_state(:SIGNALS)
|
49
|
+
in :STRING then start_label(lexer.token_value)
|
50
|
+
in :COMMENT then # noop
|
51
|
+
in :NEWLINE then # noop
|
52
|
+
end
|
53
|
+
in :SIGNALS
|
54
|
+
case tok
|
55
|
+
in :LABELS_HEADER then next_state(:LABELS)
|
56
|
+
in :STRING then start_signal(lexer.token_value)
|
57
|
+
in :COMMENT then # noop
|
58
|
+
in :NEWLINE then # noop
|
59
|
+
end
|
60
|
+
in :LABEL
|
61
|
+
case tok
|
62
|
+
in :NEWLINE then labels << finish_label
|
63
|
+
in :SEPARATOR then # noop, sometimes used as end separator
|
45
64
|
end
|
65
|
+
in :SIGNAL
|
66
|
+
case tok
|
67
|
+
in :STRING then add_property(lexer.token_value)
|
68
|
+
in :SEPARATOR then # noop, next property
|
69
|
+
in :NEWLINE then signals << finish_signal
|
70
|
+
end
|
71
|
+
end
|
72
|
+
rescue NoMatchingPatternError => e
|
73
|
+
raise LabParserError.new("Unexpected token #{debug_token(tok)} (state: #{state})", lexer)
|
74
|
+
rescue StandardError => e
|
75
|
+
raise LabParserError.new("#{e.message} (state: #{@state})", lexer)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
[signals, labels, headers, subheaders]
|
79
|
+
end
|
46
80
|
|
47
|
-
|
81
|
+
def debug_token(tok)
|
82
|
+
"#{tok}: \"#{lexer.token_value}\" - #{@properties.inspect}"
|
83
|
+
end
|
48
84
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
85
|
+
def next_state(newstate)
|
86
|
+
@state = newstate
|
87
|
+
yield if block_given?
|
88
|
+
end
|
89
|
+
|
90
|
+
def add_header(str)
|
91
|
+
@headers << str[1..].strip
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_subheader(str)
|
95
|
+
@subheaders << str[1..].strip
|
96
|
+
end
|
97
|
+
|
98
|
+
def start_label(name)
|
99
|
+
next_state(:LABEL) do
|
100
|
+
@properties[:name] = name
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def finish_label
|
105
|
+
Festwert.new(**@properties, value: nil).tap do
|
106
|
+
reset_entry!
|
107
|
+
next_state(:LABELS)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def start_signal(name)
|
112
|
+
next_state(:SIGNAL) do
|
113
|
+
@properties[:name] = name
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def finish_signal
|
118
|
+
Signal.new(**@properties).tap do
|
119
|
+
reset_entry!
|
120
|
+
next_state(:SIGNALS)
|
121
|
+
end
|
122
|
+
end
|
58
123
|
|
59
|
-
|
124
|
+
def add_property(str)
|
125
|
+
case @properties
|
126
|
+
in { task:, description: } then @properties[:description] << " " << str
|
127
|
+
in { task: } then @properties[:description] = str.strip
|
128
|
+
in { ** } then @properties[:task] = str.split("&").first
|
129
|
+
end
|
130
|
+
end
|
60
131
|
end
|
61
132
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# TODO: This is exactly the same as the DcmParserError, maybe pull these
|
2
|
+
# together?
|
3
|
+
|
4
|
+
class Ecu
|
5
|
+
class LabParserError < StandardError
|
6
|
+
|
7
|
+
CTXLENGHT = 5
|
8
|
+
|
9
|
+
attr_reader :doc, :lineno
|
10
|
+
def initialize(msg, lexer)
|
11
|
+
@msg = msg
|
12
|
+
@doc = lexer.doc
|
13
|
+
@lineno = lexer.lineno
|
14
|
+
end
|
15
|
+
|
16
|
+
def message = @msg
|
17
|
+
def context
|
18
|
+
@doc
|
19
|
+
.lines[ctx_startline..ctx_endline]
|
20
|
+
.each
|
21
|
+
.with_index(ctx_startline + 1)
|
22
|
+
.map { |line, n| present(line, n, n == lineno) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def present(line, n, highlight)
|
26
|
+
case highlight
|
27
|
+
when true then fmt(n) + " => | " + line
|
28
|
+
when false then fmt(n) + " | " + line
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def ctx_startline = [0, lineno - CTXLENGHT].max
|
33
|
+
def ctx_endline = @endline ||= [doc.lines.count - 1, lineno + CTXLENGHT].min
|
34
|
+
def fmt_str = "%#{(ctx_endline + 1).to_s.length}d"
|
35
|
+
def fmt(n) = fmt_str % n
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -1,19 +1,5 @@
|
|
1
1
|
class Ecu
|
2
2
|
class Label
|
3
|
-
|
4
|
-
# This is a silly hack, since the *.lab file doesn't contain any information
|
5
|
-
# about the label in question (just the name). Subsequently, just initialize
|
6
|
-
# a Festwert with no value and hope if does the job correctly
|
7
|
-
|
8
|
-
def self.from_lab(line)
|
9
|
-
name, description = line.strip.split(";")
|
10
|
-
if description.nil?
|
11
|
-
Festwert.new(name: name, value: nil)
|
12
|
-
else
|
13
|
-
Festwert.new(name: name, value: nil, description: description)
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
3
|
def to_lab
|
18
4
|
"#{name};#{description}"
|
19
5
|
end
|
@@ -1,13 +1,5 @@
|
|
1
1
|
class Ecu
|
2
2
|
class Signal
|
3
|
-
def self.from_lab(line)
|
4
|
-
name, tasks, comment = line.strip.split(";")
|
5
|
-
maintask = tasks.split("&").first rescue nil
|
6
|
-
new(name: name,
|
7
|
-
task: maintask,
|
8
|
-
description: comment&.strip)
|
9
|
-
end
|
10
|
-
|
11
3
|
def to_lab
|
12
4
|
"#{name};#{task};#{description}"
|
13
5
|
end
|
@@ -10,6 +10,7 @@ require_relative "../interfaces/dcm/label_list"
|
|
10
10
|
require_relative "../interfaces/lab/label_list"
|
11
11
|
require_relative "../interfaces/a2l/label_list"
|
12
12
|
require_relative "../interfaces/mfile/label_list"
|
13
|
+
require_relative "../interfaces/json/label_list"
|
13
14
|
|
14
15
|
require "set"
|
15
16
|
require_relative "../../core_ext"
|
data/lib/ecu/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: automotive-ecu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Mueller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-04-
|
11
|
+
date: 2025-04-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: terminal-table
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- bin/pry
|
98
98
|
- bin/rake
|
99
99
|
- bin/rspec
|
100
|
+
- bin/sandbox
|
100
101
|
- bin/setup
|
101
102
|
- lib/core_ext.rb
|
102
103
|
- lib/ecu.rb
|
@@ -119,8 +120,11 @@ files:
|
|
119
120
|
- lib/ecu/interfaces/dcm/label.rb
|
120
121
|
- lib/ecu/interfaces/dcm/label_list.rb
|
121
122
|
- lib/ecu/interfaces/dcm/stuetzstellenverteilung.rb
|
123
|
+
- lib/ecu/interfaces/json/label_list.rb
|
122
124
|
- lib/ecu/interfaces/lab/combined_list.rb
|
125
|
+
- lib/ecu/interfaces/lab/lab_lexer.rb
|
123
126
|
- lib/ecu/interfaces/lab/lab_parser.rb
|
127
|
+
- lib/ecu/interfaces/lab/lab_parser_error.rb
|
124
128
|
- lib/ecu/interfaces/lab/label.rb
|
125
129
|
- lib/ecu/interfaces/lab/label_list.rb
|
126
130
|
- lib/ecu/interfaces/lab/signal.rb
|