/* dot.y */ %{ #include #include #include #include "calltreedlg.h" #include "graphwidget.h" #include "treewidget.h" #include "encoder.h" extern FILE* yyin; int yylex(); void yyinit(CallTreeDlg*, FILE*, Encoder*); void yyerror(const char*); static TQMap s_pMapAttr; static TQPtrStack s_pParentStack; static TQListView* s_pTree; static GraphWidget* s_pGraph; static TreeWidget* s_pCallTree; static TreeWidget* s_pCallingTree; static Encoder* s_pEncoder; // Avoid compiler warnings #define YYENABLE_NLS 0 #ifndef YYLTYPE_IS_TRIVIAL #define YYLTYPE_IS_TRIVIAL 0 #endif %} %union { TQString* pText; } %token GRAPH DIGRAPH NODE NAME STRING NUMBER DIR_EDGE UNDIR_EDGE %token CALL_TREE CALLING_TREE %type NAME STRING NUMBER attr_val %start file %% file : call_tree calling_tree graph graph : graph_type NAME '{' graph_desc_list '}' { delete $2; } ; graph_type : GRAPH | DIGRAPH ; graph_desc_list : | graph_desc_entry graph_desc_list ; graph_desc_entry : def_node_attr | graph_attr | node_record | edge_record ; def_node_attr : NODE attributes ';' ; graph_attr : GRAPH attributes ';' { if (s_pMapAttr.find("kscope_zoom") != s_pMapAttr.end()) s_pGraph->setZoom(s_pMapAttr["kscope_zoom"].toDouble()); } ; node_record : NAME attributes ';' { s_pGraph->addNode(*$1); delete $1; s_pMapAttr.clear(); } ; edge_record : NAME edge_type NAME attributes ';' { GraphWidget::CallData cd; cd.m_sCaller = *$1; cd.m_sCallee = *$3; cd.m_sFile = s_pMapAttr["kscope_file"]; cd.m_sLine = s_pMapAttr["kscope_line"]; cd.m_sText = s_pEncoder->decode(s_pMapAttr["kscope_text"]); s_pGraph->addCall(cd); delete $1; delete $3; s_pMapAttr.clear(); } ; edge_type : DIR_EDGE | UNDIR_EDGE ; attributes : | '[' attr_list ']' ; attr_list : | non_empty_attr_list ; non_empty_attr_list : attr | attr ',' attr_list ; attr : NAME '=' attr_val { s_pMapAttr.insert(*$1, *$3); delete $1; delete $3; } ; attr_val : NAME | STRING | NUMBER ; call_tree : call_tree_prepare '{' root_node '}' ; call_tree_prepare : CALL_TREE { s_pTree = s_pCallTree; } ; calling_tree : calling_tree_prepare '{' root_node '}' ; calling_tree_prepare : CALLING_TREE { s_pTree = s_pCallingTree; } ; root_node : root_tree_node '{' child_list '}' { TQListViewItem* pItem; pItem = s_pParentStack.pop(); if (pItem->firstChild() != NULL) pItem->setOpen(true); } ; root_tree_node : NAME { TQListViewItem* pItem; pItem = new TQListViewItem(s_pTree, *$1); s_pParentStack.push(pItem); delete $1; } ; child_list : | child_node child_list ; child_node : tree_node tree_attributes '{' child_list '}' { TQListViewItem* pItem; pItem = s_pParentStack.pop(); if (pItem->firstChild() != NULL) pItem->setOpen(true); } ; tree_node : NAME { TQListViewItem* pItem; pItem = new TQListViewItem(s_pParentStack.top(), *$1); s_pParentStack.push(pItem); delete $1; } ; tree_attributes : attributes { TQListViewItem* pItem; pItem = s_pParentStack.top(); pItem->setText(1, s_pMapAttr["kscope_file"]); pItem->setText(2, s_pMapAttr["kscope_line"]); pItem->setText(3, s_pEncoder->decode(s_pMapAttr["kscope_text"])); } ; %% void yyinit(CallTreeDlg* pDlg, FILE* pFile, Encoder* pEnc) { yyin = pFile; s_pCallTree = pDlg->m_pCalledWidget; s_pCallingTree = pDlg->m_pCallingWidget; s_pGraph = pDlg->m_pGraphWidget; s_pEncoder = pEnc; } void yyerror(const char* szError) { fprintf(stderr, "%s\n", szError); }