-
Notifications
You must be signed in to change notification settings - Fork 0
/
indentation-parser-backup.jl
114 lines (98 loc) · 2.91 KB
/
indentation-parser-backup.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
struct Indentor
open::Vector{Token}
close::Vector{Token}
open_replacement::String
close_replacement::String
end
Base.:(==)(i::Indentor, j::Indentor) =
i.open == j.open &&
i.close == j.close &&
i.open_replacement == j.open_replacement &&
i.close_replacement == j.close_replacement
struct IndentorBlock
indentor::Indentor
contents::Vector{Any}
end
function indentation_parse(
tokens::Vector{Token},
indentors::Vector{Indentor}
)::IndentorBlock
indented_tokens = [
InternalMarkerBeginOfFile()
tokens
InternalMarkerEndOfFile()
]
indentors_and_marker = [
indentors
Indentor(
[InternalMarkerBeginOfFile()], [InternalMarkerEndOfFile()],
document_begin, document_end
)
]
end_i, block =
read_indentorortoken(indented_tokens, 1, indentors_and_marker)
block
end
function read_indentorortoken(
tokens::Vector{Token},
i::Int,
indentors::Vector{Indentor}
)::Tuple{Int, Union{Token, IndentorBlock}}
open_indentor_i = findfirst(indentors) do indentor
hassubvectorat(tokens, i, indentor.open)
end
if open_indentor_i === nothing
return (i+1, tokens[i])
else
open = indentors[open_indentor_i].open
open_indentors = filter(indentors) do indentor
indentor.open == open
end
return read_indentor(tokens, i+length(open), indentors, open_indentors)
end
end
function read_indentor(
tokens::Vector{Token},
i::Int,
indentors::Vector{Indentor},
indentors_canclose::Vector{Indentor}
)::Tuple{Int, IndentorBlock}
contents = Any[]
while true
if i > lastindex(tokens)
compileerror(tokens[end],
"expected " *
join((i.close for i in indentors_canclose), ", ", " or ") *
" before end of file"
)
return (i, IndentorBlock(indentors_canclose[1], contents))
end
close_indentor_i = findfirst(indentors_canclose) do indentor
hassubvectorat(tokens, i, indentor.close)
end
if close_indentor_i !== nothing
indentor = indentors_canclose[close_indentor_i]
return (
i + length(indentor.close),
IndentorBlock(indentor, contents)
)
end
i, indentorortoken = read_indentorortoken(tokens, i, indentors)
push!(contents, indentorortoken)
end
end
function hassubvectorat(
xs::Vector,
subvector_begin::Int,
subvector::Vector
)::Bool
i_xs = subvector_begin
i_subvector = 1
while i_subvector ≤ length(subvector)
i_xs > lastindex(xs) && return false
xs[i_xs] != subvector[i_subvector] && return false
i_xs += 1
i_subvector += 1
end
true
end