<commit_before>#include <getopt.h>
#include "dlib/bam_util.h"

int usage(char **argv, int retcode=EXIT_FAILURE) {
    fprintf(stderr, "MASKRIPPER version %s.\n"
                    "Usage: maskripper <opts> in.bam out.bam\n"
                    "Flags:\n-m: Minimum trimmed read length. Default: 0.\n"
                    "-l: output compression level. Default: 6.\n"
                    "-S: output in sam format.\n"
                    "-s: perform single-end analyisis. This option results in imbalanced pairs on paired-end data.\n"
                    "Use - for stdin or stdout.\n", MASKRIPPER_VERSION);
    return retcode;
}
struct opts_t {
    uint8_t *data;
    uint32_t l_data:16;
    uint32_t m_data:16;
    uint32_t n_cigar:8;
    uint32_t min_trimmed_len:8;
    ~opts_t() {if(data) free(data);}
    void resize(uint32_t new_min) {
        if(new_min > m_data) {
            m_data = new_min;
            kroundup32(m_data);
            data = (uint8_t *)realloc(data, m_data * sizeof(uint8_t));
        }
    }
};

static int trim_ns(bam1_t *b, void *data) {
    // Currently passes all reads to keep balanced pairs. TODO: rewrite for pairs of reads and filter if both fail.
    opts_t *op((opts_t *)data);
    assert(bam_aux_get(b, "PV"));
    std::vector<uint8_t> aux(bam_get_aux(b), bam_get_aux(b) + bam_get_l_aux(b));
    int tmp;
    uint8_t *const seq(bam_get_seq(b));
    uint32_t *const cigar(bam_get_cigar(b));
    op->n_cigar = b->core.n_cigar;
    op->resize(b->l_data); // Make sure it's big enough to hold everything.
    memcpy(op->data, b->data, b->core.l_qname);

    // Get #Ns at the beginning
    for(tmp = 0; bam_seqi(seq, tmp) == dlib::htseq::HTS_N; ++tmp);
    const int n_start(tmp);

    if(tmp == b->core.l_qseq - 1) // all bases are N -- garbage read
         return 1; // Currently outputting to avoid

    // Get #Ns at the end
    for(tmp = b->core.l_qseq - 1; bam_seqi(seq, tmp) == dlib::htseq::HTS_N; --tmp);
    const int n_end(b->core.l_qseq - 1 - tmp);

    // Get new length for read
    const int final_len(b->core.l_qseq - n_end - n_start);
    if(final_len < op->min_trimmed_len) // Too short.
        return 1;

    if(n_end) {
        if((tmp = bam_cigar_oplen(cigar[b->core.n_cigar - 1]) - n_end) == 0) {
            LOG_DEBUG("Entire cigar operation is the softclip. Decrease the number of new cigar operations.\n");
            --op->n_cigar;
        } else {
            LOG_DEBUG("Updating second cigar operation in-place.\n");
            cigar[b->core.n_cigar - 1] = bam_cigar_gen(tmp, BAM_CSOFT_CLIP);
        }
    }

    // Get new n_cigar.
    if((tmp = bam_cigar_oplen(*cigar) - n_start) == 0) {
        --op->n_cigar;
        memcpy(op->data + b->core.l_qname, cigar + 1, op->n_cigar << 2); // << 2 for 4 bit per cigar op
    } else {
        if(n_start) *cigar = bam_cigar_gen(tmp, BAM_CSOFT_CLIP);
        memcpy(op->data + b->core.l_qname, cigar, op->n_cigar << 2);
    }
    uint8_t *opseq(op->data + b->core.l_qname + (op->n_cigar << 2)); // Pointer to the seq region of new data field.
    for(tmp = 0; tmp < final_len >> 1; ++tmp) {
        opseq[tmp] = (bam_seqi(seq, ((tmp << 1) + n_start)) << 4) | (bam_seqi(seq, (tmp << 1) + n_start + 1));
        assert(bam_seqi(opseq, tmp * 2) == bam_seqi(seq, (2 * tmp + n_start)));
        assert(bam_seqi(opseq, tmp * 2 + 1) == bam_seqi(seq, (2 * tmp + n_start + 1)));
    }
#if 0
    char tmpbuf[300];
    for(tmp = 0; tmp < final_len; ++tmp) {
        tmpbuf[tmp] = seq_nt16_str[bam_seqi(opseq, tmp)];
    }
    tmpbuf[tmp] = '\0';
    assert(strcmp(tmpbuf, "ANNCNNNGNNNNTNNNNCNNGGNNNNNNNNNCNNNNCNNNNNNNNAAAANNTNNNAAAAAAAAAAGAGAGAGGGAGAGAGACTATACACAGGCACCACCACATTTGGCTAATTTTT") == 0);
#endif

    // Copy in qual and all of aux.
    tmp = bam_get_l_aux(b);
    memcpy(opseq + ((final_len + 1) >> 1), bam_get_qual(b) + n_start, final_len + tmp);
    // Switch data strings
    std::swap(op->data, b->data);
    b->core.n_cigar = op->n_cigar;
    //b->l_data = b->core.l_qname + (op->n_cigar << 2) + ((final_len + 1) >> 1) + final_len + tmp;
    b->core.l_qseq = final_len;
    memcpy(bam_get_aux(b), aux.data(), aux.size());
    b->l_data = (bam_get_aux(b) - b->data) + aux.size();
    //trim_array_tags(b, n_start, n_end, final_len);
    if(n_end)
        bam_aux_append(b, "NE", 'i', sizeof(int), (uint8_t *)&n_end);
    if(n_start)
        bam_aux_append(b, "NS", 'i', sizeof(int), (uint8_t *)&n_start);
    const uint32_t *pvar = (uint32_t *)dlib::array_tag(b, "PV");
    std::vector<uint32_t>pvals(pvar + n_start, pvar + final_len + n_start);
    const uint32_t *fvar = (uint32_t *)dlib::array_tag(b, "FA");
    std::vector<uint32_t>fvals(fvar + n_start, fvar + final_len + n_start);
    bam_aux_del(b, bam_aux_get(b, "PV"));
    bam_aux_del(b, bam_aux_get(b, "FA"));
    dlib::bam_aux_array_append(b, "PV", 'I', sizeof(uint32_t), final_len, (uint8_t *)pvals.data());
    dlib::bam_aux_array_append(b, "FA", 'I', sizeof(uint32_t), final_len, (uint8_t *)fvals.data());
    return 0;
}

static int pe_trim_ns(bam1_t *b1, bam1_t *b2, void *aux)
{
    return trim_ns(b1, aux) && trim_ns(b2, aux);
}

int main(int argc, char *argv[]) {
    if(argc < 3)
        return usage(argv);

    if(strcmp(argv[1], "--help") == 0)
        return usage(argv, EXIT_SUCCESS);

    int c;
    int is_se{0};
    char out_mode[4] = "wb";
    opts_t opts{0};
    while((c = getopt(argc, argv, "m:l:h?sS")) > -1) {
        switch(c) {
        case 'm': opts.min_trimmed_len = (uint32_t)atoi(optarg); break;
        case 'l': out_mode[2] = atoi(optarg) % 10 + '0'; break;
        case 's': is_se = 1; break;
        case 'S': sprintf(out_mode, "w"); break;
        case 'h': case '?': return usage(argv, EXIT_SUCCESS);
        }
    }
    if(argc - 2 != optind)
        LOG_EXIT("Required: precisely two positional arguments (in bam, out bam).\n");

    LOG_DEBUG("ZOUNDS\n");
    // Actually this function. You can't really apply a null function....
    dlib::BamHandle inHandle(argv[optind]);
    dlib::BamHandle outHandle(argv[optind + 1], inHandle.header, out_mode);
    if(is_se) {
        dlib::abstract_single_iter(inHandle.fp, inHandle.header, outHandle.fp,
                                   &trim_ns, (void *)&opts);
    } else {
        dlib::abstract_pair_iter(inHandle.fp, inHandle.header, outHandle.fp, &pe_trim_ns, (void *)&opts);
    }
    return EXIT_SUCCESS;
}
<commit_msg>Properly handle reverse-aligned read aux tags.<commit_after>#include <getopt.h>
#include "dlib/bam_util.h"

int usage(char **argv, int retcode=EXIT_FAILURE) {
    fprintf(stderr, "MASKRIPPER version %s.\n"
                    "Usage: maskripper <opts> in.bam out.bam\n"
                    "Flags:\n-m: Minimum trimmed read length. Default: 0.\n"
                    "-l: output compression level. Default: 6.\n"
                    "-S: output in sam format.\n"
                    "-s: perform single-end analyisis. This option results in imbalanced pairs on paired-end data.\n"
                    "Use - for stdin or stdout.\n", MASKRIPPER_VERSION);
    return retcode;
}
struct opts_t {
    uint8_t *data;
    uint32_t l_data:16;
    uint32_t m_data:16;
    uint32_t n_cigar:8;
    uint32_t min_trimmed_len:8;
    ~opts_t() {if(data) free(data);}
    void resize(uint32_t new_min) {
        if(new_min > m_data) {
            m_data = new_min;
            kroundup32(m_data);
            data = (uint8_t *)realloc(data, m_data * sizeof(uint8_t));
        }
    }
};

