dms-parser 0.5.1 → 0.5.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/lib/dms/tier1.rb +61 -28
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 356dcaecf022100fac1eeae5350a76ecfc417f831f64084ffe912cd4da486a80
|
|
4
|
+
data.tar.gz: 74e4bd7721ac3f5c7325ada5145c98ad5eccb7723c6e0eed45fcd99dd0a61b9e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 39ef8d91e5fdb82746a03ddc8e3b367970b60ff2291021b7a33ed922d3fc93a377f6e0a4c4ddd9093d52f9c7aae87bf3d674ca089bd18c6d6a42fcde2c58358a
|
|
7
|
+
data.tar.gz: d95fec6634f7049576d56e93195eb47f772e54daa49e270ea7afeace93c2ea3021747c9b8e4a8baa17e54779e1d687198f58462da5a7fd1531d6baf05f521cc8
|
data/lib/dms/tier1.rb
CHANGED
|
@@ -217,7 +217,7 @@ module Dms
|
|
|
217
217
|
# params: Array of ParamGroup
|
|
218
218
|
# params_dec: Array (always empty in this implementation)
|
|
219
219
|
# sigil: String (the literal sigil string)
|
|
220
|
-
DecoratorCall = Struct.new(:sigil, :family, :fn_name, :ns, :position, :params, :params_dec)
|
|
220
|
+
DecoratorCall = Struct.new(:sigil, :family, :fn_name, :ns, :position, :params, :params_dec, :call_style)
|
|
221
221
|
|
|
222
222
|
# kind: :named or :positional
|
|
223
223
|
# value: Hash (for named) or Array (for positional)
|
|
@@ -463,7 +463,8 @@ module Dms
|
|
|
463
463
|
# Resolve a decorator call's family from imports.
|
|
464
464
|
# Returns [family_name, canonical_fn_name] or raises.
|
|
465
465
|
# Also applies deny-list check.
|
|
466
|
-
|
|
466
|
+
# call_style: :named or :nameless
|
|
467
|
+
def self.resolve_family(sigil, fn_name, ns, imports, call_style: :named)
|
|
467
468
|
# Filter imports by ns if specified
|
|
468
469
|
candidate_imports = if ns
|
|
469
470
|
filtered = imports.select { |imp| imp.ns == ns }
|
|
@@ -475,6 +476,24 @@ module Dms
|
|
|
475
476
|
imports
|
|
476
477
|
end
|
|
477
478
|
|
|
479
|
+
# Nameless call: fn_name is empty; resolve to the single bound family name
|
|
480
|
+
if call_style == :nameless
|
|
481
|
+
bound_families = []
|
|
482
|
+
candidate_imports.each do |imp|
|
|
483
|
+
(imp.bind[sigil] || []).each { |fam| bound_families << fam }
|
|
484
|
+
end
|
|
485
|
+
if bound_families.empty?
|
|
486
|
+
raise DecodeError.new(0, 0, "unbound sigil '#{sigil}'")
|
|
487
|
+
end
|
|
488
|
+
if bound_families.size > 1
|
|
489
|
+
raise DecodeError.new(0, 0,
|
|
490
|
+
"nameless call on sigil '#{sigil}' is ambiguous between families " \
|
|
491
|
+
+ bound_families.map { |f| "'#{f}'" }.join(", "))
|
|
492
|
+
end
|
|
493
|
+
family = bound_families.first
|
|
494
|
+
return [family, family]
|
|
495
|
+
end
|
|
496
|
+
|
|
478
497
|
# For each import, check families bound to this sigil
|
|
479
498
|
# Apply aliases and allow/deny rules
|
|
480
499
|
accepted = [] # [family_name, canonical_fn_name]
|
|
@@ -773,8 +792,8 @@ module Dms
|
|
|
773
792
|
# But we don't know the next key yet — so we store them as pending.
|
|
774
793
|
def collect_leading_decorators(path_prefix)
|
|
775
794
|
while !eof? && sigil_at?(@pos)
|
|
776
|
-
sigil, fn_name, ns, params = parse_decorator_call
|
|
777
|
-
@pending_leading << { sigil: sigil, fn_name: fn_name, ns: ns, params: params }
|
|
795
|
+
sigil, fn_name, ns, params, cs = parse_decorator_call
|
|
796
|
+
@pending_leading << { sigil: sigil, fn_name: fn_name, ns: ns, params: params, call_style: cs }
|
|
778
797
|
skip_trivia_no_consume_leading
|
|
779
798
|
break if eof?
|
|
780
799
|
# Check if next line also starts with a sigil
|
|
@@ -824,8 +843,8 @@ module Dms
|
|
|
824
843
|
if sigil_at?(@pos)
|
|
825
844
|
# Collect leading decorators for next value
|
|
826
845
|
loop do
|
|
827
|
-
sigil, fn_name, ns, params = parse_decorator_call
|
|
828
|
-
@pending_leading << { sigil: sigil, fn_name: fn_name, ns: ns, params: params }
|
|
846
|
+
sigil, fn_name, ns, params, cs = parse_decorator_call
|
|
847
|
+
@pending_leading << { sigil: sigil, fn_name: fn_name, ns: ns, params: params, call_style: cs }
|
|
829
848
|
# After decorator call, consume rest of line
|
|
830
849
|
skip_inline_ws
|
|
831
850
|
if consume_eol || eof?
|
|
@@ -860,8 +879,8 @@ module Dms
|
|
|
860
879
|
pending = @pending_leading.dup
|
|
861
880
|
@pending_leading.clear
|
|
862
881
|
pending.each do |dec|
|
|
863
|
-
family, canonical_fn = resolve_call(dec[:sigil], dec[:fn_name], dec[:ns])
|
|
864
|
-
add_decorator_call(current_path, dec[:sigil], family, canonical_fn, dec[:ns], :leading, dec[:params])
|
|
882
|
+
family, canonical_fn = resolve_call(dec[:sigil], dec[:fn_name], dec[:ns], call_style: dec[:call_style] || :named)
|
|
883
|
+
add_decorator_call(current_path, dec[:sigil], family, canonical_fn, dec[:ns], :leading, dec[:params], call_style: dec[:call_style] || :named)
|
|
865
884
|
end
|
|
866
885
|
end
|
|
867
886
|
|
|
@@ -1029,9 +1048,9 @@ module Dms
|
|
|
1029
1048
|
def parse_t1_inner_and_value(path)
|
|
1030
1049
|
# Collect all consecutive inner decorator calls
|
|
1031
1050
|
while !eof? && sigil_at?(@pos)
|
|
1032
|
-
sigil, fn_name, ns, params = parse_decorator_call
|
|
1033
|
-
family, canonical_fn = resolve_call(sigil, fn_name, ns)
|
|
1034
|
-
add_decorator_call(path, sigil, family, canonical_fn, ns, :inner, params)
|
|
1051
|
+
sigil, fn_name, ns, params, cs = parse_decorator_call
|
|
1052
|
+
family, canonical_fn = resolve_call(sigil, fn_name, ns, call_style: cs || :named)
|
|
1053
|
+
add_decorator_call(path, sigil, family, canonical_fn, ns, :inner, params, call_style: cs || :named)
|
|
1035
1054
|
skip_inline_ws
|
|
1036
1055
|
end
|
|
1037
1056
|
|
|
@@ -1059,9 +1078,9 @@ module Dms
|
|
|
1059
1078
|
|
|
1060
1079
|
def parse_t1_trailing_decorators(path)
|
|
1061
1080
|
while !eof? && sigil_at?(@pos)
|
|
1062
|
-
sigil, fn_name, ns, params = parse_decorator_call
|
|
1063
|
-
family, canonical_fn = resolve_call(sigil, fn_name, ns)
|
|
1064
|
-
add_decorator_call(path, sigil, family, canonical_fn, ns, :trailing, params)
|
|
1081
|
+
sigil, fn_name, ns, params, cs = parse_decorator_call
|
|
1082
|
+
family, canonical_fn = resolve_call(sigil, fn_name, ns, call_style: cs || :named)
|
|
1083
|
+
add_decorator_call(path, sigil, family, canonical_fn, ns, :trailing, params, call_style: cs || :named)
|
|
1065
1084
|
skip_inline_ws
|
|
1066
1085
|
end
|
|
1067
1086
|
end
|
|
@@ -1081,15 +1100,28 @@ module Dms
|
|
|
1081
1100
|
|
|
1082
1101
|
raise DecodeError.new(@line, col, "empty decorator sigil") if sigil.empty?
|
|
1083
1102
|
|
|
1084
|
-
# Parse name (bare identifier)
|
|
1085
|
-
#
|
|
1086
|
-
|
|
1087
|
-
|
|
1103
|
+
# Parse name (bare identifier) — may be empty for nameless calls
|
|
1104
|
+
# Nameless: sigil followed by '(', whitespace, EOL, ',', ']', '}'
|
|
1105
|
+
# Error: sigil followed by '.' (dotted form requires name before '.')
|
|
1106
|
+
next_byte = @src.getbyte(@pos)
|
|
1107
|
+
call_style = :named
|
|
1108
|
+
if next_byte == DOT
|
|
1109
|
+
raise DecodeError.new(@line, col, "dotted form requires a name before '.'")
|
|
1110
|
+
elsif next_byte == LPAREN || next_byte == SP || next_byte == TAB ||
|
|
1111
|
+
next_byte == LF || next_byte == CR || next_byte == COMMA ||
|
|
1112
|
+
next_byte == RBRACK || next_byte == RBRACE || next_byte.nil? || @pos >= @src.bytesize
|
|
1113
|
+
# Nameless call
|
|
1114
|
+
call_style = :nameless
|
|
1115
|
+
name1 = ""
|
|
1116
|
+
else
|
|
1117
|
+
name1 = parse_bare_ident
|
|
1118
|
+
raise DecodeError.new(@line, col, "expected decorator name after sigil '#{sigil}'") if name1.empty?
|
|
1119
|
+
end
|
|
1088
1120
|
|
|
1089
1121
|
# Check for '.' => namespace qualifier
|
|
1090
1122
|
ns = nil
|
|
1091
1123
|
fn_name = name1
|
|
1092
|
-
if @src.getbyte(@pos) == DOT
|
|
1124
|
+
if call_style == :named && @src.getbyte(@pos) == DOT
|
|
1093
1125
|
@pos += 1 # consume '.'
|
|
1094
1126
|
name2 = parse_bare_ident
|
|
1095
1127
|
if name2.empty?
|
|
@@ -1122,7 +1154,7 @@ module Dms
|
|
|
1122
1154
|
# If no params at all, treat as one empty named group
|
|
1123
1155
|
params << ParamGroup.new(:named, {}) if params.empty?
|
|
1124
1156
|
|
|
1125
|
-
[sigil, fn_name, ns, params]
|
|
1157
|
+
[sigil, fn_name, ns, params, call_style]
|
|
1126
1158
|
end
|
|
1127
1159
|
|
|
1128
1160
|
# Parse a param group (between parens, after '(' was consumed).
|
|
@@ -1244,9 +1276,9 @@ module Dms
|
|
|
1244
1276
|
# Inner decorator in flow array
|
|
1245
1277
|
loop do
|
|
1246
1278
|
break unless sigil_at?(@pos)
|
|
1247
|
-
sigil, fn_name, ns, params = parse_decorator_call
|
|
1248
|
-
family, canonical_fn = resolve_call(sigil, fn_name, ns)
|
|
1249
|
-
add_decorator_call(current_path, sigil, family, canonical_fn, ns, :inner, params)
|
|
1279
|
+
sigil, fn_name, ns, params, cs = parse_decorator_call
|
|
1280
|
+
family, canonical_fn = resolve_call(sigil, fn_name, ns, call_style: cs || :named)
|
|
1281
|
+
add_decorator_call(current_path, sigil, family, canonical_fn, ns, :inner, params, call_style: cs || :named)
|
|
1250
1282
|
skip_inline_ws
|
|
1251
1283
|
end
|
|
1252
1284
|
# Now parse the actual value
|
|
@@ -1326,20 +1358,20 @@ module Dms
|
|
|
1326
1358
|
val
|
|
1327
1359
|
end
|
|
1328
1360
|
|
|
1329
|
-
def add_decorator_call(path, sigil, family, fn_name, ns, position, params)
|
|
1361
|
+
def add_decorator_call(path, sigil, family, fn_name, ns, position, params, call_style: :named)
|
|
1330
1362
|
path_key = path_to_key(path)
|
|
1331
1363
|
entry = @dec_entries[path_key]
|
|
1332
1364
|
if entry.nil?
|
|
1333
1365
|
entry = DecoratorEntry.new(path.dup, {}, [])
|
|
1334
1366
|
@dec_entries[path_key] = entry
|
|
1335
1367
|
end
|
|
1336
|
-
call = DecoratorCall.new(sigil, family, fn_name, ns, position, params, [])
|
|
1368
|
+
call = DecoratorCall.new(sigil, family, fn_name, ns, position, params, [], call_style)
|
|
1337
1369
|
entry.calls[sigil] ||= []
|
|
1338
1370
|
entry.calls[sigil] << call
|
|
1339
1371
|
end
|
|
1340
1372
|
|
|
1341
|
-
def resolve_call(sigil, fn_name, ns)
|
|
1342
|
-
Tier1.resolve_family(sigil, fn_name, ns, @imports)
|
|
1373
|
+
def resolve_call(sigil, fn_name, ns, call_style: :named)
|
|
1374
|
+
Tier1.resolve_family(sigil, fn_name, ns, @imports, call_style: call_style)
|
|
1343
1375
|
end
|
|
1344
1376
|
|
|
1345
1377
|
def path_to_key(path)
|
|
@@ -1732,7 +1764,8 @@ module Dms
|
|
|
1732
1764
|
"ns" => call.ns,
|
|
1733
1765
|
"position" => call.position.to_s,
|
|
1734
1766
|
"params" => params_json,
|
|
1735
|
-
"params_dec" => []
|
|
1767
|
+
"params_dec" => [],
|
|
1768
|
+
"call_style" => (call.call_style || :named).to_s
|
|
1736
1769
|
}
|
|
1737
1770
|
end
|
|
1738
1771
|
|