Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add typechecking for insert! #67

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/HerbGrammar.jl
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ export
read_pcsg,
add_rule!,
remove_rule!,
cleanup_removed_rules!
cleanup_removed_rules!,

RuleNodeTypeCheckError

end # module HerbGrammar
35 changes: 25 additions & 10 deletions src/nodelocation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,34 @@
end
end

struct RuleNodeTypeCheckError <: Exception
message::String
end

Base.showerror(io::IO, e::RuleNodeTypeCheckError) = print(io, e.message)

Check warning on line 35 in src/nodelocation.jl

View check run for this annotation

Codecov / codecov/patch

src/nodelocation.jl#L35

Added line #L35 was not covered by tests

"""
insert!(loc::NodeLoc, rulenode::RuleNode)
Replaces the subtree pointed to by loc with the given rulenode.
"""
function Base.insert!(root::RuleNode, loc::NodeLoc, rulenode::RuleNode)
parent, i = loc.parent, loc.i
if loc.i > 0
parent.children[i] = rulenode
else
root.ind = rulenode.ind
root._val = rulenode._val
root.children = rulenode.children
end
return root
function Base.insert!(root::RuleNode, loc::NodeLoc, rulenode::RuleNode, grammar::AbstractGrammar)
subtree = get(root, loc)
return_type_subtree = return_type(grammar, subtree.ind)
return_type_replacement = return_type(grammar, rulenode.ind)
# if the types do not match throw an error
if return_type_replacement !== return_type_subtree
throw(RuleNodeTypeCheckError("The provided replacement node does have the correct type to be replaced in the tree.
The subtree of the current tree expects a rule with type $return_type_subtree , but
the provided replacement has type $return_type_replacement"))
end

parent, i = loc.parent, loc.i
if loc.i > 0
parent.children[i] = rulenode
else
root.ind = rulenode.ind
root._val = rulenode._val
root.children = rulenode.children

Check warning on line 58 in src/nodelocation.jl

View check run for this annotation

Codecov / codecov/patch

src/nodelocation.jl#L56-L58

Added lines #L56 - L58 were not covered by tests
end
return root
end
28 changes: 27 additions & 1 deletion test/test_rulenode_operators.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module SomeDefinitions
a_variable_that_is_defined = 7
a_variable_that_is_defined = 7
end

@testset verbose = true "RuleNode Operators" begin
Expand All @@ -15,4 +15,30 @@ end
@test !isvariable(g₁, RuleNode(7, g₁), SomeDefinitions)
@test isvariable(g₁, RuleNode(7, g₁))
end
@testset "Check typecheck for insert!" begin
g = @cfgrammar begin
Start = Int + Int
Int = 1
Int = 2
B = "notgood"
end

root = RuleNode(1, [RuleNode(2), RuleNode(2)]) # 1 + 1
replacement = RuleNode(4) # notgood
@test rulenode2expr(replacement, g) == :("notgood")
location = NodeLoc(root, 1) # first child

# attempting to replace type Int by type B should not work
@test_throws HerbGrammar.RuleNodeTypeCheckError insert!(root, location, replacement, g)

root = RuleNode(1, [RuleNode(2), RuleNode(2)]) # 1 + 1
replacement = RuleNode(3) # number 2
@test rulenode2expr(replacement, g) == :2
location = NodeLoc(root, 1) # first child

# replacing from (1 + 1) -> (2 + 1) should work
insert!(root, location, replacement, g)

@test rulenode2expr(root, g) == :(2 + 1)
end
end
Loading