glance/graph_algs.txt

108 lines
5.7 KiB
Plaintext

-- Pseudocode for collapsing a syntax graph.
-- New stateful algorithm
-- Note: Node refers to the FGL node, which is just an integer. The node label has to be looked up separately in the graph.
-- The node label has all of the information about the node such as what SyntaxNode it represents.
collapseRoots treeRoots = foldl' (collapseTree treeRoots)
collapseNodes :: SyntaxGrrah -> SyntaxGraph
collapseNodes originalGraph = finalGraph where
-- findTreeRoots returns a list of nodes that will embed other nodes, but are not embedded themselves.
-- These nodes are thus each a root of a collapsed node tree.
treeRoots = findTreeRoots originalGraph
-- Now collapse each tree of nodes
finalGraph = collapseRoots treeRoots originalGraph treeRoots
-- |findTreeRoots returns a list of nodes that might embed other nodes, but are not embedded themselves.
-- These nodes are thus each a root of a collapsed node tree.
-- A node is a treeRoot if all of these conditions are true:
-- 1. The SyntaxNode can embed other nodes (i.e. nodeCanEmbed is true)
-- 2. The node has at least one parent that can not embed (i.e. the node has a parent where nodeCanEmbed is false.)
-- Note: A treeRoot may not actually have any embeddable children, since collapseTree will do nothing in that case.
findTreeRoots :: SyntaxGraph -> [Node]
-- filterNodes is a library function that returns a list of the nodes in the graph
-- where the filter function is true.
-- filterNodes :: (Node -> Bool) -> Graph -> [Node]
findTreeRoots graph = filterNodes (isTreeRoot graph) graph
isTreeRoot :: SyntaxGraph -> Node -> Bool
isTreeRoot graph node = graphNodeCanEmbed graph node && hasAParentThatCannotEmbed where
hasAParentThatCannotEmbed = not $ null parentsThatCannotEmbed
parentsThatCannotEmbed = filter (graphNodeCanEmbed graph) (findParents graph node)
findParents :: Graph -> Node -> [Node]
findParents = _ -- TODO
graphNodeCanEmbed :: Graph -> Node -> Bool
graphNodeCanEmbed graph node = syntaxNodeCanEmbed $ lookupSyntaxNode graph node
lookupSyntaxNode :: SyntaxGraph -> Node -> SyntaxNode
collapseTree :: [Node] -> SyntaxGraph -> Node -> SyntaxGraph
collapseTree treeRoots oldGraph rootNode = case childrenToEmbed of
[] -> oldGraph
_ -> finalGraph
where
-- TODO Write pseudocode for subfunctions
childrenToEmbed = findChildrenToEmbed treeRoots rootNode oldGraph
-- Recursively collapse the children nodes
graphWithCollapsedChildren = collapseRoots treeRoots oldGraph childrenToEmbed
-- Transfer the edges of the children to rootNode
childEdgesToTransfer = findChildEdgesToTransfer childrenToEmbed graphWithCollapsedChildren
graphWithChildEdgesDeleted = deleteChildEdges childEdgesToTransfer graphWithCollapsedChildren
graphWithEdgesTransferred = addChildEdges rootNode childEdgesToTransfer graphWithChildEdgesDeleted
-- Modify the rootNode label (i.e. SyntaxNode) to incorporate the children it is embedding
graphWithChildrenCollapsed = embedChildSyntaxNodes rootNode childrenToEmbed graphWithEdgesTransferred
-- Delete the children that have been embedded
finalGraph = deleteChildren childrenToEmbed graphWithChildrenCollapsed
-- | findChildrenToEmbed returns a list of the node's children that can be embedded
-- A child can be embedded iff all of these conditions are true:
-- 1. The node is not a treeRoot (otherwise a cycle of embedding could occur)
-- 2. The SyntaxNode is embeddable (i.e. nodeIsEmbeddable is True)
-- 3. The node has exactly one parent that can embed (i.e. nodeCanEmbed is True for one parent)
findChildrenToEmbed :: Node -> SyntaxGraph -> [Node]
findChildrenToEmbed treeRoots node graph = if graphNodeCanEmbed node graph
then childrenToEmbed
else []
where
childrenToEmbed = _ -- TODO
-- | graphNodeCanEmbed returns true if the label (SyntaxNode) associated with the
-- node can be embedded in other SyntaxNodes (i.e. nodeCanEmbed is True)
graphNodeCanEmbed :: Node -> SyntaxGraph -> Bool
graphNodeCanEmbed node graph = _
-- OLD ALGORITHM
-- To make the problem simpler, collapseNodes just cares about the
collapseNodes :: SyntaxGraph -> SyntaxGraph
collapseNodes inGraph = graphFold foldFunc initialOutputGraph inGraph where
initialOutputGraph = emptyGraph
foldFunc :: SyntaxGraph -> Context -> SyntaxGraph
foldFunc oldGraph context = let node = nodeInContext context in
-- The node can not be embedded, and can not embed other nodes, so it is by itself.
-- We thus just add it to the accumulator graph.
-- willEmbed is true iff the current node will embed other nodes in the graph
| not (willBeEmbedded context inGraph) && not (willEmbed context inGraph) = context & oldGraph
-- willBeEmbedded checks to see if the parent of the current node will embed the current node
-- In this case the current node will be embedded, and does not embed other node.
-- We do not add the current node since it will be embedded in its parent.
-- This case is not necessary. If the current node were to be added, it would simply be
-- removed again from the accumulation graph.
| willBeEmbedded context inGraph && not (willEmbed context) = oldGraph
-- This node will embed other nodes.
-- First we find our children that will be embedded. If the child is in the
-- oldGraph, then we also need to remove the child from the oldGraph.
-- If the child is not yet in the oldGraph, then we just embed it.
| willEmbed context inGraph =
newGraph where
(oldGraphChildren, oldGraphWithChildrenRemoved) = findAndRemoveChildren oldGraph context
remainingChildrem = getRemainingChildren oldGraphChildren inGraph context
embeddedNode = makeEmbeddedNode context oldGraphChildren remainingChildren
newGarph = embeddedNode & oldGraphWithChildrenRemoved