static int trim_ns(bam1_t *b, void *data) {
    // Currently passes all reads to keep balanced pairs. TODO: rewrite for pairs of reads and filter if both fail.
    opts_t *op((opts_t *)data);
    assert(bam_aux_get(b, "PV"));
    std::vector<uint8_t> aux(bam_get_aux(b), bam_get_aux(b) + bam_get_l_aux(b));
    int tmp;
    uint8_t *const seq(bam_get_seq(b));
    uint32_t *const cigar(bam_get_cigar(b));
    op->n_cigar = b->core.n_cigar;
    op->resize(b->l_data); // Make sure it's big enough to hold everything.
    memcpy(op->data, b->data, b->core.l_qname);

    // Get #Ns at the beginning
    for(tmp = 0; bam_seqi(seq, tmp) == dlib::htseq::HTS_N; ++tmp);
    const int n_start(tmp);

    if(tmp == b->core.l_qseq - 1) // all bases are N -- garbage read
         return 1; // Currently outputting to avoid

    // Get #Ns at the end
    for(tmp = b->core.l_qseq - 1; bam_seqi(seq, tmp) == dlib::htseq::HTS_N; --tmp);
    const int n_end(b->core.l_qseq - 1 - tmp);

    // Get new length for read
    const int final_len(b->core.l_qseq - n_end - n_start);
    if(final_len < op->min_trimmed_len) // Too short.
        return 1;

    if(n_end) {
        if((tmp = bam_cigar_oplen(cigar[b->core.n_cigar - 1]) - n_end) == 0) {
            LOG_DEBUG("Entire cigar operation is the softclip. Decrease the number of new cigar operations.\n");
            --op->n_cigar;
        } else {
            LOG_DEBUG("Updating second cigar operation in-place.\n");
            cigar[b->core.n_cigar - 1] = bam_cigar_gen(tmp, BAM_CSOFT_CLIP);
        }
    }

    // Get new n_cigar.
    if((tmp = bam_cigar_oplen(*cigar) - n_start) == 0) {
        --op->n_cigar;
        memcpy(op->data + b->core.l_qname, cigar + 1, op->n_cigar << 2); // << 2 for 4 bit per cigar op
    } else {
        if(n_start) *cigar = bam_cigar_gen(tmp, BAM_CSOFT_CLIP);
        memcpy(op->data + b->core.l_qname, cigar, op->n_cigar << 2);
    }
    uint8_t *opseq(op->data + b->core.l_qname + (op->n_cigar << 2)); // Pointer to the seq region of new data field.
    for(tmp = 0; tmp < final_len >> 1; ++tmp) {
        opseq[tmp] = (bam_seqi(seq, ((tmp << 1) + n_start)) << 4) | (bam_seqi(seq, (tmp << 1) + n_start + 1));
        assert(bam_seqi(opseq, tmp * 2) == bam_seqi(seq, (2 * tmp + n_start)));
        assert(bam_seqi(opseq, tmp * 2 + 1) == bam_seqi(seq, (2 * tmp + n_start + 1)));
    }
#if 0
    char tmpbuf[300];
    for(tmp = 0; tmp < final_len; ++tmp) {
        tmpbuf[tmp] = seq_nt16_str[bam_seqi(opseq, tmp)];
    }
    tmpbuf[tmp] = '\0';
    assert(strcmp(tmpbuf, "ANNCNNNGNNNNTNNNNCNNGGNNNNNNNNNCNNNNCNNNNNNNNAAAANNTNNNAAAAAAAAAAGAGAGAGGGAGAGAGACTATACACAGGCACCACCACATTTGGCTAATTTTT") == 0);
#endif

    // Copy in qual and all of aux.
    tmp = bam_get_l_aux(b);
    memcpy(opseq + ((final_len + 1) >> 1), bam_get_qual(b) + n_start, final_len + tmp);
    // Switch data strings
    std::swap(op->data, b->data);
    b->core.n_cigar = op->n_cigar;
    //b->l_data = b->core.l_qname + (op->n_cigar << 2) + ((final_len + 1) >> 1) + final_len + tmp;
    b->core.l_qseq = final_len;
    memcpy(bam_get_aux(b), aux.data(), aux.size());
    b->l_data = (bam_get_aux(b) - b->data) + aux.size();
    //trim_array_tags(b, n_start, n_end, final_len);
    if(n_end)
        bam_aux_append(b, "NE", 'i', sizeof(int), (uint8_t *)&n_end);
    if(n_start)
        bam_aux_append(b, "NS", 'i', sizeof(int), (uint8_t *)&n_start);
    const uint32_t *pvar = (uint32_t *)dlib::array_tag(b, "PV");
    tmp = b->core.flag & BAM_FREVERSE ? n_end: n_start;
    std::vector<uint32_t>pvals(pvar + tmp, pvar + final_len + tmp);
    const uint32_t *fvar = (uint32_t *)dlib::array_tag(b, "FA");
    std::vector<uint32_t>fvals(fvar + tmp, fvar + final_len + tmp);
    bam_aux_del(b, bam_aux_get(b, "PV"));
    bam_aux_del(b, bam_aux_get(b, "FA"));
    dlib::bam_aux_array_append(b, "PV", 'I', sizeof(uint32_t), final_len, (uint8_t *)pvals.data());
    dlib::bam_aux_array_append(b, "FA", 'I', sizeof(uint32_t), final_len, (uint8_t *)fvals.data());
    return 0;
}

static int pe_trim_ns(bam1_t *b1, bam1_t *b2, void *aux)
{
    return trim_ns(b1, aux) && trim_ns(b2, aux);
}

int main(int argc, char *argv[]) {
    if(argc < 3)
        return usage(argv);

    if(strcmp(argv[1], "--help") == 0)
        return usage(argv, EXIT_SUCCESS);

    int c;
    int is_se{0};
    char out_mode[4] = "wb";
    opts_t opts{0};
    while((c = getopt(argc, argv, "m:l:h?sS")) > -1) {
        switch(c) {
        case 'm': opts.min_trimmed_len = (uint32_t)atoi(optarg); break;
        case 'l': out_mode[2] = atoi(optarg) % 10 + '0'; break;
        case 's': is_se = 1; break;
        case 'S': sprintf(out_mode, "w"); break;
        case 'h': case '?': return usage(argv, EXIT_SUCCESS);
        }
    }
    if(argc - 2 != optind)
        LOG_EXIT("Required: precisely two positional arguments (in bam, out bam).\n");

    LOG_DEBUG("ZOUNDS\n");
    // Actually this function. You can't really apply a null function....
    dlib::BamHandle inHandle(argv[optind]);
    dlib::BamHandle outHandle(argv[optind + 1], inHandle.header, out_mode);
    if(is_se) {
        dlib::abstract_single_iter(inHandle.fp, inHandle.header, outHandle.fp,
                                   &trim_ns, (void *)&opts);
    } else {
        dlib::abstract_pair_iter(inHandle.fp, inHandle.header, outHandle.fp, &pe_trim_ns, (void *)&opts);
    }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "parser.hpp"

#include "ast.hpp"
#include "tokens.hpp"
#include "string_slice.hpp"
#include "scope_stack.hpp"

#include <iostream>
#include <exception>
#include <string>
#include <unordered_map>

class ParseError: std::exception
{
public:
	Token token;
	ParseError(Token token): token {token} {}
	virtual const char* what() const noexcept {
		return "Parse error.";
	}
};

class Parser
{
	std::vector<Token>::const_iterator begin;
	std::vector<Token>::const_iterator end;
	std::vector<Token>::const_iterator token_iter;

	ScopeStack scope_stack;

	std::unordered_map<StringSlice, int> op_prec; // Binary operator precidence map
	std::string binary_op_list; // Storage for operator strings, referenced by op_prec

	AST ast;

	void add_op_prec(const char* op, int prec) {
		auto itr = binary_op_list.cend();
		binary_op_list.append(op);
		op_prec.emplace(StringSlice(itr, binary_op_list.cend()), prec);
	}

public:
	Parser(const std::vector<Token>& tokens): begin {tokens.cbegin()}, end {tokens.cend()}, token_iter {tokens.cbegin()} {
		// Build operator precidence map
		// Note that this is only for function-like binary operators.
		// Non-function-like operators such as . have their own rules.
		// Unary operators always bind more tightly than binary operators.
		binary_op_list.reserve(256); // Make sure we have enough space to avoid iterator invalidation
		binary_op_list.append(" "); // To get it started, so that add_op_prec()'s logic works

		add_op_prec("*", 100); // Multiply
		add_op_prec("/", 100); // Divide
		add_op_prec("//", 100); // Modulus/remainder

		add_op_prec("+", 90); // Add
		add_op_prec("-", 90); // Subtract

		add_op_prec("<<", 80); // Bit shift left
		add_op_prec(">>", 80); // Bit shift right

		add_op_prec("<", 70); // Less than
		add_op_prec(">", 70); // Greater than
		add_op_prec("<=", 70); // Less than or equal
		add_op_prec(">=", 70); // Greater than or equal

		add_op_prec("==", 60); // Equal
		add_op_prec("!=", 60); // Not equal

		add_op_prec("&", 50); // Bit-wise and

		add_op_prec("^", 40); // Bit-wise xor

		add_op_prec("|", 30); // Bit-wise or

		add_op_prec("and", 20); // Logical and

		add_op_prec("or", 10); // Logical or

		add_op_prec("=", -10); // Assignment
	}

	AST parse() {
		// Iterate over the tokens
		while (token_iter < end) {
			skip_comments_and_newlines();

			// Call the appropriate parsing function for the token type
			switch (token_iter->type) {
					// Function declaration
				case K_FUNC: {
					auto subtree = parse_func_definition();
					// TODO: ast.roots.push_back(subtree);
					break;
				}

				case LEX_EOF:
					goto done;

					// Something else, not allowed at this level
				default:
					throw ParseError {*token_iter};
			}

		}

done:

		return std::move(ast);
	}

private:

	void skip_comments() {
		while (token_iter->type == COMMENT || token_iter->type == DOC_COMMENT)
			++token_iter;
	}

	void skip_comments_and_newlines() {
		while (token_iter->type == COMMENT || token_iter->type == DOC_COMMENT || token_iter->type == NEWLINE)
			++token_iter;
	}

	// Returns whether the token is a function identifier or operator
	bool token_is_function(Token t) {
		if (t.type == OPERATOR) {
			return true;
		} else if (t.type == IDENTIFIER &&
		           scope_stack.is_symbol_in_scope(t.text) &&
		           scope_stack.symbol_type(t.text) == SymbolType::FUNCTION
		          ) {
			return true;
		} else {
			return false;
		}
	}

	// All the parsing methods below should adhere to the following
	// conventions:
	//
	// - When they are called, they assume token_iter is on the first
	//   character for them to consume.
	//
	// - When they return, they leave token_iter on the first character that
	//   they don't consume (as opposed to the last character they do).  In
	//   particular they should not consume trailing whitespace unless it
	//   is actually syntactically meaningful to them.
	//
	// - When calling another parsing method, the call should be done in a
	//   state consistent with the above, and handle things afterwards
	//   assuming a state consistent with the above.

	// Expression
	std::unique_ptr<ExprNode> parse_expression() {
		switch (token_iter->type) {
				// Scope
			case LPAREN: {
				return parse_scope();
			}

			// Return statement
			case K_RETURN: {
				// TODO
				throw ParseError {*token_iter};
			}

			// Declaration
			case K_FUNC:
			case K_STRUCT:
			case K_LET: {
				return parse_declaration();
			}

			// Literal
			case INTEGER_LIT:
			case FLOAT_LIT:
			case STRING_LIT:
			case RAW_STRING_LIT: {
				// TODO
				throw ParseError {*token_iter};
			}

			// Identifier or operator, means this is a more
			// complex case.
			case IDENTIFIER:
			case OPERATOR: {
				// Check if symbol is in scope
				if (!scope_stack.is_symbol_in_scope(token_iter->text)) {
					throw ParseError {*token_iter};
				}

				// If next token is a terminator, it's a singleton
				if (token_iter[1].type == NEWLINE || token_iter[1].type == COMMA) {
					// TODO
					throw ParseError {*token_iter};
				}
				// If next token is a [, it's a function call
				else if (token_iter[1].type == LSQUARE) {
					return parse_standard_func_call();
				}
				// If next token is an identifier or operator, it's a compound expression
				else if (token_iter[1].type == IDENTIFIER || token_iter[1].type == OPERATOR) {
					parse_compound_expression();
				}
				// Otherwise, error
				else {
					throw ParseError {*token_iter};
				}
			}

			default: {
				throw ParseError {*token_iter};
			}
		}
	}

	// Compound expression
	std::unique_ptr<ExprNode> parse_compound_expression() {
		// If it's a unary operator, parse to the first
		// non-operator
		if (token_is_function(*token_iter)) {
			// Unary operator, consume to point of

		}

		// Parse binary operator

		// ???
	}

	// Declaration
	std::unique_ptr<DeclNode> parse_declaration() {
		switch (token_iter->type) {
			case K_FUNC: {
				return parse_func_definition();
			}

			default: {
				throw ParseError {*token_iter};
			}
		}
	}

	// Function definition
	std::unique_ptr<FuncDeclNode> parse_func_definition() {
		auto node = std::unique_ptr<FuncDeclNode>(new FuncDeclNode);

		// Function name
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type == IDENTIFIER || token_iter->type == OPERATOR) {
			node->name = token_iter->text;
		} else {
			throw ParseError {*token_iter};
		}

		// Open bracket
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type != LSQUARE)
			throw ParseError {*token_iter};

		// Parameters
		while (true) {
			// Parameter name
			++token_iter;
			skip_comments_and_newlines();
			StringSlice name;
			if (token_iter->type == IDENTIFIER)
				name = token_iter->text;
			else if (token_iter->type == RSQUARE)
				break;
			else
				throw ParseError {*token_iter};

			// Colon
			++token_iter;
			skip_comments_and_newlines();
			if (token_iter->type != COLON)
				throw ParseError {*token_iter};

			// Parameter type
			// TODO: types aren't just names, need to evaluate full type expression here.
			++token_iter;
			skip_comments_and_newlines();
			if (token_iter->type == IDENTIFIER)
				node->parameters.push_back(NameTypePair {name, std::unique_ptr<TypeExprNode>(new TypeExprNode())});
			else
				throw ParseError {*token_iter};

			// Either a comma or closing square bracket
			++token_iter;
			skip_comments_and_newlines();
			if (token_iter->type == COMMA)
				continue;
			else if (token_iter->type == RSQUARE)
				break;
			else
				throw ParseError {*token_iter};
		}

		// ->
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type != OPERATOR || token_iter->text != "->")
			throw ParseError {*token_iter};

		// Return type
		// TODO: types aren't just names, need to evaluate full type expression here.
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type == IDENTIFIER)
			node->return_type = std::unique_ptr<TypeExprNode>(new TypeExprNode());
		else
			throw ParseError {*token_iter};

		// Push name onto scope stack
		scope_stack.push_symbol(node->name, SymbolType::FUNCTION);

		// Function body
		// TODO
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type == LPAREN) {
			node->body = parse_scope();
		}

		std::cout << "\tFunction definition: " << node->name << std::endl;

		return node;
	}

	// Standard function call syntax
	std::unique_ptr<FuncCallNode> parse_standard_func_call() {
		auto node = std::unique_ptr<FuncCallNode>(new FuncCallNode());

		// Get function name
		if (token_iter->type == IDENTIFIER || token_iter->type == OPERATOR) {
			node->name = token_iter->text;
		} else {
			throw ParseError {*token_iter};
		}

		// [
		++token_iter;
		skip_comments();
		if (token_iter->type != LSQUARE)
			throw ParseError {*token_iter};
		++token_iter;

		while (true) {
			skip_comments_and_newlines();

			// ]?
			if (token_iter->type == RSQUARE) {
				++token_iter;
				break;
			}

			// TODO: parse arguments
			++token_iter;
		}

		return node;
	}

	// Scope
	std::unique_ptr<ScopeNode> parse_scope() {
		auto node = std::unique_ptr<ScopeNode>(new ScopeNode());

		// Open scope
		if (token_iter->type != LPAREN)
			throw ParseError {*token_iter};
		++token_iter;

		// Push this scope
		scope_stack.push_scope();

		while (true) {
			skip_comments_and_newlines();

			// Close scope?
			if (token_iter->type == RPAREN) {
				++token_iter;
				break;
			}
			// Should be an expression
			else {
				node->expressions.push_back(parse_expression());
			}
		}

		// Pop this scope
		scope_stack.pop_scope();

		return node;
	}
};

