示例#1
0
    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;
        }
    }
示例#2
0
    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;
        }
    }
示例#3
0
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;
}