bool ControlParser::parseWhileBody (int keyword, const TokenLoc& loc, Scanner& scanner) { if (keyword==Scanner::K_endwhile) { Codes loop; Codes expr; mExprParser.append (expr); Generator::jump (loop, -static_cast<int> (mCodeBlock.size()+expr.size())); std::copy (expr.begin(), expr.end(), std::back_inserter (mCode)); Codes skip; Generator::jumpOnZero (skip, mCodeBlock.size()+loop.size()+1); std::copy (skip.begin(), skip.end(), std::back_inserter (mCode)); std::copy (mCodeBlock.begin(), mCodeBlock.end(), std::back_inserter (mCode)); Codes loop2; Generator::jump (loop2, -static_cast<int> (mCodeBlock.size()+expr.size()+skip.size())); if (loop.size()!=loop2.size()) throw std::logic_error ( "internal compiler error: failed to generate a while loop"); std::copy (loop2.begin(), loop2.end(), std::back_inserter (mCode)); mState = WhileEndwhileState; return true; } else if (keyword==Scanner::K_if || keyword==Scanner::K_while) { // nested ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals); if (parser.parseKeyword (keyword, loc, scanner)) scanner.scan (parser); parser.appendCode (mCodeBlock); return true; } else { mLineParser.reset(); if (mLineParser.parseKeyword (keyword, loc, scanner)) scanner.scan (mLineParser); return true; } }
bool ControlParser::parseIfBody (int keyword, const TokenLoc& loc, Scanner& scanner) { if (keyword==Scanner::K_endif || keyword==Scanner::K_elseif || keyword==Scanner::K_else) { std::pair<Codes, Codes> entry; if (mState!=IfElseBodyState) mExprParser.append (entry.first); std::copy (mCodeBlock.begin(), mCodeBlock.end(), std::back_inserter (entry.second)); mIfCode.push_back (entry); mCodeBlock.clear(); if (keyword==Scanner::K_endif) { // store code for if-cascade Codes codes; for (IfCodes::reverse_iterator iter (mIfCode.rbegin()); iter!=mIfCode.rend(); ++iter) { Codes block; if (iter!=mIfCode.rbegin()) Generator::jump (iter->second, codes.size()+1); if (!iter->first.empty()) { // if or elseif std::copy (iter->first.begin(), iter->first.end(), std::back_inserter (block)); Generator::jumpOnZero (block, iter->second.size()+1); } std::copy (iter->second.begin(), iter->second.end(), std::back_inserter (block)); std::swap (codes, block); std::copy (block.begin(), block.end(), std::back_inserter (codes)); } std::copy (codes.begin(), codes.end(), std::back_inserter (mCode)); mIfCode.clear(); mState = IfEndifState; } else if (keyword==Scanner::K_elseif) { mExprParser.reset(); scanner.scan (mExprParser); mState = IfElseifEndState; } else if (keyword==Scanner::K_else) { mState = IfElseJunkState; /// \todo should be IfElseEndState; add an option for that } return true; } else if (keyword==Scanner::K_if || keyword==Scanner::K_while) { // nested ControlParser parser (getErrorHandler(), getContext(), mLocals, mLiterals); if (parser.parseKeyword (keyword, loc, scanner)) scanner.scan (parser); parser.appendCode (mCodeBlock); return true; } else { mLineParser.reset(); if (mLineParser.parseKeyword (keyword, loc, scanner)) scanner.scan (mLineParser); return true; } }
TableInfo phuffman::utility::BuildTable(InputIterator first, InputIterator last, Codes& table) { using namespace std; typedef DepthCounterNode Node; typedef multimap<size_t, Node*> HuffmanTree; typedef vector<Node*> Nodes; assert(distance(first, last) <= constants::MAXIMUM_DATABLOCK_SIZE); assert(table.size() >= constants::ALPHABET_SIZE); HuffmanTree tree; Nodes leafs; TableInfo info; // Initialize tree { Frequencies frequencies = CountFrequencies(first, last); Frequencies::const_iterator first = frequencies.begin(), last = frequencies.end(); while (first != last) { Node* leaf = new Node(first->symbol); tree.insert(make_pair(first->frequency, leaf)); leafs.push_back(leaf); ++first; } } // Build tree { for (size_t i=0, size=tree.size(); i<size-1; ++i) { HuffmanTree::iterator first = tree.begin(), second = tree.begin(); ++second; size_t freq = first->first + second->first; // Calculate freq for a node Node* node = new Node(first->second, second->second); ++second; tree.erase(first, second); // Remove two nodes with the smallest frequency tree.insert(make_pair(freq, node)); // Add node that points to previosly removed nodes } assert(tree.size() == 1); } // Count codelengths // In fact, codelengths are already counted in the 'depth' member of a node // There is only one exception: if the tree contains only one object, we need to set it's depth manually Node* root = tree.begin()->second; root->depth = 1; // Sort nodes by codelength sort(leafs.begin(), leafs.end(), TreeComparator); // Build table { Nodes::const_iterator first = leafs.begin(), last = leafs.end(); Node *curNode = *first; info.maximum_codelength = curNode->depth; Code curCode = CodeMake(curNode->depth, 0); table[curNode->element] = curCode; ++first; while (first != last) { assert(curNode->depth >= curCode.codelength); curNode = *first; // If current codeword and next codeword have equal lengths if (curNode->depth == curCode.codelength) { // Just increase codeword by 1 curCode.code += 1; } // Otherwise else { // Increase codeword by 1 and _after_ that shift codeword right curCode.code = (curCode.code + 1) >> (curNode->depth - curCode.codelength); } curCode.codelength = curNode->depth; table[curNode->element] = curCode; ++first; } } delete root; return info; }