AST parse_tokens(const std::vector<Token>& tokens)
{
	Parser parser(tokens);
	AST ast;

	try {
		ast = parser.parse();
	} catch (ParseError e) {
		std::cout << "Parse Error: " << "[L" << e.token.line + 1 << ", C" << e.token.column << ", " << e.token.type << "]:\t" << " " << e.token.text << std::endl;
		throw e;
	}

	return ast;
}<commit_msg>Starting to get operators to work... but mostly just segfaults.<commit_after>#include "parser.hpp"

#include "ast.hpp"
#include "tokens.hpp"
#include "string_slice.hpp"
#include "scope_stack.hpp"

#include <iostream>
#include <exception>
#include <string>
#include <unordered_map>

class ParseError: std::exception
{
public:
	Token token;
	ParseError(Token token): token {token} {}
	virtual const char* what() const noexcept {
		return "Parse error.";
	}
};

class Parser
{
	std::vector<Token>::const_iterator begin;
	std::vector<Token>::const_iterator end;
	std::vector<Token>::const_iterator token_iter;

	ScopeStack scope_stack;

	std::unordered_map<StringSlice, int> op_prec; // Binary operator precidence map
	std::string binary_op_list; // Storage for operator strings, referenced by op_prec

	AST ast;

	void add_op_prec(const char* op, int prec) {
		auto itr = binary_op_list.cend();
		binary_op_list.append(op);
		op_prec.emplace(StringSlice(itr, binary_op_list.cend()), prec);
	}

public:
	Parser(const std::vector<Token>& tokens): begin {tokens.cbegin()}, end {tokens.cend()}, token_iter {tokens.cbegin()} {
		// Build operator precidence map
		// Note that this is only for function-like binary operators.
		// Non-function-like operators such as . have their own rules.
		// Unary operators always bind more tightly than binary operators.
		binary_op_list.reserve(256); // Make sure we have enough space to avoid iterator invalidation
		binary_op_list.append(" "); // To get it started, so that add_op_prec()'s logic works

		add_op_prec("*", 100); // Multiply
		add_op_prec("/", 100); // Divide
		add_op_prec("//", 100); // Modulus/remainder

		add_op_prec("+", 90); // Add
		add_op_prec("-", 90); // Subtract

		add_op_prec("<<", 80); // Bit shift left
		add_op_prec(">>", 80); // Bit shift right

		add_op_prec("<", 70); // Less than
		add_op_prec(">", 70); // Greater than
		add_op_prec("<=", 70); // Less than or equal
		add_op_prec(">=", 70); // Greater than or equal

		add_op_prec("==", 60); // Equal
		add_op_prec("!=", 60); // Not equal

		add_op_prec("&", 50); // Bit-wise and

		add_op_prec("^", 40); // Bit-wise xor

		add_op_prec("|", 30); // Bit-wise or

		add_op_prec("and", 20); // Logical and

		add_op_prec("or", 10); // Logical or

		add_op_prec("=", -10); // Assignment
	}

	AST parse() {
		// Iterate over the tokens
		while (token_iter < end) {
			skip_comments_and_newlines();

			// Call the appropriate parsing function for the token type
			switch (token_iter->type) {
					// Function declaration
				case K_FUNC: {
					auto subtree = parse_func_definition();
					// TODO: ast.roots.push_back(subtree);
					break;
				}

				case LEX_EOF:
					goto done;

					// Something else, not allowed at this level
				default:
					throw ParseError {*token_iter};
			}

		}

done:

		return std::move(ast);
	}

private:

	void skip_comments() {
		while (token_iter->type == COMMENT || token_iter->type == DOC_COMMENT)
			++token_iter;
	}

	void skip_comments_and_newlines() {
		while (token_iter->type == COMMENT || token_iter->type == DOC_COMMENT || token_iter->type == NEWLINE)
			++token_iter;
	}

	// Returns whether the token is a function identifier or operator
	bool token_is_function(Token t) {
		if (t.type == OPERATOR) {
			return true;
		} else if (t.type == IDENTIFIER &&
		           scope_stack.is_symbol_in_scope(t.text) &&
		           scope_stack.symbol_type(t.text) == SymbolType::FUNCTION
		          ) {
			return true;
		} else {
			return false;
		}
	}

	// Returns whether the token is a variable identifier
	bool token_is_variable(Token t) {
		if (t.type == IDENTIFIER &&
		        scope_stack.is_symbol_in_scope(t.text) &&
		        scope_stack.symbol_type(t.text) == SymbolType::VARIABLE
		   ) {
			return true;
		} else {
			return false;
		}
	}

	// All the parsing methods below should adhere to the following
	// conventions:
	//
	// - When they are called, they assume token_iter is on the first
	//   character for them to consume.
	//
	// - When they return, they leave token_iter on the first character that
	//   they don't consume (as opposed to the last character they do).  In
	//   particular they should not consume trailing whitespace unless it
	//   is actually syntactically meaningful to them.
	//
	// - When calling another parsing method, the call should be done in a
	//   state consistent with the above, and handle things afterwards
	//   assuming a state consistent with the above.

	// Expression
	std::unique_ptr<ExprNode> parse_expression() {
		switch (token_iter->type) {
				// Scope
			case LPAREN: {
				return parse_scope();
			}

			// Return statement
			case K_RETURN: {
				// TODO
				throw ParseError {*token_iter};
			}

			// Declaration
			case K_FUNC:
			case K_STRUCT:
			case K_LET: {
				return parse_declaration();
			}

			// Literal
			case INTEGER_LIT:
			case FLOAT_LIT:
			case STRING_LIT:
			case RAW_STRING_LIT: {
				// TODO
				throw ParseError {*token_iter};
			}

			// Identifier or operator, means this is a more
			// complex case.
			case IDENTIFIER:
			case OPERATOR: {
				// Check if symbol is in scope
				if (!scope_stack.is_symbol_in_scope(token_iter->text)) {
					throw ParseError {*token_iter};
				}

				// If next token is a terminator, it's a singleton
				if (token_iter[1].type == NEWLINE || token_iter[1].type == COMMA) {
					// TODO
					throw ParseError {*token_iter};
				}
				// If next token is a [, it's a function call
				else if (token_iter[1].type == LSQUARE) {
					return parse_standard_func_call();
				}
				// If next token is an identifier or operator, it's a compound expression
				else if (token_iter[1].type == IDENTIFIER || token_iter[1].type == OPERATOR) {
					parse_compound_expression();
				}
				// Otherwise, error
				else {
					throw ParseError {*token_iter};
				}
			}

			default: {
				throw ParseError {*token_iter};
			}
		}
	}

	// Compound expression
	std::unique_ptr<ExprNode> parse_compound_expression() {
		// If it's a unary operator, parse to the first
		// non-operator
		if (token_is_function(*token_iter)) {
			// Unary operator, consume to point of

		}

		// Parse binary operator

		// ???
	}

	// Declaration
	std::unique_ptr<DeclNode> parse_declaration() {
		switch (token_iter->type) {
			case K_FUNC: {
				return parse_func_definition();
			}

			default: {
				throw ParseError {*token_iter};
			}
		}
	}

	// Function definition
	std::unique_ptr<FuncDeclNode> parse_func_definition() {
		auto node = std::unique_ptr<FuncDeclNode>(new FuncDeclNode);

		// Function name
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type == IDENTIFIER || token_iter->type == OPERATOR) {
			node->name = token_iter->text;
		} else {
			throw ParseError {*token_iter};
		}

