Skip to content

Commit

Permalink
various small fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewcooke committed Mar 4, 2016
1 parent 5c096df commit c4fe807
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 18 deletions.
2 changes: 1 addition & 1 deletion src/ParserCombinator.jl
Expand Up @@ -4,7 +4,7 @@ module ParserCombinator
using Compat
using AutoHashEquals
import Base: start, next, done, endof, getindex, colon, isless, size, hash
import Base: ==, ~, +, &, |, >=, >, |>
import Base: ==, ~, +, &, |, >=, >, |>, !

export Matcher,
diagnostic, forwards, LineSource, LineIter,
Expand Down
14 changes: 13 additions & 1 deletion src/core/debug.jl
Expand Up @@ -73,10 +73,22 @@ MAX_RES = 50
MAX_SRC = 10
MAX_IND = 10

if VERSION < v"0.4-"
shorten(s) = s
else
# shorten(s) = replace(s, r"(?:[a-zA-Z]+\.)+([a-zA-Z]+)", s"\1")
shorten(s) = replace(s, r"(?:[a-zA-Z]+\.)+([a-zA-Z]+)",
Base.SubstitutionString("\1"))
end

function truncate(s::AbstractString, n=10)
if length(s) <= n
return s
end
s = shorten(s)
l = length(s)
if l <= n
s
return s
else
j = div(2*n+1,3) - 2
# j + 3 + (l - k + 1) = n
Expand Down
1 change: 0 additions & 1 deletion src/core/extras.jl
Expand Up @@ -36,4 +36,3 @@ StarList(m::Matcher, s::Matcher) = Alt(Seq(m, Star(Seq(s, m))), Epsilon())
StarList!(m::Matcher, s::Matcher) = Alt!(Seq!(m, Star!(Seq!(s, m))), Epsilon())
PlusList(m::Matcher, s::Matcher) = Seq(m, Star(Seq(s, m)))
PlusList!(m::Matcher, s::Matcher) = Seq!(m, Star!(Seq!(s, m)))

7 changes: 4 additions & 3 deletions src/core/matchers.jl
Expand Up @@ -686,13 +686,12 @@ success(k::Config, m::Lookahead, s, t, i, r::Value) = Success(LookaheadState(t,


# if the child matches, fail; if the child fails return EMPTY
# no backtracking of the child is supported (i don't understand how it would
# work, but feel free to correct mfie....)
# repeated calls fail (the internal matcher is not backtracked).

@auto_hash_equals type Not<:Matcher
name::Symbol
matcher::Matcher
Not(matcher) = new(:Not ,matcher)
Not(matcher) = new(:Not, matcher)
end

@auto_hash_equals immutable NotState<:State
Expand All @@ -701,6 +700,8 @@ end

execute(k::Config, m::Not, s::Clean, i) = Execute(m, NotState(i), m.matcher, CLEAN, i)

execute(k::Config, m::Not, s::NotState, i) = FAILURE

success(k::Config, m::Not, s::NotState, t, i, r::Value) = FAILURE

failure(k::Config, m::Not, s::NotState) = Success(s, s.iter, EMPTY)
Expand Down
2 changes: 2 additions & 0 deletions src/core/sugar.jl
Expand Up @@ -30,6 +30,8 @@ Opt!(m::Matcher) = Alt!(m, Epsilon())
# match and discard
~(m::Matcher) = Drop(m)

# refuse
!(m::Matcher) = Not(Lookahead(m))

# match in sequence, result in array

Expand Down
63 changes: 53 additions & 10 deletions src/regex/Regex.jl
Expand Up @@ -2,28 +2,71 @@
module Regex

using ...ParserCombinator

using AutoHashEquals

abstract Pattern

type Choice <: Pattern
@auto_hash_equals type Choice <: Pattern
patterns::Vector{Pattern}
end

type Sequence <: Pattern
@auto_hash_equals type Sequence <: Pattern
patterns::Vector{Pattern}
end

type Literal <: Pattern
char::Char
@auto_hash_equals type Repeat <: Pattern
patterns::Vector{Pattern}
lo::Int
hi::Int
end

pattern = Delayed()
make_rpt(lo) = p -> Repeat(p, lo, typemax(Int))
make_rpt(lo, hi) = p -> Repeat(p, lo, hi)

@auto_hash_equals type Range <: Pattern
lo::Char
hi::Char
end

Literal(s::AbstractString) = (@assert length(s) == 1; Range(s[1], s[1]))
Literal(c::Char) = Range(c, c)
Dot() = Range(typemin(Char), typemax(Char))

@auto_hash_equals type Group <: Pattern
index::Int
pattern::Pattern
end

choice = PlusList(pattern, e"|") |> Choice
sequence = Plus(pattern) |> Sequence
literal = p"[^[\].*+\\]" > Literal
function make_pattern()

group_count = 0
function make_group(pattern)
group_count += 1
Group(group_count, pattern)
end

make_sequence(p) = length(p) == 1 ? p[1] : Sequence(p)
make_choice(p) = length(p) == 1 ? p[1] : Choice(p)


literal = p"[^[\].*+\\|(){}?]" > Literal
any = E"." > Dot

outseq = Delayed()
atom = literal | any | outseq
plus = atom + E"+" > make_rpt(1)
star = atom + E"*" > make_rpt(0)
opt = atom + E"?" > make_rpt(0, 1)
once = atom + !(E"*"|E"+"|E"?")
inseq = Plus(plus | star | opt | once) |> make_sequence
choice = PlusList(inseq, E"|") |> make_choice
gchoice = E"(" + !(e"?") + choice + E")" > make_group
nchoice = E"(?:" + choice + E")"
outseq.matcher = Plus(gchoice | nchoice | literal) |> make_sequence

return choice + Eos()
end

pattern.matcher = (choice | sequence | literal) + Eos()
pattern = make_pattern()

end
12 changes: 10 additions & 2 deletions test/regex/pattern.jl
@@ -1,5 +1,13 @@

using ParserCombinator.Parsers.Regex; R = ParserCombinator.Parsers.Regex

@test parse_one("abc", R.pattern) == [R.Sequence([R.Literal('a'), R.Literal('b'), R.Literal('c')])]

for (s, r) in [("abc",
[R.Sequence([R.Literal('a'), R.Literal('b'), R.Literal('c')])]),
("a|b",
[R.Choice([R.Literal('a'), R.Literal('b')])]),
("a|b(?:c|d)",
[R.Choice([R.Literal('a'), R.Sequence([R.Literal('b'), R.Choice([R.Literal("c"), R.Literal("d")])])])])
]
@test parse_dbg(s, R.pattern) == r
println("$s ok")
end
1 change: 1 addition & 0 deletions test/runtests.jl
Expand Up @@ -9,6 +9,7 @@ using ParserCombinator
using Base.Test
using Compat
#include("regex/pattern.jl")
#exit(0)
end

module CoreTest
Expand Down

0 comments on commit c4fe807

Please sign in to comment.