1 // Implementation of CEdge methods
2 // Copyright © 2009 The University of Chicago
7 #include "GrammarRule.h"
8 #include "StringFunc.h"
12 bool IsTerminalCategory(CStringSurrogate ssPiece
)
14 return !(ssPiece
.GetLength() > 1 ||
15 ssPiece
.GetLength() <= 0);
19 //////////////////////////////////////////////////////////////////////
20 // Construction/Destruction
21 //////////////////////////////////////////////////////////////////////
25 m_InFinalParse
= FALSE
;
27 m_MinimumLength
= 20000; // Just needs to be a large number
34 for( pEdge = m_Daughters.first(); pEdge; pEdge = m_Daughters.next() )
44 CEdge::CEdge( CGrammarRule
* rule
, CParse
* word
, int i
)
46 Append( rule
->GetLHS() );
47 if( rule
->GetRHS().GetKey()[0] == GRAMMAR_RULE_WILD_CARD
)
50 for( int j
= 0; j
< rule
->GetRHS().GetKeyLength(); j
++ )
52 if( rule
->GetRHS().GetKey()[j
] == GRAMMAR_RULE_WILD_CARD
)
54 rightSide
= word
->GetKey()[ j
+ i
- 1 ];
55 CSS
ssRHS( rightSide
);
60 else Append( rule
->GetRHS() );
64 m_DotLocation
= 2; // that's where a rule always starts
65 m_InFinalParse
= FALSE
;
67 m_MinimumLength
= 20000; // Just needs to be a large number
72 CEdge::CEdge( CEdge
& Edge
) : CParse( Edge
)
74 m_Start
= Edge
.GetStart();
75 m_DotLocation
= Edge
.GetDotLocation();
76 m_InFinalParse
= FALSE
;
77 m_Parent
= Edge
.m_Parent
;
78 m_MinimumLength
= Edge
.m_MinimumLength
;
79 m_Depth
= Edge
.getDepth();
82 for( pEdge
= Edge
.m_Daughters
.first(); pEdge
; pEdge
= Edge
.m_Daughters
.next() )
84 m_Daughters
.append( pEdge
);
89 CEdge::CEdge( CParse
& Cat
, QString Key
, int i
, int End
) // Used in Scanning
96 m_InFinalParse
= FALSE
;
98 m_MinimumLength
= 20000; // Just needs to be a large number
103 CSS
CEdge::GetNextNode()
105 return GetPiece( m_DotLocation
);
109 int CEdge::GetStart() { return m_Start
; }
112 void CEdge::SetDotLocation (int n
) { m_DotLocation
= n
; }
115 int CEdge::GetDotLocation() { return m_DotLocation
; }
118 void CEdge::SetStart( int n
) { m_Start
= n
; }
123 return GetPiece(1).Display();
129 return ThisPieceAndWhatFollows(2).Display();
133 CStringSurrogate
CEdge::GetLHS()
139 bool CEdge::Complete ()
141 if( m_DotLocation
> Size() ) { return TRUE
; }
146 void CEdge::MoveDotToTheRight()
148 Q_ASSERT( m_DotLocation
<= m_PieceCount
+ 1 ) ;// check that
153 bool CEdge::NextNodeIsNonterminal()
155 CSS ssPiece
= GetPiece( m_DotLocation
);
156 return !IsTerminalCategory( ssPiece
);
160 bool CEdge::NextNodeIsTerminal()
162 return IsTerminalCategory( GetPiece( m_DotLocation
) );
166 bool CEdge::Incomplete()
168 if( m_DotLocation
== Size() + 1 ) { return FALSE
; }
169 else { return TRUE
; }
173 QString
CEdge::Display()
175 QString String
= GetPiece(1).Display() + " ->";
177 for( i
= 2; i
<= m_PieceCount
; i
++ )
179 if( i
== m_DotLocation
)
183 String
+= GetPiece(i
).Display();
185 if( m_DotLocation
== i
)
192 void CEdge::GetParse( CParse
* parse
, bool clearParse
)
194 if( clearParse
) parse
->ClearParse();
197 CStringSurrogate
rightSide( rhs
);
199 if( m_Daughters
.isEmpty() )
201 parse
->Append(rightSide
);
206 for( daughter
= m_Daughters
.first(); daughter
; daughter
= m_Daughters
.next() )
208 daughter
->GetParse( parse
, FALSE
);
214 QRect
CEdge::drawTree(Q3Canvas
* canvas
, int left
, int depth
,
215 QMap
<QString
, QString
>* filter
)
220 // int X_MARGIN = 10; unused variable 'X_Margin'
223 //================================================
225 Q3CanvasItem
* edge
= new Q3CanvasText( LHS(), canvas
),
229 m_CanvasItems
.clear();
230 m_CanvasItems
.append( edge
);
233 myTop
= ( depth
* Y_SPACING
) + Y_MARGIN
,
241 Q3ValueList
<QRect
> daughterBoundingRectangles
;
242 Q3ValueList
<QRect
>::iterator it
;
244 QRect myBoundingRect
, rectangle
;
245 myBoundingRect
.setTop( myTop
);
246 myBoundingRect
.setLeft( myLeft
);
247 myBoundingRect
.setBottom( myTop
+ edge
->boundingRect().height() - 1 );
248 myBoundingRect
.setRight( myLeft
+ edge
->boundingRect().width() - 1 );
251 // bool first = TRUE; unused variable 'first'
254 for( daughter
= m_Daughters
.first(); daughter
; daughter
= m_Daughters
.next() )
256 daughterBoundingRectangles
.append( rectangle
);
258 daughterBoundingRectangles
[count
] = daughter
->drawTree( canvas
, left
, depth
+ 1, filter
);
260 // Adjust left position based on bounding rectangle of last daughter
261 left
= daughterBoundingRectangles
[count
].right() + X_PADDING
;
266 if( m_Daughters
.isEmpty() )
270 childTop
= ( ( depth
+ 1 ) * Y_SPACING
) + Y_MARGIN
;
272 leaf
= new Q3CanvasText( Filter( filter
, RHS() ), canvas
);
273 m_CanvasItems
.append( leaf
);
275 leaf
->move( childLeft
, childTop
);
278 // Adjust my bounding rect
279 if( leaf
->boundingRect().right() > myBoundingRect
.right() ) myBoundingRect
.setRight( leaf
->boundingRect().right() );
280 myBoundingRect
.setBottom( leaf
->boundingRect().bottom() );
284 for( it
= daughterBoundingRectangles
.begin(); it
!= daughterBoundingRectangles
.end(); ++it
)
286 // Adjust my bounding rect
287 if( (*it
).right() > myBoundingRect
.right() ) myBoundingRect
.setRight( (*it
).right() );
288 if( (*it
).bottom() > myBoundingRect
.bottom() ) myBoundingRect
.setBottom( (*it
).bottom() );
292 if( myBoundingRect
.width() == edge
->boundingRect().width() )
294 // Shift all children to the right
295 if( m_Daughters
.isEmpty() )
297 shiftAmount
= int (( myBoundingRect
.width() - leaf
->boundingRect().width() ) / 2.0);
299 leaf
->move( leaf
->boundingRect().left() + shiftAmount
, leaf
->boundingRect().top() );
304 shiftAmount
= int (( myBoundingRect
.width() - ( daughterBoundingRectangles
.last().right() - daughterBoundingRectangles
.first().left() ) ) / 2.0);
306 for( daughter
= m_Daughters
.first(); daughter
; daughter
= m_Daughters
.next() )
308 daughter
->shiftTree( canvas
, shiftAmount
, 0 );
311 for( it
= daughterBoundingRectangles
.begin(); it
!= daughterBoundingRectangles
.end(); ++it
)
313 // Adjust the bounding rect position
314 (*it
).setLeft( (*it
).left() + shiftAmount
);
315 (*it
).setRight( (*it
).right() + shiftAmount
);
319 else myLeft
= ( myBoundingRect
.right() - ( myBoundingRect
.width() / 2 ) ) - ( edge
->boundingRect().width() / 2 );
322 if( myLeft
< myBoundingRect
.left() ) myLeft
= myBoundingRect
.left();
323 edge
->move( myLeft
, myTop
);
325 // Draw lines to daughter nodes
326 if( m_Daughters
.isEmpty() )
328 myCenterX
= edge
->boundingRect().center().x();
329 myBottom
= edge
->boundingRect().bottom();
331 childCenterX
= leaf
->boundingRect().center().x();
332 childTop
= leaf
->boundingRect().top();
334 if( myCenterX
- childCenterX
== 1 || myCenterX
- childCenterX
== -1 ) myCenterX
= childCenterX
;
336 line
= new Q3CanvasLine( canvas
);
337 line
->setPoints( myCenterX
, myBottom
, childCenterX
, childTop
);
340 m_CanvasItems
.append( line
);
344 Q3ValueList
<QRect
>::iterator it
;
345 for( it
= daughterBoundingRectangles
.begin(); it
!= daughterBoundingRectangles
.end(); ++it
)
347 myCenterX
= edge
->boundingRect().center().x();
348 myBottom
= edge
->boundingRect().bottom();
350 childCenterX
= (*it
).center().x();
351 childTop
= (*it
).top();
353 if( myCenterX
- childCenterX
== 1 || myCenterX
- childCenterX
== -1 ) myCenterX
= childCenterX
;
355 line
= new Q3CanvasLine( canvas
);
356 line
->setPoints( myCenterX
, myBottom
, childCenterX
, childTop
);
359 m_CanvasItems
.append( line
);
366 return myBoundingRect
;
370 void CEdge::shiftTree( Q3Canvas
* canvas
, int right
, int down
)
373 for( daughter
= m_Daughters
.first(); daughter
; daughter
= m_Daughters
.next() )
375 daughter
->shiftTree( canvas
, right
, down
);
379 for( item
= m_CanvasItems
.first(); item
; item
= m_CanvasItems
.next() )
381 item
->moveBy( right
, down
);
387 void CEdge::setMinimumLength( int length
, QMap
<QString
,int>* mins
)
389 if( m_Parent
&& mins
&& mins
->find( LHS() ) != mins
->end() )
391 int parentLength
= m_Parent
->getMinimumLength();
392 parentLength
-= (*mins
)[ LHS() ];
393 parentLength
+= length
;
395 m_Parent
->setMinimumLength( parentLength
, mins
);
398 m_MinimumLength
= length
;
402 QString
CEdge::DisplayParse( QMap
<QString
, QString
>* filter
)
404 QString parse
= LHS() + "( ";
406 if( m_Daughters
.count() )
409 for( daughter
= m_Daughters
.first(); daughter
; daughter
= m_Daughters
.next() )
411 parse
+= daughter
->DisplayParse( filter
);
417 if( filter
) parse
+= Filter( filter
, RHS() );