		// Open bracket
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type != LSQUARE)
			throw ParseError {*token_iter};

		// Parameters
		while (true) {
			// Parameter name
			++token_iter;
			skip_comments_and_newlines();
			StringSlice name;
			if (token_iter->type == IDENTIFIER)
				name = token_iter->text;
			else if (token_iter->type == RSQUARE)
				break;
			else
				throw ParseError {*token_iter};

			// Colon
			++token_iter;
			skip_comments_and_newlines();
			if (token_iter->type != COLON)
				throw ParseError {*token_iter};

			// Parameter type
			// TODO: types aren't just names, need to evaluate full type expression here.
			++token_iter;
			skip_comments_and_newlines();
			if (token_iter->type == IDENTIFIER)
				node->parameters.push_back(NameTypePair {name, std::unique_ptr<TypeExprNode>(new TypeExprNode())});
			else
				throw ParseError {*token_iter};

			// Either a comma or closing square bracket
			++token_iter;
			skip_comments_and_newlines();
			if (token_iter->type == COMMA)
				continue;
			else if (token_iter->type == RSQUARE)
				break;
			else
				throw ParseError {*token_iter};
		}

		// ->
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type != OPERATOR || token_iter->text != "->")
			throw ParseError {*token_iter};

		// Return type
		// TODO: types aren't just names, need to evaluate full type expression here.
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type == IDENTIFIER)
			node->return_type = std::unique_ptr<TypeExprNode>(new TypeExprNode());
		else
			throw ParseError {*token_iter};

		// Push name onto scope stack
		scope_stack.push_symbol(node->name, SymbolType::FUNCTION);

		// Function body
		// TODO
		++token_iter;
		skip_comments_and_newlines();
		if (token_iter->type == LPAREN) {
			node->body = parse_scope();
		}

		std::cout << "\tFunction definition: " << node->name << std::endl;

		return node;
	}

	// Standard function call syntax
	std::unique_ptr<FuncCallNode> parse_standard_func_call() {
		auto node = std::unique_ptr<FuncCallNode>(new FuncCallNode());

		// Get function name
		if (token_iter->type == IDENTIFIER || token_iter->type == OPERATOR) {
			node->name = token_iter->text;
		} else {
			throw ParseError {*token_iter};
		}

		// [
		++token_iter;
		skip_comments();
		if (token_iter->type != LSQUARE)
			throw ParseError {*token_iter};
		++token_iter;

		skip_comments_and_newlines();

		// ]?
		if (token_iter->type == RSQUARE) {
			++token_iter;
			return node;
		}

		while (true) {
			node->parameters.push_back(parse_expression());

			skip_comments_and_newlines();

			// , or ]
			if (token_iter->type == COMMA) {
				++token_iter;
				continue;
			} else if (token_iter->type == RSQUARE) {
				++token_iter;
				break;
			}

			++token_iter;
			skip_comments_and_newlines();
		}

		return node;
	}

	// Unary function call syntax
	std::unique_ptr<FuncCallNode> parse_unary_func_call() {
		auto node = std::unique_ptr<FuncCallNode>(new FuncCallNode());

		// Get function name
		if (token_iter->type == IDENTIFIER || token_iter->type == OPERATOR) {
			node->name = token_iter->text;
		} else {
			throw ParseError {*token_iter};
		}
		++token_iter;

		// This token should be the argument
		switch (token_iter->type) {
				// Scope
			case LPAREN: {
				node->parameters.push_back(parse_scope());
				break;
			}

			// Literal
			case INTEGER_LIT:
			case FLOAT_LIT:
			case STRING_LIT:
			case RAW_STRING_LIT: {
				// TODO
				throw ParseError {*token_iter};
			}

			// Identifier or operator
			case IDENTIFIER:
			case OPERATOR: {
				// Check if symbol is in scope
				if (!scope_stack.is_symbol_in_scope(token_iter->text)) {
					throw ParseError {*token_iter};
				}

				// If next token is a [, it's a function call
				if (token_iter[1].type == LSQUARE) {
					node->parameters.push_back(parse_standard_func_call());
					break;
				}
				// If token is a function but not being called with normal
				// syntax, it has to be unary as well.
				else if (token_is_function(*token_iter)) {
					node->parameters.push_back(parse_unary_func_call());
					break;
				}
				// If token is a variable, but not being called as a function
				else if (token_is_variable(*token_iter)) {
					// TODO
					throw ParseError {*token_iter};
					break;
				}
				// Otherwise, error
				else {
					throw ParseError {*token_iter};
				}
			}

			default: {
				throw ParseError {*token_iter};
			}
		}

		return node;
	}

	// Binary infix function call syntax
	std::unique_ptr<FuncCallNode> parse_binary_func_call(/* Stuff goes here...*/) {
		auto node = std::unique_ptr<FuncCallNode>(new FuncCallNode());

		// TODO

		return node;
	}

	// Scope
	std::unique_ptr<ScopeNode> parse_scope() {
		auto node = std::unique_ptr<ScopeNode>(new ScopeNode());

		// Open scope
		if (token_iter->type != LPAREN)
			throw ParseError {*token_iter};
		++token_iter;

		// Push this scope
		scope_stack.push_scope();

		while (true) {
			skip_comments_and_newlines();

			// Close scope?
			if (token_iter->type == RPAREN) {
				++token_iter;
				break;
			}
			// Should be an expression
			else {
				node->expressions.push_back(parse_expression());
			}
		}

		// Pop this scope
		scope_stack.pop_scope();

		return node;
	}
};

AST parse_tokens(const std::vector<Token>& tokens)
{
	Parser parser(tokens);
	AST ast;

	try {
		ast = parser.parse();
	} catch (ParseError e) {
		std::cout << "Parse Error: " << "[L" << e.token.line + 1 << ", C" << e.token.column << ", " << e.token.type << "]:\t" << " " << e.token.text << std::endl;
		throw e;
	}

	return ast;
}<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/qmljsdocument.h>

#include <QFile>
#include <QList>
#include <QCoreApplication>
#include <QStringList>
#include <QFileInfo>
#include <QTime>
#include <QtDebug>

#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#ifdef __GNUC__
#  include <cxxabi.h>
#endif

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace std;

class ASTDump: protected Visitor
{
public:
    void operator()(const QString &fileName, const QByteArray &src, Node *ast) {
        _src = src;
        QString basename = fileName;
        int dotIdx = basename.lastIndexOf('.');
        if (dotIdx != -1)
            basename.truncate(dotIdx);
        basename.append(QLatin1String(".ast.dot"));
        out.open(basename.toUtf8().constData());

        out << "digraph AST { ordering=out;" << endl;
        // cout << "rankdir = \"LR\";" << endl;
        Node::accept(ast, this);

        typedef QPair<QByteArray, QByteArray> Pair;

        foreach (const Pair &conn, _connections)
            out << conn.first.constData() << " -> " << conn.second.constData() << endl;

        alignTerminals();

        out << "}" << endl;
        out.close();
        cout << qPrintable(basename) << endl;
    }

protected:
    void alignTerminals() {
        out<<"{ rank=same;" << endl;
        foreach (const QByteArray &terminalShape, _terminalShapes) {
            out << "  " << string(terminalShape) << ";" << endl;
        }
        out<<"}"<<endl;
    }

    static QByteArray name(Node *ast) {
#ifdef __GNUC__
        QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 12;
#else
        QByteArray name = typeid(*ast).name();
#endif
        return name;
    }

    QString spell(const SourceLocation &token) {
        return _src.mid(token.offset, token.length).replace('\'', "\\\\").replace('"', "\\\"");
    }

    void terminal(const SourceLocation &token) {
        if (!token.isValid())
            return;

        static int count = 1;
        QByteArray id = 't' + QByteArray::number(count++);
        Node *node = _stack.last();
        _connections.append(qMakePair(_id[node], id));

        QByteArray t;
        t.append(id);
        t.append(" [label = \"");
        t.append(spell(token).toUtf8());
        t.append("\" shape=rect]");
        _terminalShapes.append(t);
    }

    virtual void nonterminal(Node *ast) {
        Node::accept(ast, this);
    }

    virtual void node(Node *ast) {
        out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << endl;
    }

    virtual bool preVisit(Node *ast) {
        static int count = 1;
        const QByteArray id = 'n' + QByteArray::number(count++);
        _id[ast] = id;

        if (! _stack.isEmpty())
            _connections.append(qMakePair(_id[_stack.last()], id));

        _stack.append(ast);

        node(ast);

        return true;
    }

    virtual void postVisit(Node *) {
        _stack.removeLast();
    }

protected: // visiting methods:
    virtual bool visit(UiImport *ast) {
        terminal(ast->importToken);

        if (ast->importUri)
            nonterminal(ast->importUri);
        else
            terminal(ast->fileNameToken);

        terminal(ast->versionToken);
        terminal(ast->asToken);
        terminal(ast->importIdToken);
        terminal(ast->semicolonToken);
        return false;
    }

    virtual bool visit(UiObjectBinding *ast) {
        if (ast->hasOnToken) {
            nonterminal(ast->qualifiedTypeNameId);
            terminal(ast->colonToken);
            nonterminal(ast->qualifiedId);
        } else {
            nonterminal(ast->qualifiedId);
            terminal(ast->colonToken);
            nonterminal(ast->qualifiedTypeNameId);
        }
        nonterminal(ast->initializer);
        return false;
    }

    virtual bool visit(UiObjectDefinition *ast) {
        nonterminal(ast->qualifiedTypeNameId);
        nonterminal(ast->initializer);
        return false;
    }

    virtual bool visit(UiObjectInitializer *ast) {
        terminal(ast->lbraceToken);
        nonterminal(ast->members);
        terminal(ast->rbraceToken);
        return false;
    }

    virtual bool visit(UiScriptBinding *ast) {
        nonterminal(ast->qualifiedId);
        terminal(ast->colonToken);
        nonterminal(ast->statement);
        return false;
    }

    virtual bool visit(UiArrayBinding *ast) {
        nonterminal(ast->qualifiedId);
        terminal(ast->colonToken);
        terminal(ast->lbracketToken);
        nonterminal(ast->members);
        terminal(ast->rbracketToken);
        return false;
    }

    virtual bool visit(UiArrayMemberList *ast) {
        terminal(ast->commaToken);
        nonterminal(ast->member);
        nonterminal(ast->next);
        return false;
    }

    virtual bool visit(UiQualifiedId *ast) {
        terminal(ast->identifierToken);
        nonterminal(ast->next);
        return false;
    }

    virtual bool visit(UiPublicMember *ast) {
        // TODO: place the parameters...
//        UiParameterList *parameters;

        terminal(ast->defaultToken);
        terminal(ast->readonlyToken);
        terminal(ast->propertyToken);
        terminal(ast->typeModifierToken);
        terminal(ast->typeToken);
        terminal(ast->identifierToken);
        terminal(ast->colonToken);
        nonterminal(ast->statement);
        nonterminal(ast->binding);
        terminal(ast->semicolonToken);
        return false;
    }

    virtual bool visit(UiFormal *ast) { terminal(ast->identifierToken); terminal(ast->asToken); terminal(ast->aliasToken); return false; }
    virtual bool visit(UiSignature *ast) { terminal(ast->lparenToken); nonterminal(ast->formals); terminal(ast->rparenToken); return false; }

