fully fledged bracket counter

This commit is contained in:
Brandon Taylor 2017-08-03 09:17:14 -04:00
parent 1a8fad9cb5
commit 54ecf83c40
1 changed files with 28 additions and 23 deletions

View File

@ -1,29 +1,29 @@
struct Parser{T} mutable struct Parser{T}
tokens::T tokens::T
substitutions::Dict{String, String} substitutions::Dict{String, String}
records::Dict{String, Dict{String, String}} records::Dict{String, Dict{String, String}}
line::Ref{Int} line::Int
bracket_counter::Int
end end
Base.eltype(p::Parser) = eltype(p.tokens) Base.eltype(p::Parser) = eltype(p.tokens)
Base.one(p::Parser) = eltype(p)("") Base.one(p::Parser) = eltype(p)("")
Parser(tokens::T, substitutions, records, line) where T = Parser(tokens::T, substitutions, records, line, bracket_counter) where T =
Parser{T}(tokens, substitutions, records, line) Parser{T}(tokens, substitutions, records, line, bracket_counter)
parse_text(text) = begin Parser(tokens) = Parser(tokens, Dict{String, String}(), Dict{String, Dict{String, String}}(), 1, 0)
tokens = matchall(r"[^\s\"#{}@,=]+|\s+|\"|#|{|}|@|,|=", text)
Parser(tokens, Dict{String, String}(), Dict{String, String}(), Ref(1))
end
location(parser) = "on line $(parser.line.x)" parse_text(text) = matchall(r"[^\s\"#{}@,=\\]+|\s+|\"|#|{|}|@|,|=|\\", text) |> Parser
location(parser) = "on line $(parser.line)"
next_token_default!(parser) = next_token_default!(parser) =
if isempty(parser.tokens) if isempty(parser.tokens)
one(parser) one(parser)
else else
result = shift!(parser.tokens) result = shift!(parser.tokens)
parser.line.x = parser.line.x + count(x -> x == '\n', result) parser.line = parser.line + count(x -> x == '\n', result)
if all(isspace, result) if all(isspace, result)
eltype(parser)(" ") eltype(parser)(" ")
else else
@ -56,29 +56,34 @@ expect(parser, result, expectation) =
expect!(parser, expectation) = expect(parser, next_token!(parser, expectation), expectation) expect!(parser, expectation) = expect(parser, next_token!(parser, expectation), expectation)
token_and_counter!(parser, bracket_counter = 1) = begin token_and_counter!(parser, eol) = begin
token = next_token_with_space!(parser, "}") token = next_token_with_space!(parser, eol)
if token == "{" if token == "{"
bracket_counter += 1 parser.bracket_counter += 1
elseif token == "}" elseif token == "}"
bracket_counter -= 1 parser.bracket_counter -= 1
end
if parser.bracket_counter < 0
error("} without corresponding { $(location(parser))")
else
token
end end
token, bracket_counter
end end
value!(parser, values = eltype(parser)[]) = begin value!(parser, values = eltype(parser)[]) = begin
token = next_token!(parser) token = next_token!(parser)
if token == "\"" if token == "\""
token = next_token_with_space!(parser, "\"") token = token_and_counter!(parser, "\"")
while token != "\"" while !(token == "\"" && parser.bracket_counter == 0)
push!(values, token) push!(values, token)
token = next_token_with_space!(parser, "\"") token = token_and_counter!(parser, "\" or }")
end end
elseif token == "{" elseif token == "{"
token, counter = token_and_counter!(parser) parser.bracket_counter += 1
while counter > 0 token = token_and_counter!(parser, "}")
while parser.bracket_counter > 0
push!(values, token) push!(values, token)
token, counter = token_and_counter!(parser, counter) token = token_and_counter!(parser, "}")
end end
else else
push!(values, getkey(parser.substitutions, token, String(token) ) ) push!(values, getkey(parser.substitutions, token, String(token) ) )
@ -125,7 +130,7 @@ julia> preamble, result = parse_bibtex(""\"
@string{short = long} @string{short = long}
@a{b, @a{b,
c = {{c} c}, c = {{c} c},
d = "d d", d = "d {"} d",
e = f # short e = f # short
} }
""\"); ""\");
@ -140,7 +145,7 @@ julia> result["b"]["c"]
"{c} c" "{c} c"
julia> result["b"]["d"] julia> result["b"]["d"]
"d d" "d {\\"} d"
julia> result["b"]["e"] julia> result["b"]["e"]
"f short" "f short"