    virtual bool visit(StringLiteral *ast) { terminal(ast->literalToken); return false; }
    virtual bool visit(NumericLiteral *ast) { terminal(ast->literalToken); return false; }
    virtual bool visit(TrueLiteral *ast) { terminal(ast->trueToken); return false; }
    virtual bool visit(FalseLiteral *ast) { terminal(ast->falseToken); return false; }
    virtual bool visit(IdentifierExpression *ast) { terminal(ast->identifierToken); return false; }
    virtual bool visit(FieldMemberExpression *ast) { nonterminal(ast->base); terminal(ast->dotToken); terminal(ast->identifierToken); return false; }
    virtual bool visit(BinaryExpression *ast) { nonterminal(ast->left); terminal(ast->operatorToken); nonterminal(ast->right); return false; }
    virtual bool visit(UnaryPlusExpression *ast) { terminal(ast->plusToken); nonterminal(ast->expression); return false; }
    virtual bool visit(UnaryMinusExpression *ast) { terminal(ast->minusToken); nonterminal(ast->expression); return false; }
    virtual bool visit(NestedExpression *ast) { terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); return false; }
    virtual bool visit(ThisExpression *ast) { terminal(ast->thisToken); return false; }
    virtual bool visit(NullExpression *ast) { terminal(ast->nullToken); return false; }
    virtual bool visit(RegExpLiteral *ast) { terminal(ast->literalToken); return false; }
    virtual bool visit(ArrayLiteral *ast) { terminal(ast->lbracketToken); nonterminal(ast->elements); terminal(ast->commaToken); nonterminal(ast->elision); terminal(ast->rbracketToken); return false; }
    virtual bool visit(ObjectLiteral *ast) { terminal(ast->lbraceToken); nonterminal(ast->properties); terminal(ast->rbraceToken); return false; }
    virtual bool visit(ElementList *ast) { nonterminal(ast->next); terminal(ast->commaToken); nonterminal(ast->elision); nonterminal(ast->expression); return false; }
    virtual bool visit(Elision *ast) { nonterminal(ast->next); terminal(ast->commaToken); return false; }
    virtual bool visit(PropertyNameAndValueList *ast) { nonterminal(ast->name); terminal(ast->colonToken); nonterminal(ast->value); terminal(ast->commaToken); nonterminal(ast->next); return false; }
    virtual bool visit(IdentifierPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
    virtual bool visit(StringLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
    virtual bool visit(NumericLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
    virtual bool visit(ArrayMemberExpression *ast) { nonterminal(ast->base); terminal(ast->lbracketToken); nonterminal(ast->expression); terminal(ast->rbracketToken); return false; }
    virtual bool visit(NewMemberExpression *ast) { terminal(ast->newToken); nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
    virtual bool visit(NewExpression *ast) { terminal(ast->newToken); nonterminal(ast->expression); return false; }
    virtual bool visit(CallExpression *ast) { nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
    virtual bool visit(ArgumentList *ast) { nonterminal(ast->expression); terminal(ast->commaToken); nonterminal(ast->next); return false; }
    virtual bool visit(PostIncrementExpression *ast) { nonterminal(ast->base); terminal(ast->incrementToken); return false; }
    virtual bool visit(PostDecrementExpression *ast) { nonterminal(ast->base); terminal(ast->decrementToken); return false; }
    virtual bool visit(DeleteExpression *ast) { terminal(ast->deleteToken); nonterminal(ast->expression); return false; }
    virtual bool visit(VoidExpression *ast) { terminal(ast->voidToken); nonterminal(ast->expression); return false; }
    virtual bool visit(TypeOfExpression *ast) { terminal(ast->typeofToken); nonterminal(ast->expression); return false; }
    virtual bool visit(PreIncrementExpression *ast) { terminal(ast->incrementToken); nonterminal(ast->expression); return false; }
    virtual bool visit(PreDecrementExpression *ast) { terminal(ast->decrementToken); nonterminal(ast->expression); return false; }
    virtual bool visit(TildeExpression *ast) { terminal(ast->tildeToken); nonterminal(ast->expression); return false; }
    virtual bool visit(NotExpression *ast) { terminal(ast->notToken); nonterminal(ast->expression); return false; }
    virtual bool visit(ConditionalExpression *ast) { nonterminal(ast->expression); terminal(ast->questionToken); nonterminal(ast->ok); terminal(ast->colonToken); nonterminal(ast->ko); return false; }
    virtual bool visit(Expression *ast) { nonterminal(ast->left); terminal(ast->commaToken); nonterminal(ast->right); return false; }
    virtual bool visit(Block *ast) { terminal(ast->lbraceToken); nonterminal(ast->statements); terminal(ast->rbraceToken); return false; }
    virtual bool visit(VariableStatement *ast) { terminal(ast->declarationKindToken); nonterminal(ast->declarations); terminal(ast->semicolonToken); return false; }
    virtual bool visit(VariableDeclaration *ast) { terminal(ast->identifierToken); nonterminal(ast->expression); return false; }
    virtual bool visit(VariableDeclarationList *ast) { nonterminal(ast->declaration); terminal(ast->commaToken); nonterminal(ast->next); return false; }
    virtual bool visit(EmptyStatement* ast) { terminal(ast->semicolonToken); return false; }
    virtual bool visit(ExpressionStatement *ast) { nonterminal(ast->expression); terminal(ast->semicolonToken); return false; }
    virtual bool visit(IfStatement *ast) { terminal(ast->ifToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); nonterminal(ast->ok); terminal(ast->elseToken); nonterminal(ast->ko); return false; }
    virtual bool visit(DoWhileStatement *ast) { terminal(ast->doToken); nonterminal(ast->statement); terminal(ast->whileToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); terminal(ast->semicolonToken); return false; }

// TODO: visitors for:
//    WhileStatement
//    ForStatement
//    LocalForStatement
//    ForEachStatement
//    LocalForEachStatement
//    ContinueStatement
//    BreakStatement
//    ReturnStatement
//    WithStatement
//    CaseBlock
//    SwitchStatement
//    CaseClause
//    DefaultClause
//    LabelledStatement
//    ThrowStatement
//    Catch
//    Finally
//    TryStatement
//    FunctionExpression
//    FunctionDeclaration
//    DebuggerStatement
//    UiParameterList

private:
    QHash<Node *, QByteArray> _id;
    QList<QPair<QByteArray, QByteArray> > _connections;
    QList<Node *> _stack;
    QList<QByteArray> _terminalShapes;
    ofstream out;
    QByteArray _src;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QStringList files = app.arguments();
    files.removeFirst();

    foreach (const QString &fileName, files) {
        QFile file(fileName);
        if (! file.open(QFile::ReadOnly)) {
            cerr << "Cannot open \"" << qPrintable(fileName)
                      << "\", skipping it." << endl;
            continue;
        }

        const QByteArray source = file.readAll();
        file.close();

        Document::Ptr doc = Document::create(fileName);
        doc->setSource(source);
        doc->parseQml();

        foreach (const DiagnosticMessage &m, doc->diagnosticMessages()) {
            ostream *os;
            if (m.isError()) {
                os = &cerr;
                *os << "Error:";
            } else {
                os = &cout;
                *os << "Warning:";
            }

            if (m.loc.isValid())
                *os << m.loc.startLine << ':' << m.loc.startColumn << ':';
            *os << ' ';
            *os << qPrintable(m.message) << endl;
        }

        ASTDump dump;
        dump(fileName, source, doc->qmlProgram());
    }

    return EXIT_SUCCESS;
}
<commit_msg>Fix compilation of tests/tools/qml-ast2dot.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/qmljsdocument.h>

#include <QFile>
#include <QList>
#include <QCoreApplication>
#include <QStringList>
#include <QFileInfo>
#include <QTime>
#include <QtDebug>

#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <iostream>
#ifdef __GNUC__
#  include <cxxabi.h>
#endif

using namespace QmlJS;
using namespace QmlJS::AST;
using namespace std;

class ASTDump: protected Visitor
{
public:
    void operator()(const QString &fileName, const QByteArray &src, Node *ast) {
        _src = src;
        QString basename = fileName;
        int dotIdx = basename.lastIndexOf('.');
        if (dotIdx != -1)
            basename.truncate(dotIdx);
        basename.append(QLatin1String(".ast.dot"));
        out.open(basename.toUtf8().constData());

        out << "digraph AST { ordering=out;" << endl;
        // cout << "rankdir = \"LR\";" << endl;
        Node::accept(ast, this);

        typedef QPair<QByteArray, QByteArray> Pair;

        foreach (const Pair &conn, _connections)
            out << conn.first.constData() << " -> " << conn.second.constData() << endl;

        alignTerminals();

        out << "}" << endl;
        out.close();
        cout << qPrintable(basename) << endl;
    }

protected:
    void alignTerminals() {
        out<<"{ rank=same;" << endl;
        foreach (const QByteArray &terminalShape, _terminalShapes) {
            out << "  " << string(terminalShape) << ";" << endl;
        }
        out<<"}"<<endl;
    }

    static QByteArray name(Node *ast) {
#ifdef __GNUC__
        QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 12;
#else
        QByteArray name = typeid(*ast).name();
#endif
        return name;
    }

    QString spell(const SourceLocation &token) {
        return _src.mid(token.offset, token.length).replace('\'', "\\\\").replace('"', "\\\"");
    }

    void terminal(const SourceLocation &token) {
        if (!token.isValid())
            return;

        static int count = 1;
        QByteArray id = 't' + QByteArray::number(count++);
        Node *node = _stack.last();
        _connections.append(qMakePair(_id[node], id));

        QByteArray t;
        t.append(id);
        t.append(" [label = \"");
        t.append(spell(token).toUtf8());
        t.append("\" shape=rect]");
        _terminalShapes.append(t);
    }

    virtual void nonterminal(Node *ast) {
        Node::accept(ast, this);
    }

    virtual void node(Node *ast) {
        out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << endl;
    }

    virtual bool preVisit(Node *ast) {
        static int count = 1;
        const QByteArray id = 'n' + QByteArray::number(count++);
        _id[ast] = id;

        if (! _stack.isEmpty())
            _connections.append(qMakePair(_id[_stack.last()], id));

        _stack.append(ast);

        node(ast);

        return true;
    }

    virtual void postVisit(Node *) {
        _stack.removeLast();
    }

protected: // visiting methods:
    virtual bool visit(UiImport *ast) {
        terminal(ast->importToken);

        if (ast->importUri)
            nonterminal(ast->importUri);
        else
            terminal(ast->fileNameToken);

        terminal(ast->versionToken);
        terminal(ast->asToken);
        terminal(ast->importIdToken);
        terminal(ast->semicolonToken);
        return false;
    }

    virtual bool visit(UiObjectBinding *ast) {
        if (ast->hasOnToken) {
            nonterminal(ast->qualifiedTypeNameId);
            terminal(ast->colonToken);
            nonterminal(ast->qualifiedId);
        } else {
            nonterminal(ast->qualifiedId);
            terminal(ast->colonToken);
            nonterminal(ast->qualifiedTypeNameId);
        }
        nonterminal(ast->initializer);
        return false;
    }

    virtual bool visit(UiObjectDefinition *ast) {
        nonterminal(ast->qualifiedTypeNameId);
        nonterminal(ast->initializer);
        return false;
    }

    virtual bool visit(UiObjectInitializer *ast) {
        terminal(ast->lbraceToken);
        nonterminal(ast->members);
        terminal(ast->rbraceToken);
        return false;
    }

    virtual bool visit(UiScriptBinding *ast) {
        nonterminal(ast->qualifiedId);
        terminal(ast->colonToken);
        nonterminal(ast->statement);
        return false;
    }

    virtual bool visit(UiArrayBinding *ast) {
        nonterminal(ast->qualifiedId);
        terminal(ast->colonToken);
        terminal(ast->lbracketToken);
        nonterminal(ast->members);
        terminal(ast->rbracketToken);
        return false;
    }

    virtual bool visit(UiArrayMemberList *ast) {
        terminal(ast->commaToken);
        nonterminal(ast->member);
        nonterminal(ast->next);
        return false;
    }

    virtual bool visit(UiQualifiedId *ast) {
        terminal(ast->identifierToken);
        nonterminal(ast->next);
        return false;
    }

    virtual bool visit(UiPublicMember *ast) {
        // TODO: place the parameters...
//        UiParameterList *parameters;

        terminal(ast->defaultToken);
        terminal(ast->readonlyToken);
        terminal(ast->propertyToken);
        terminal(ast->typeModifierToken);
        terminal(ast->typeToken);
        terminal(ast->identifierToken);
        terminal(ast->colonToken);
        nonterminal(ast->statement);
        nonterminal(ast->binding);
        terminal(ast->semicolonToken);
        return false;
    }

    virtual bool visit(UiFormal *ast) { terminal(ast->identifierToken); terminal(ast->asToken); terminal(ast->aliasToken); return false; }
    virtual bool visit(UiSignature *ast) { terminal(ast->lparenToken); nonterminal(ast->formals); terminal(ast->rparenToken); return false; }

    virtual bool visit(StringLiteral *ast) { terminal(ast->literalToken); return false; }
    virtual bool visit(NumericLiteral *ast) { terminal(ast->literalToken); return false; }
    virtual bool visit(TrueLiteral *ast) { terminal(ast->trueToken); return false; }
    virtual bool visit(FalseLiteral *ast) { terminal(ast->falseToken); return false; }
    virtual bool visit(IdentifierExpression *ast) { terminal(ast->identifierToken); return false; }
    virtual bool visit(FieldMemberExpression *ast) { nonterminal(ast->base); terminal(ast->dotToken); terminal(ast->identifierToken); return false; }
    virtual bool visit(BinaryExpression *ast) { nonterminal(ast->left); terminal(ast->operatorToken); nonterminal(ast->right); return false; }
    virtual bool visit(UnaryPlusExpression *ast) { terminal(ast->plusToken); nonterminal(ast->expression); return false; }
    virtual bool visit(UnaryMinusExpression *ast) { terminal(ast->minusToken); nonterminal(ast->expression); return false; }
    virtual bool visit(NestedExpression *ast) { terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); return false; }
    virtual bool visit(ThisExpression *ast) { terminal(ast->thisToken); return false; }
    virtual bool visit(NullExpression *ast) { terminal(ast->nullToken); return false; }
    virtual bool visit(RegExpLiteral *ast) { terminal(ast->literalToken); return false; }
    virtual bool visit(ArrayLiteral *ast) { terminal(ast->lbracketToken); nonterminal(ast->elements); terminal(ast->commaToken); nonterminal(ast->elision); terminal(ast->rbracketToken); return false; }
    virtual bool visit(ObjectLiteral *ast) { terminal(ast->lbraceToken); nonterminal(ast->properties); terminal(ast->rbraceToken); return false; }
    virtual bool visit(ElementList *ast) { nonterminal(ast->next); terminal(ast->commaToken); nonterminal(ast->elision); nonterminal(ast->expression); return false; }
    virtual bool visit(Elision *ast) { nonterminal(ast->next); terminal(ast->commaToken); return false; }
    virtual bool visit(PropertyNameAndValueList *ast) { nonterminal(ast->name); terminal(ast->colonToken); nonterminal(ast->value); terminal(ast->commaToken); nonterminal(ast->next); return false; }
    virtual bool visit(IdentifierPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
    virtual bool visit(StringLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
    virtual bool visit(NumericLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
    virtual bool visit(ArrayMemberExpression *ast) { nonterminal(ast->base); terminal(ast->lbracketToken); nonterminal(ast->expression); terminal(ast->rbracketToken); return false; }
    virtual bool visit(NewMemberExpression *ast) { terminal(ast->newToken); nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
    virtual bool visit(NewExpression *ast) { terminal(ast->newToken); nonterminal(ast->expression); return false; }
    virtual bool visit(CallExpression *ast) { nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
    virtual bool visit(ArgumentList *ast) { nonterminal(ast->expression); terminal(ast->commaToken); nonterminal(ast->next); return false; }
    virtual bool visit(PostIncrementExpression *ast) { nonterminal(ast->base); terminal(ast->incrementToken); return false; }
    virtual bool visit(PostDecrementExpression *ast) { nonterminal(ast->base); terminal(ast->decrementToken); return false; }
    virtual bool visit(DeleteExpression *ast) { terminal(ast->deleteToken); nonterminal(ast->expression); return false; }
    virtual bool visit(VoidExpression *ast) { terminal(ast->voidToken); nonterminal(ast->expression); return false; }
    virtual bool visit(TypeOfExpression *ast) { terminal(ast->typeofToken); nonterminal(ast->expression); return false; }
    virtual bool visit(PreIncrementExpression *ast) { terminal(ast->incrementToken); nonterminal(ast->expression); return false; }
    virtual bool visit(PreDecrementExpression *ast) { terminal(ast->decrementToken); nonterminal(ast->expression); return false; }
    virtual bool visit(TildeExpression *ast) { terminal(ast->tildeToken); nonterminal(ast->expression); return false; }
    virtual bool visit(NotExpression *ast) { terminal(ast->notToken); nonterminal(ast->expression); return false; }
    virtual bool visit(ConditionalExpression *ast) { nonterminal(ast->expression); terminal(ast->questionToken); nonterminal(ast->ok); terminal(ast->colonToken); nonterminal(ast->ko); return false; }
    virtual bool visit(Expression *ast) { nonterminal(ast->left); terminal(ast->commaToken); nonterminal(ast->right); return false; }
    virtual bool visit(Block *ast) { terminal(ast->lbraceToken); nonterminal(ast->statements); terminal(ast->rbraceToken); return false; }
    virtual bool visit(VariableStatement *ast) { terminal(ast->declarationKindToken); nonterminal(ast->declarations); terminal(ast->semicolonToken); return false; }
    virtual bool visit(VariableDeclaration *ast) { terminal(ast->identifierToken); nonterminal(ast->expression); return false; }
    virtual bool visit(VariableDeclarationList *ast) { nonterminal(ast->declaration); terminal(ast->commaToken); nonterminal(ast->next); return false; }
    virtual bool visit(EmptyStatement* ast) { terminal(ast->semicolonToken); return false; }
    virtual bool visit(ExpressionStatement *ast) { nonterminal(ast->expression); terminal(ast->semicolonToken); return false; }
    virtual bool visit(IfStatement *ast) { terminal(ast->ifToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); nonterminal(ast->ok); terminal(ast->elseToken); nonterminal(ast->ko); return false; }
    virtual bool visit(DoWhileStatement *ast) { terminal(ast->doToken); nonterminal(ast->statement); terminal(ast->whileToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); terminal(ast->semicolonToken); return false; }

// TODO: visitors for:
//    WhileStatement
//    ForStatement
//    LocalForStatement
//    ForEachStatement
//    LocalForEachStatement
//    ContinueStatement
//    BreakStatement
//    ReturnStatement
//    WithStatement
//    CaseBlock
//    SwitchStatement
//    CaseClause
//    DefaultClause
//    LabelledStatement
//    ThrowStatement
//    Catch
//    Finally
//    TryStatement
//    FunctionExpression
//    FunctionDeclaration
//    DebuggerStatement
//    UiParameterList

private:
    QHash<Node *, QByteArray> _id;
    QList<QPair<QByteArray, QByteArray> > _connections;
    QList<Node *> _stack;
    QList<QByteArray> _terminalShapes;
    ofstream out;
    QByteArray _src;
};

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QStringList files = app.arguments();
    files.removeFirst();

    foreach (const QString &fileName, files) {
        QFile file(fileName);
        if (! file.open(QFile::ReadOnly)) {
            cerr << "Cannot open \"" << qPrintable(fileName)
                      << "\", skipping it." << endl;
            continue;
        }

        const QByteArray source = file.readAll();
        file.close();

        Document::Ptr doc = Document::create(fileName, Document::QmlLanguage);
        doc->setSource(source);
        doc->parse();

        foreach (const DiagnosticMessage &m, doc->diagnosticMessages()) {
            ostream *os;
            if (m.isError()) {
                os = &cerr;
                *os << "Error:";
            } else {
                os = &cout;
                *os << "Warning:";
            }

            if (m.loc.isValid())
                *os << m.loc.startLine << ':' << m.loc.startColumn << ':';
            *os << ' ';
            *os << qPrintable(m.message) << endl;
        }

        ASTDump dump;
        dump(fileName, source, doc->qmlProgram());
    }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#pragma once
#include <silicium/html/tree.hpp>

namespace tags
{
	//----------------TITLE tag----------------
	template <class Element>
	auto html(Element &&content)
	{
		return Si::html::tag("html", std::forward<Element>(content));
	}

	template <class Element>
	auto head(Element &&content)
	{
		return Si::html::tag("head", std::forward<Element>(content));
	}

	template <class Element>
	auto body(Element &&content)
	{
		return Si::html::tag("body", std::forward<Element>(content));
	}

	//----------------TITLE tag----------------
	inline auto title(std::string const &content)
	{
		using namespace Si::html;
		return tag("title", text(content));
	}

	//----------------H1 tag----------------
	template <class Element>
	auto h1(Element &&content)
	{
		using namespace Si::html;
		return tag("h1", std::forward<Element>(content));
	}

	//----------------H2 tag----------------
	template <class Element>
	auto h2(Element &&content)
	{
		using namespace Si::html;
		return tag("h2", std::forward<Element>(content));
	}

	//----------------H3 tag----------------
	template <class Element>
	auto h3(Element &&content)
	{
		using namespace Si::html;
		return tag("h3", std::forward<Element>(content));
	}

	//----------------H4 tag----------------
	template <class Element>
	auto h4(Element &&content)
	{
		using namespace Si::html;
		return tag("h4", std::forward<Element>(content));
	}

	//----------------MENU tag----------------
	template <class Element>
	auto menu(Element &&content)
	{
		return Si::html::tag("menu", std::forward<Element>(content));
	}

	//----------------FOOTER tag----------------
	template <class Element>
	auto footer(Element &&content)
	{
		return Si::html::tag("footer", std::forward<Element>(content));
	}

	//----------------P tag----------------
	inline auto p(std::string const &content)
	{
		using namespace Si::html;
		return tag("p", text(content));
	}

	template <class Element, class Attributes>
	auto p(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("p", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------DIV tag----------------
	template <class Element>
	auto div(Element &&content)
	{
		return Si::html::tag("div", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto div(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("div", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------SPAN tag----------------
	template <class Element>
	auto span(Element &&content)
	{
		return Si::html::tag("span", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto span(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("span", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------table tags----------------
	template <class Element>
	auto table(Element &&content)
	{
		return Si::html::tag("table", std::forward<Element>(content));
	}

	template <class Element>
	auto table(std::string const &summary, Element &&content)
	{
		return Si::html::tag("table", Si::html::attribute("summary", summary),
		                     std::forward<Element>(content));
	}

	template <class Element>
	auto thead(Element &&content)
	{
		return Si::html::tag("thead", std::forward<Element>(content));
	}

	template <class Element>
	auto tbody(Element &&content)
	{
		return Si::html::tag("tbody", std::forward<Element>(content));
	}

	template <class Element>
	auto tfoot(Element &&content)
	{
		return Si::html::tag("tfoot", std::forward<Element>(content));
	}

	//----------------TD tag----------------
	template <class Element>
	auto td(Element &&content)
	{
		return Si::html::tag("td", std::forward<Element>(content));
	}

	//----------------UL tag----------------
	template <class Element>
	auto ul(Element &&content)
	{
		return Si::html::tag("ul", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto ul(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("ul", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------LI tag----------------
	template <class Element>
	auto li(Element &&content)
	{
		return Si::html::tag("li", std::forward<Element>(content));
	}

	//----------------PRE tag----------------
	template <class Element>
	auto pre(Element &&content)
	{
		return Si::html::tag("pre", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto pre(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("pre", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	template <class Attributes>
	auto br(Attributes &&attributes)
	{
		using namespace Si::html;
		return tag("br", std::forward<Attributes>(attributes), empty);
	}

	//----------------classes attrib----------------
	inline auto cl(std::string const &content)
	{
		return Si::html::attribute("class", content);
	}

	//----------------href attrib----------------
    inline auto href(std::string const &link)
	{
        return Si::html::attribute("href", link);
	}

    // Opens the link in a new tab
    inline auto href_new_tab(std::string const &link)
    {
        return href(link) + Si::html::attribute("target", "_blank");
    }

    template <class Element, class Attributes>
    inline auto a(Attributes &&attributes, Element &&content)
    {
        return Si::html::tag("a", std::forward<Attributes>(attributes),
                             std::forward<Element>(content));
    }

	// PSEUDO TAG: link (emulates the a-tag)
	template <std::size_t N>
	auto link(std::string const &protocol,
	          char const(&address_without_protocol)[N],
	          std::string const &caption)
	{
		using namespace Si::html;
		return dynamic(
		    [protocol, &address_without_protocol, caption](code_sink &sink)
		    {
			    if (protocol == "http://" || protocol == "https://")
			    {
                    tag("a", href_external(protocol + address_without_protocol),
				        text(caption))
				        .generate(sink);
			    }
			    else
			    {
				    tag("a", href(protocol + address_without_protocol),
				        text(caption))
				        .generate(sink);
			    }
			});
	}

	template <std::size_t N>
	auto link(std::string const &protocol,
	          char const(&address_without_protocol)[N])
	{
		return link(protocol, address_without_protocol,
		            address_without_protocol);
	}

	// PSEUDO ATTRIBUTE: anchor_attributes (emulates a jump mark on a page)
	template <std::size_t N>
	auto anchor_attributes(char const(&name)[N])
	{
		using namespace Si::html;
		return attribute("name", name) + href(std::string("#") + name);
	}
}
<commit_msg>Fixed function name<commit_after>#pragma once
#include <silicium/html/tree.hpp>

namespace tags
{
	//----------------TITLE tag----------------
	template <class Element>
	auto html(Element &&content)
	{
		return Si::html::tag("html", std::forward<Element>(content));
	}

	template <class Element>
	auto head(Element &&content)
	{
		return Si::html::tag("head", std::forward<Element>(content));
	}

	template <class Element>
	auto body(Element &&content)
	{
		return Si::html::tag("body", std::forward<Element>(content));
	}

	//----------------TITLE tag----------------
	inline auto title(std::string const &content)
	{
		using namespace Si::html;
		return tag("title", text(content));
	}

	//----------------H1 tag----------------
	template <class Element>
	auto h1(Element &&content)
	{
		using namespace Si::html;
		return tag("h1", std::forward<Element>(content));
	}

	//----------------H2 tag----------------
	template <class Element>
	auto h2(Element &&content)
	{
		using namespace Si::html;
		return tag("h2", std::forward<Element>(content));
	}

	//----------------H3 tag----------------
	template <class Element>
	auto h3(Element &&content)
	{
		using namespace Si::html;
		return tag("h3", std::forward<Element>(content));
	}

	//----------------H4 tag----------------
	template <class Element>
	auto h4(Element &&content)
	{
		using namespace Si::html;
		return tag("h4", std::forward<Element>(content));
	}

	//----------------MENU tag----------------
	template <class Element>
	auto menu(Element &&content)
	{
		return Si::html::tag("menu", std::forward<Element>(content));
	}

	//----------------FOOTER tag----------------
	template <class Element>
	auto footer(Element &&content)
	{
		return Si::html::tag("footer", std::forward<Element>(content));
	}

	//----------------P tag----------------
	inline auto p(std::string const &content)
	{
		using namespace Si::html;
		return tag("p", text(content));
	}

	template <class Element, class Attributes>
	auto p(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("p", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------DIV tag----------------
	template <class Element>
	auto div(Element &&content)
	{
		return Si::html::tag("div", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto div(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("div", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------SPAN tag----------------
	template <class Element>
	auto span(Element &&content)
	{
		return Si::html::tag("span", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto span(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("span", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------table tags----------------
	template <class Element>
	auto table(Element &&content)
	{
		return Si::html::tag("table", std::forward<Element>(content));
	}

	template <class Element>
	auto table(std::string const &summary, Element &&content)
	{
		return Si::html::tag("table", Si::html::attribute("summary", summary),
		                     std::forward<Element>(content));
	}

	template <class Element>
	auto thead(Element &&content)
	{
		return Si::html::tag("thead", std::forward<Element>(content));
	}

	template <class Element>
	auto tbody(Element &&content)
	{
		return Si::html::tag("tbody", std::forward<Element>(content));
	}

	template <class Element>
	auto tfoot(Element &&content)
	{
		return Si::html::tag("tfoot", std::forward<Element>(content));
	}

	//----------------TD tag----------------
	template <class Element>
	auto td(Element &&content)
	{
		return Si::html::tag("td", std::forward<Element>(content));
	}

	//----------------UL tag----------------
	template <class Element>
	auto ul(Element &&content)
	{
		return Si::html::tag("ul", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto ul(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("ul", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	//----------------LI tag----------------
	template <class Element>
	auto li(Element &&content)
	{
		return Si::html::tag("li", std::forward<Element>(content));
	}

	//----------------PRE tag----------------
	template <class Element>
	auto pre(Element &&content)
	{
		return Si::html::tag("pre", std::forward<Element>(content));
	}

	template <class Element, class Attributes>
	auto pre(Attributes &&attributes, Element &&content)
	{
		return Si::html::tag("pre", std::forward<Attributes>(attributes),
		                     std::forward<Element>(content));
	}

	template <class Attributes>
	auto br(Attributes &&attributes)
	{
		using namespace Si::html;
		return tag("br", std::forward<Attributes>(attributes), empty);
	}

	//----------------classes attrib----------------
	inline auto cl(std::string const &content)
	{
		return Si::html::attribute("class", content);
	}

	//----------------href attrib----------------
    inline auto href(std::string const &link)
	{
        return Si::html::attribute("href", link);
	}

    // Opens the link in a new tab
    inline auto href_new_tab(std::string const &link)
    {
        return href(link) + Si::html::attribute("target", "_blank");
    }

    template <class Element, class Attributes>
    inline auto a(Attributes &&attributes, Element &&content)
    {
        return Si::html::tag("a", std::forward<Attributes>(attributes),
                             std::forward<Element>(content));
    }

	// PSEUDO TAG: link (emulates the a-tag)
	template <std::size_t N>
	auto link(std::string const &protocol,
	          char const(&address_without_protocol)[N],
	          std::string const &caption)
	{
		using namespace Si::html;
		return dynamic(
		    [protocol, &address_without_protocol, caption](code_sink &sink)
		    {
			    if (protocol == "http://" || protocol == "https://")
			    {
                    tag("a", href_new_tab(protocol + address_without_protocol),
				        text(caption))
				        .generate(sink);
			    }
			    else
			    {
				    tag("a", href(protocol + address_without_protocol),
				        text(caption))
				        .generate(sink);
			    }
			});
	}

	template <std::size_t N>
	auto link(std::string const &protocol,
	          char const(&address_without_protocol)[N])
	{
		return link(protocol, address_without_protocol,
		            address_without_protocol);
	}

	// PSEUDO ATTRIBUTE: anchor_attributes (emulates a jump mark on a page)
	template <std::size_t N>
	auto anchor_attributes(char const(&name)[N])
	{
		using namespace Si::html;
		return attribute("name", name) + href(std::string("#") + name);
	}
}
<|endoftext|>


<commit_before>#ifndef _RTL_BOOTSTRAP_HXX_
#include "rtl/bootstrap.hxx"
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef CPPUNIT_SIMPLEHEADER_HXX
#include <cppunit/simpleheader.hxx>
#endif

#ifndef _CPPUHELPER_BOOTSTRAP_HXX_
#include <cppuhelper/bootstrap.hxx>
#endif

#ifndef _COM_SUN_STAR_XML_SAX_XPARSER_HPP_
#include <com/sun/star/xml/sax/XParser.hpp>
#endif

namespace css = com::sun::star;
namespace lang = css::lang;
namespace uno  = css::uno;
namespace sax = css::xml::sax;

// StringHelper
inline void operator <<= (rtl::OString& _rAsciiString, const rtl::OUString& _rUnicodeString)
{
    _rAsciiString = rtl::OUStringToOString(_rUnicodeString,RTL_TEXTENCODING_ASCII_US);
}

namespace unotest
{
//------------------------------------------------------------------------
// testing constructors
//------------------------------------------------------------------------

    class  ctor : public CppUnit::TestFixture
    {
    public:
        void ctor_001()
            {
                uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
                if (xFactory.is())
                {
                    // sample, get a xParser instance
                    uno::Reference< sax::XParser > xParser;
                    xParser = uno::Reference< sax::XParser > (
                        xFactory->createInstance(
                            ::rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser")), uno::UNO_QUERY);

                    CPPUNIT_ASSERT_MESSAGE("can't get sax::Parser", xParser.is());
                }
            }

        CPPUNIT_TEST_SUITE(ctor);
        CPPUNIT_TEST(ctor_001);
        CPPUNIT_TEST_SUITE_END();
    };

    // -----------------------------------------------------------------------------
    CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(unotest::ctor, "unotest");
} // unotest

// -----------------------------------------------------------------------------

// this macro creates an empty function, which will called by the RegisterAllFunctions()
// to let the user the possibility to also register some functions by hand.

void RegisterAdditionalFunctions(FktRegFuncPtr _pFunc)
{
    uno::Reference<lang::XMultiServiceFactory> xMS;

    try
    {
        uno::Reference< uno::XComponentContext > xComponentContext = cppu::defaultBootstrap_InitialComponentContext();
        xMS.set(xComponentContext->getServiceManager(), uno::UNO_QUERY);
        comphelper::setProcessServiceFactory(xMS);
    }
    catch (::com::sun::star::uno::Exception e )
    {
        rtl::OString aError;
        aError <<= e.Message;
        printf("Error: %s\n", aError.getStr());
    }
}
// NOADDITIONAL;
<commit_msg>INTEGRATION: CWS pchfix02 (1.2.108); FILE MERGED 2006/09/01 17:53:52 kaib 1.2.108.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: unotest.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 03:51:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_testshl2.hxx"
#ifndef _RTL_BOOTSTRAP_HXX_
#include "rtl/bootstrap.hxx"
#endif

#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
#include <comphelper/processfactory.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_XCOMPONENTCONTEXT_HPP_
#include <com/sun/star/uno/XComponentContext.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XMULTISERVICEFACTORY_HPP_
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#endif

#ifndef CPPUNIT_SIMPLEHEADER_HXX
#include <cppunit/simpleheader.hxx>
#endif

#ifndef _CPPUHELPER_BOOTSTRAP_HXX_
#include <cppuhelper/bootstrap.hxx>
#endif

#ifndef _COM_SUN_STAR_XML_SAX_XPARSER_HPP_
#include <com/sun/star/xml/sax/XParser.hpp>
#endif

namespace css = com::sun::star;
namespace lang = css::lang;
namespace uno  = css::uno;
namespace sax = css::xml::sax;

// StringHelper
inline void operator <<= (rtl::OString& _rAsciiString, const rtl::OUString& _rUnicodeString)
{
    _rAsciiString = rtl::OUStringToOString(_rUnicodeString,RTL_TEXTENCODING_ASCII_US);
}

namespace unotest
{
//------------------------------------------------------------------------
// testing constructors
//------------------------------------------------------------------------

    class  ctor : public CppUnit::TestFixture
    {
    public:
        void ctor_001()
            {
                uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() );
                if (xFactory.is())
                {
                    // sample, get a xParser instance
                    uno::Reference< sax::XParser > xParser;
                    xParser = uno::Reference< sax::XParser > (
                        xFactory->createInstance(
                            ::rtl::OUString::createFromAscii("com.sun.star.xml.sax.Parser")), uno::UNO_QUERY);

                    CPPUNIT_ASSERT_MESSAGE("can't get sax::Parser", xParser.is());
                }
            }

        CPPUNIT_TEST_SUITE(ctor);
        CPPUNIT_TEST(ctor_001);
        CPPUNIT_TEST_SUITE_END();
    };

    // -----------------------------------------------------------------------------
    CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(unotest::ctor, "unotest");
} // unotest

// -----------------------------------------------------------------------------

// this macro creates an empty function, which will called by the RegisterAllFunctions()
// to let the user the possibility to also register some functions by hand.

void RegisterAdditionalFunctions(FktRegFuncPtr _pFunc)
{
    uno::Reference<lang::XMultiServiceFactory> xMS;

    try
    {
        uno::Reference< uno::XComponentContext > xComponentContext = cppu::defaultBootstrap_InitialComponentContext();
        xMS.set(xComponentContext->getServiceManager(), uno::UNO_QUERY);
        comphelper::setProcessServiceFactory(xMS);
    }
    catch (::com::sun::star::uno::Exception e )
    {
        rtl::OString aError;
        aError <<= e.Message;
        printf("Error: %s\n", aError.getStr());
    }
}
// NOADDITIONAL;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016, Humanoid Lab, Georgia Tech Research Corporation
 * Copyright (c) 2016-2017, Graphics Lab, Georgia Tech Research Corporation
 * Copyright (c) 2016-2017, Personal Robotics Lab, Carnegie Mellon University
 * All rights reserved.
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef DART_MATH_CONFIGURATIONSPACE_HPP_
#define DART_MATH_CONFIGURATIONSPACE_HPP_

#include <Eigen/Dense>
#include "dart/math/MathTypes.hpp"
#include "dart/math/Geometry.hpp"

namespace dart {
namespace math {

//==============================================================================
template <std::size_t Dimension>
struct RealVectorSpace
{
  enum : std::size_t { NumDofs = Dimension };
  enum : int { NumDofsEigen = Dimension };

  using TangentSpace = RealVectorSpace<NumDofs>;

  using Point          = Eigen::Matrix<double, NumDofs, 1>;
  using EuclideanPoint = Eigen::Matrix<double, NumDofs, 1>;
  using Vector         = Eigen::Matrix<double, NumDofs, 1>;
  using Matrix         = Eigen::Matrix<double, NumDofs, NumDofs>;
  using JacobianMatrix = Eigen::Matrix<double, 6, NumDofs>;
};

using NullSpace = RealVectorSpace<0u>;
using R1Space = RealVectorSpace<1u>;
using R2Space = RealVectorSpace<2u>;
using R3Space = RealVectorSpace<3u>;

//==============================================================================
struct SO3Space
{
  enum : std::size_t { NumDofs = 3u };
  enum : int { NumDofsEigen = 3 };

  using TangentSpace = RealVectorSpace<NumDofs>;

  using Point          = Eigen::Matrix3d;
  using EuclideanPoint = Eigen::Vector3d;
  using Vector         = Eigen::Vector3d;
  using Matrix         = Eigen::Matrix3d;
  using JacobianMatrix = Eigen::Matrix<double, 6, NumDofs>;
};

//==============================================================================
struct SE3Space
{
  enum : std::size_t { NumDofs = 6u };
  enum : int { NumDofsEigen = 6 };

  using TangentSpace = RealVectorSpace<NumDofs>;

  using Point          = Eigen::Isometry3d;
  using EuclideanPoint = Eigen::Vector6d;
  using Vector         = Eigen::Vector6d;
  using Matrix         = Eigen::Matrix6d;
  using JacobianMatrix = Eigen::Matrix6d;
};

struct MapsToManifoldPoint {};

//==============================================================================
template <typename SpaceT>
typename SpaceT::Matrix inverse(const typename SpaceT::Matrix& mat);

//==============================================================================
template <typename SpaceT>
typename SpaceT::EuclideanPoint
toEuclideanPoint(const typename SpaceT::Point& point);

//==============================================================================
template <typename SpaceT>
typename SpaceT::Point
toManifoldPoint(const typename SpaceT::EuclideanPoint& point);

//==============================================================================
template <typename SpaceT>
typename SpaceT::Point integratePosition(
    const typename SpaceT::Point& pos,
    const typename SpaceT::Vector& vel,
    double dt);

//==============================================================================
template <typename SpaceT>
typename SpaceT::Vector integrateVelocity(
    const typename SpaceT::Vector& vel,
    const typename SpaceT::Vector& acc,
    double dt);

} // namespace math
} // namespace dart

#include "dart/math/detail/ConfigurationSpace.hpp"

#endif // DART_MATH_CONFIGURATIONSPACE_HPP_
<commit_msg>Use static constexpr instead of enum class (#852)<commit_after>/*
 * Copyright (c) 2016, Humanoid Lab, Georgia Tech Research Corporation
 * Copyright (c) 2016-2017, Graphics Lab, Georgia Tech Research Corporation
 * Copyright (c) 2016-2017, Personal Robotics Lab, Carnegie Mellon University
 * All rights reserved.
 *
 * This file is provided under the following "BSD-style" License:
 *   Redistribution and use in source and binary forms, with or
 *   without modification, are permitted provided that the following
 *   conditions are met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *   POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef DART_MATH_CONFIGURATIONSPACE_HPP_
#define DART_MATH_CONFIGURATIONSPACE_HPP_

#include <Eigen/Dense>
#include "dart/math/MathTypes.hpp"
#include "dart/math/Geometry.hpp"

namespace dart {
namespace math {

//==============================================================================
template <std::size_t Dimension>
struct RealVectorSpace
{
  static constexpr std::size_t NumDofs = Dimension;
  static constexpr int NumDofsEigen = static_cast<int>(Dimension);

  using TangentSpace = RealVectorSpace<NumDofs>;

  using Point          = Eigen::Matrix<double, NumDofs, 1>;
  using EuclideanPoint = Eigen::Matrix<double, NumDofs, 1>;
  using Vector         = Eigen::Matrix<double, NumDofs, 1>;
  using Matrix         = Eigen::Matrix<double, NumDofs, NumDofs>;
  using JacobianMatrix = Eigen::Matrix<double, 6, NumDofs>;
};

using NullSpace = RealVectorSpace<0u>;
using R1Space = RealVectorSpace<1u>;
using R2Space = RealVectorSpace<2u>;
using R3Space = RealVectorSpace<3u>;

//==============================================================================
struct SO3Space
{
  static constexpr std::size_t NumDofs = 3u;
  static constexpr int NumDofsEigen = 3;

  using TangentSpace = RealVectorSpace<NumDofs>;

  using Point          = Eigen::Matrix3d;
  using EuclideanPoint = Eigen::Vector3d;
  using Vector         = Eigen::Vector3d;
  using Matrix         = Eigen::Matrix3d;
  using JacobianMatrix = Eigen::Matrix<double, 6, NumDofs>;
};

//==============================================================================
struct SE3Space
{
  static constexpr std::size_t NumDofs = 6u;
  static constexpr int NumDofsEigen = 6;

  using TangentSpace = RealVectorSpace<NumDofs>;

  using Point          = Eigen::Isometry3d;
  using EuclideanPoint = Eigen::Vector6d;
  using Vector         = Eigen::Vector6d;
  using Matrix         = Eigen::Matrix6d;
  using JacobianMatrix = Eigen::Matrix6d;
};

struct MapsToManifoldPoint {};

//==============================================================================
template <typename SpaceT>
typename SpaceT::Matrix inverse(const typename SpaceT::Matrix& mat);

//==============================================================================
template <typename SpaceT>
typename SpaceT::EuclideanPoint
toEuclideanPoint(const typename SpaceT::Point& point);

//==============================================================================
template <typename SpaceT>
typename SpaceT::Point
toManifoldPoint(const typename SpaceT::EuclideanPoint& point);

//==============================================================================
template <typename SpaceT>
typename SpaceT::Point integratePosition(
    const typename SpaceT::Point& pos,
    const typename SpaceT::Vector& vel,
    double dt);

//==============================================================================
template <typename SpaceT>
typename SpaceT::Vector integrateVelocity(
    const typename SpaceT::Vector& vel,
    const typename SpaceT::Vector& acc,
    double dt);

} // namespace math
} // namespace dart

#include "dart/math/detail/ConfigurationSpace.hpp"

#endif // DART_MATH_CONFIGURATIONSPACE_HPP_
<|endoftext|>