Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r73206 - trunk/libs/spirit/example/qi/compiler_tutorial/conjure3
From: joel_at_[hidden]
Date: 2011-07-18 00:06:09


Author: djowel
Date: 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
New Revision: 73206
URL: http://svn.boost.org/trac/boost/changeset/73206

Log:
LLVM backend!
Added:
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/token_ids.hpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp (contents, props changed)
   trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp (contents, props changed)

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/annotation.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,88 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ANNOTATION_HPP)
+#define BOOST_SPIRIT_CONJURE_ANNOTATION_HPP
+
+#include <map>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/mpl/bool.hpp>
+#include "ast.hpp"
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The annotation handler links the AST to a map of iterator positions
+ // for the purpose of subsequent semantic error handling when the
+ // program is being compiled.
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator>
+ struct annotation
+ {
+ template <typename, typename>
+ struct result { typedef void type; };
+
+ std::vector<Iterator>& iters;
+ annotation(std::vector<Iterator>& iters)
+ : iters(iters) {}
+
+ struct set_id
+ {
+ typedef void result_type;
+
+ int id;
+ set_id(int id) : id(id) {}
+
+ void operator()(ast::function_call& x) const
+ {
+ x.function_name.id = id;
+ }
+
+ void operator()(ast::identifier& x) const
+ {
+ x.id = id;
+ }
+
+ template <typename T>
+ void operator()(T& x) const
+ {
+ // no-op
+ }
+ };
+
+ void operator()(ast::operand& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ boost::apply_visitor(set_id(id), ast);
+ }
+
+ void operator()(ast::assignment& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.lhs.id = id;
+ }
+
+ void operator()(ast::return_statement& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+
+ void operator()(ast::identifier& ast, Iterator pos) const
+ {
+ int id = iters.size();
+ iters.push_back(pos);
+ ast.id = id;
+ }
+ };
+}
+
+#endif
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/ast.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,287 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_AST_HPP)
+#define BOOST_SPIRIT_CONJURE_AST_HPP
+
+#include <boost/config/warning_disable.hpp>
+#include <boost/variant/recursive_variant.hpp>
+#include <boost/fusion/include/adapt_struct.hpp>
+#include <boost/fusion/include/io.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+#include "token_ids.hpp"
+
+namespace client { namespace ast
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The AST
+ ///////////////////////////////////////////////////////////////////////////
+ struct tagged
+ {
+ int id; // Used to annotate the AST with the iterator position.
+ // This id is used as a key to a map<int, Iterator>
+ // (not really part of the AST.)
+ };
+
+ struct nil {};
+ struct unary;
+ struct function_call;
+ struct expression;
+
+ struct identifier : tagged
+ {
+ identifier(std::string const& name = "") : name(name) {}
+ std::string name;
+ };
+
+ typedef boost::variant<
+ nil
+ , bool
+ , unsigned int
+ , identifier
+ , boost::recursive_wrapper<unary>
+ , boost::recursive_wrapper<function_call>
+ , boost::recursive_wrapper<expression>
+ >
+ operand;
+
+ #define OP(id) (id + op_operator)
+ #define OP_EX(id, mask) (id + (mask | op_operator))
+
+ enum optoken
+ {
+ // pseudo tags
+ op_operator = lexer::ID_OP_OPERATOR,
+ op_binary = lexer::ID_OP_BINARY,
+ op_unary = lexer::ID_OP_UNARY,
+ op_mask = (op_operator | op_unary | op_binary),
+
+ // precedence 1
+ op_comma = OP(0),
+
+ // precedence 2
+ op_assign = OP(1),
+ op_plus_assign = OP(2),
+ op_minus_assign = OP(3),
+ op_times_assign = OP(4),
+ op_divide_assign = OP(5),
+ op_mod_assign = OP(6),
+ op_bit_and_assign = OP(7),
+ op_bit_xor_assign = OP(8),
+ op_bitor_assign = OP(9),
+ op_shift_left_assign = OP(10),
+ op_shift_right_assign = OP(11),
+
+ // precedence 3
+ op_logical_or = OP_EX(12, op_binary),
+
+ // precedence 4
+ op_logical_and = OP_EX(13, op_binary),
+
+ // precedence 5
+ op_bit_or = OP_EX(14, op_binary),
+
+ // precedence 6
+ op_bit_xor = OP_EX(15, op_binary),
+
+ // precedence 7
+ op_bit_and = OP_EX(16, op_binary),
+
+ // precedence 8
+ op_equal = OP_EX(17, op_binary),
+ op_not_equal = OP_EX(18, op_binary),
+
+ // precedence 9
+ op_less = OP_EX(19, op_binary),
+ op_less_equal = OP_EX(20, op_binary),
+ op_greater = OP_EX(21, op_binary),
+ op_greater_equal = OP_EX(22, op_binary),
+
+ // precedence 10
+ op_shift_left = OP_EX(23, op_binary),
+ op_shift_right = OP_EX(24, op_binary),
+
+ // precedence 11
+ op_plus = OP_EX(25, op_binary|op_unary),
+ op_minus = OP_EX(26, op_binary|op_unary),
+
+ // precedence 12
+ op_times = OP_EX(27, op_binary),
+ op_divide = OP_EX(28, op_binary),
+ op_mod = OP_EX(29, op_binary),
+
+ // precedence 13
+ op_positive = OP_EX(30, op_unary),
+ op_negative = OP_EX(31, op_unary),
+ op_pre_incr = OP_EX(32, op_unary),
+ op_pre_decr = OP_EX(33, op_unary),
+ op_compl = OP_EX(34, op_unary),
+ op_not = OP_EX(35, op_unary),
+
+ // precedence 14
+ op_post_incr = OP(36),
+ op_post_decr = OP(37)
+ };
+
+ struct unary
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct operation
+ {
+ optoken operator_;
+ operand operand_;
+ };
+
+ struct function_call
+ {
+ identifier function_name;
+ std::list<expression> args;
+ };
+
+ struct expression
+ {
+ operand first;
+ std::list<operation> rest;
+ };
+
+ struct assignment
+ {
+ identifier lhs;
+ expression rhs;
+ };
+
+ struct variable_declaration
+ {
+ identifier lhs;
+ boost::optional<expression> rhs;
+ };
+
+ struct if_statement;
+ struct while_statement;
+ struct statement_list;
+ struct return_statement;
+
+ typedef boost::variant<
+ variable_declaration
+ , assignment
+ , boost::recursive_wrapper<if_statement>
+ , boost::recursive_wrapper<while_statement>
+ , boost::recursive_wrapper<return_statement>
+ , boost::recursive_wrapper<statement_list>
+ >
+ statement;
+
+ struct statement_list : std::list<statement> {};
+
+ struct if_statement
+ {
+ expression condition;
+ statement then;
+ boost::optional<statement> else_;
+ };
+
+ struct while_statement
+ {
+ expression condition;
+ statement body;
+ };
+
+ struct return_statement : tagged
+ {
+ boost::optional<expression> expr;
+ };
+
+ struct function
+ {
+ std::string return_type;
+ identifier function_name;
+ std::list<identifier> args;
+ boost::optional<statement_list> body;
+ };
+
+ typedef std::list<function> function_list;
+
+ // print functions for debugging
+ inline std::ostream& operator<<(std::ostream& out, nil)
+ {
+ out << "nil"; return out;
+ }
+
+ inline std::ostream& operator<<(std::ostream& out, identifier const& id)
+ {
+ out << id.name; return out;
+ }
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::unary,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::operation,
+ (client::ast::optoken, operator_)
+ (client::ast::operand, operand_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function_call,
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::expression>, args)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::expression,
+ (client::ast::operand, first)
+ (std::list<client::ast::operation>, rest)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::variable_declaration,
+ (client::ast::identifier, lhs)
+ (boost::optional<client::ast::expression>, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::assignment,
+ (client::ast::identifier, lhs)
+ (client::ast::expression, rhs)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::if_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, then)
+ (boost::optional<client::ast::statement>, else_)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::while_statement,
+ (client::ast::expression, condition)
+ (client::ast::statement, body)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::return_statement,
+ (boost::optional<client::ast::expression>, expr)
+)
+
+BOOST_FUSION_ADAPT_STRUCT(
+ client::ast::function,
+ (std::string, return_type)
+ (client::ast::identifier, function_name)
+ (std::list<client::ast::identifier>, args)
+ (boost::optional<client::ast::statement_list>, body)
+)
+
+#endif

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,606 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "config.hpp"
+#include "compiler.hpp"
+#include "vm.hpp"
+
+#include <boost/foreach.hpp>
+#include <boost/variant/apply_visitor.hpp>
+#include <boost/assert.hpp>
+#include <boost/lexical_cast.hpp>
+#include <set>
+
+namespace client { namespace code_gen
+{
+ void compiler::init_fpm()
+ {
+ // Set up the optimizer pipeline. Start with registering info about how the
+ // target lays out data structures.
+ fpm.add(new llvm::TargetData(*vm.execution_engine()->getTargetData()));
+ // Provide basic AliasAnalysis support for GVN.
+ fpm.add(llvm::createBasicAliasAnalysisPass());
+ // Promote allocas to registers.
+ fpm.add(llvm::createPromoteMemoryToRegisterPass());
+ // Do simple "peephole" optimizations and bit-twiddling optzns.
+ fpm.add(llvm::createInstructionCombiningPass());
+ // Reassociate expressions.
+ fpm.add(llvm::createReassociatePass());
+ // Eliminate Common SubExpressions.
+ fpm.add(llvm::createGVNPass());
+ // Simplify the control flow graph (deleting unreachable blocks, etc).
+ fpm.add(llvm::createCFGSimplificationPass());
+
+ fpm.doInitialization();
+ }
+
+ llvm::Value* compiler::operator()(unsigned int x)
+ {
+ return llvm::ConstantInt::get(context(), llvm::APInt(int_size, x));
+ }
+
+ llvm::Value* compiler::operator()(bool x)
+ {
+ return llvm::ConstantInt::get(context(), llvm::APInt(1, x));
+ }
+
+ llvm::Value* compiler::operator()(ast::identifier const& x)
+ {
+ // Look this variable up in the function.
+ llvm::Value* value = named_values[x.name];
+ if (value == 0)
+ {
+ error_handler(x.id, "Undeclared variable: " + x.name);
+ return 0;
+ }
+
+ // Load the value.
+ return builder.CreateLoad(value, x.name.c_str());
+ }
+
+ llvm::Value* compiler::operator()(ast::unary const& x)
+ {
+ llvm::Value* operand = boost::apply_visitor(*this, x.operand_);
+ if (operand == 0)
+ return 0;
+
+ switch (x.operator_)
+ {
+ case ast::op_minus: return builder.CreateNeg(operand, "negtmp");
+ case ast::op_not: return builder.CreateNot(operand, "nottmp");
+ case ast::op_plus: return operand;
+ default: BOOST_ASSERT(0); return 0;
+ }
+ }
+
+ llvm::Value* compiler::operator()(ast::function_call const& x)
+ {
+ llvm::Function* callee = vm.module()->getFunction(x.function_name.name);
+ if (callee == 0)
+ {
+ error_handler(x.function_name.id, "Function not found: " + x.function_name.name);
+ return false;
+ }
+
+ if (callee->arg_size() != x.args.size())
+ {
+ error_handler(x.function_name.id, "Wrong number of arguments: " + x.function_name.name);
+ return 0;
+ }
+
+ std::vector<llvm::Value*> args;
+ BOOST_FOREACH(ast::expression const& expr, x.args)
+ {
+ args.push_back((*this)(expr));
+ if (args.back() == 0)
+ return 0;
+ }
+
+ return builder.CreateCall(callee, args.begin(), args.end(), "calltmp");
+ }
+
+ namespace
+ {
+ int precedence[] = {
+ // precedence 1
+ 1, // op_comma
+
+ // precedence 2
+ 2, // op_assign
+ 2, // op_plus_assign
+ 2, // op_minus_assign
+ 2, // op_times_assign
+ 2, // op_divide_assign
+ 2, // op_mod_assign
+ 2, // op_bit_and_assign
+ 2, // op_bit_xor_assign
+ 2, // op_bitor_assign
+ 2, // op_shift_left_assign
+ 2, // op_shift_right_assign
+
+ // precedence 3
+ 3, // op_logical_or
+
+ // precedence 4
+ 4, // op_logical_and
+
+ // precedence 5
+ 5, // op_bit_or
+
+ // precedence 6
+ 6, // op_bit_xor
+
+ // precedence 7
+ 7, // op_bit_and
+
+ // precedence 8
+ 8, // op_equal
+ 8, // op_not_equal
+
+ // precedence 9
+ 9, // op_less
+ 9, // op_less_equal
+ 9, // op_greater
+ 9, // op_greater_equal
+
+ // precedence 10
+ 10, // op_shift_left
+ 10, // op_shift_right
+
+ // precedence 11
+ 11, // op_plus
+ 11, // op_minus
+
+ // precedence 12
+ 12, // op_times
+ 12, // op_divide
+ 12, // op_mod
+
+ // precedence 13
+ 13, // op_positive
+ 13, // op_negative
+ 13, // op_pre_incr
+ 13, // op_pre_decr
+ 13, // op_compl
+ 13, // op_not
+
+ // precedence 14
+ 14, // op_post_incr
+ 14 // op_post_decr
+ };
+ }
+
+ llvm::Value* compiler::compile_binary_expression(
+ llvm::Value* lhs, llvm::Value* rhs, ast::optoken op)
+ {
+ switch (op)
+ {
+ case ast::op_plus: return builder.CreateAdd(lhs, rhs, "addtmp");
+ case ast::op_minus: return builder.CreateSub(lhs, rhs, "subtmp");
+ case ast::op_times: return builder.CreateMul(lhs, rhs, "multmp");
+ case ast::op_divide: return builder.CreateSDiv(lhs, rhs, "divtmp");
+
+ case ast::op_equal: return builder.CreateICmpEQ(lhs, rhs, "eqtmp");
+ case ast::op_not_equal: return builder.CreateICmpNE(lhs, rhs, "netmp");
+ case ast::op_less: return builder.CreateICmpSLT(lhs, rhs, "slttmp");
+ case ast::op_less_equal: return builder.CreateICmpSLE(lhs, rhs, "sletmp");
+ case ast::op_greater: return builder.CreateICmpSGT(lhs, rhs, "sgttmp");
+ case ast::op_greater_equal: return builder.CreateICmpSGE(lhs, rhs, "sgetmp");
+
+ case ast::op_logical_or: return builder.CreateOr(lhs, rhs, "ortmp");
+ case ast::op_logical_and: return builder.CreateAnd(lhs, rhs, "andtmp");
+ default: BOOST_ASSERT(0); return 0;
+ }
+ }
+
+ inline int precedence_of(ast::optoken op)
+ {
+ return precedence[op & ~ast::op_mask];
+ }
+
+ // The Shunting-yard algorithm
+ llvm::Value* compiler::compile_expression(
+ int min_precedence,
+ llvm::Value* lhs,
+ std::list<ast::operation>::const_iterator& rest_begin,
+ std::list<ast::operation>::const_iterator rest_end)
+ {
+ while ((rest_begin != rest_end) &&
+ (precedence_of(rest_begin->operator_) >= min_precedence))
+ {
+ ast::optoken op = rest_begin->operator_;
+ llvm::Value* rhs = boost::apply_visitor(*this, rest_begin->operand_);
+ if (rhs == 0)
+ return 0;
+ ++rest_begin;
+
+ while ((rest_begin != rest_end) &&
+ (precedence_of(rest_begin->operator_) > precedence_of(op)))
+ {
+ ast::optoken next_op = rest_begin->operator_;
+ rhs = compile_expression(
+ precedence_of(next_op), rhs, rest_begin, rest_end);
+ }
+
+ lhs = compile_binary_expression(lhs, rhs, op);
+ }
+ return lhs;
+ }
+
+ llvm::Value* compiler::operator()(ast::expression const& x)
+ {
+ llvm::Value* lhs = boost::apply_visitor(*this, x.first);
+ if (lhs == 0)
+ return 0;
+ std::list<ast::operation>::const_iterator rest_begin = x.rest.begin();
+ return compile_expression(0, lhs, rest_begin, x.rest.end());
+ }
+
+ llvm::Value* compiler::operator()(ast::assignment const& x)
+ {
+ llvm::Value* lhs = named_values[x.lhs.name];
+ if (lhs == 0)
+ {
+ error_handler(x.lhs.id, "Undeclared variable: " + x.lhs.name);
+ return 0;
+ }
+
+ llvm::Value* rhs = (*this)(x.rhs);
+ if (rhs == 0)
+ return 0;
+
+ builder.CreateStore(rhs, lhs);
+ return rhs;
+ }
+
+ // Create an alloca instruction in the entry block of
+ // the function. This is used for mutable variables etc.
+ llvm::AllocaInst*
+ create_entry_block_alloca(
+ llvm::Function* function, std::string const& var, llvm::LLVMContext& context)
+ {
+ llvm::IRBuilder<> builder(
+ &function->getEntryBlock(), function->getEntryBlock().begin());
+ return builder.CreateAlloca(
+ llvm::Type::getIntNTy(context, int_size), 0, var.c_str());
+ }
+
+ bool compiler::operator()(ast::variable_declaration const& x)
+ {
+ if (named_values.find(x.lhs.name) != named_values.end())
+ {
+ error_handler(x.lhs.id, "Duplicate variable: " + x.lhs.name);
+ return false;
+ }
+
+ llvm::Function* function = builder.GetInsertBlock()->getParent();
+ llvm::Value* init = 0;
+ std::string const& var = x.lhs.name;
+
+ if (x.rhs) // if there's an RHS initializer
+ {
+ init = (*this)(*x.rhs);
+ if (init == 0) // don't add the variable if the RHS fails
+ return false;
+ }
+
+ llvm::AllocaInst* alloca
+ = create_entry_block_alloca(function, var, context());
+ if (init != 0)
+ builder.CreateStore(init, alloca);
+
+ // Remember this binding.
+ named_values[var] = alloca;
+ return true;
+ }
+
+ struct compiler::statement_compiler : compiler
+ {
+ typedef bool result_type;
+ };
+
+ compiler::statement_compiler& compiler::as_statement()
+ {
+ return *static_cast<statement_compiler*>(this);
+ }
+
+ bool compiler::operator()(ast::statement const& x)
+ {
+ return boost::apply_visitor(as_statement(), x);
+ }
+
+ bool compiler::operator()(ast::statement_list const& x)
+ {
+ BOOST_FOREACH(ast::statement const& s, x)
+ {
+ if (!(*this)(s))
+ return false;
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::if_statement const& x)
+ {
+ llvm::Value* condition = (*this)(x.condition);
+ if (condition == 0)
+ return 0;
+
+ llvm::Function* function = builder.GetInsertBlock()->getParent();
+
+ // Create blocks for the then and else cases. Insert the 'then' block at the
+ // end of the function.
+ llvm::BasicBlock* then_block = llvm::BasicBlock::Create(context(), "if.then", function);
+ llvm::BasicBlock* else_block = 0;
+ llvm::BasicBlock* exit_block = 0;
+
+ if (x.else_)
+ {
+ else_block = llvm::BasicBlock::Create(context(), "if.else");
+ builder.CreateCondBr(condition, then_block, else_block);
+ }
+ else
+ {
+ exit_block = llvm::BasicBlock::Create(context(), "if.end");
+ builder.CreateCondBr(condition, then_block, exit_block);
+ }
+
+ // Emit then value.
+ builder.SetInsertPoint(then_block);
+ if (!(*this)(x.then))
+ return 0;
+ if (then_block->getTerminator() == 0)
+ {
+ if (exit_block == 0)
+ exit_block = llvm::BasicBlock::Create(context(), "if.end");
+ builder.CreateBr(exit_block);
+ }
+ // Codegen of 'then' can change the current block, update then_block
+ then_block = builder.GetInsertBlock();
+
+ if (x.else_)
+ {
+ // Emit else block.
+ function->getBasicBlockList().push_back(else_block);
+ builder.SetInsertPoint(else_block);
+ if (!(*this)(*x.else_))
+ return 0;
+ if (else_block->getTerminator() == 0)
+ {
+ if (exit_block == 0)
+ exit_block = llvm::BasicBlock::Create(context(), "if.end");
+ builder.CreateBr(exit_block);
+ }
+ // Codegen of 'else' can change the current block, update else_block
+ else_block = builder.GetInsertBlock();
+ }
+
+ if (exit_block != 0)
+ {
+ // Emit exit block
+ function->getBasicBlockList().push_back(exit_block);
+ builder.SetInsertPoint(exit_block);
+ }
+ return true;
+ }
+
+ bool compiler::operator()(ast::while_statement const& x)
+ {
+ llvm::Function* function = builder.GetInsertBlock()->getParent();
+
+ llvm::BasicBlock* cond_block = llvm::BasicBlock::Create(context(), "while.cond", function);
+ llvm::BasicBlock* body_block = llvm::BasicBlock::Create(context(), "while.body");
+ llvm::BasicBlock* exit_block = llvm::BasicBlock::Create(context(), "while.end");
+
+ builder.CreateBr(cond_block);
+ builder.SetInsertPoint(cond_block);
+ llvm::Value* condition = (*this)(x.condition);
+ if (condition == 0)
+ return false;
+ builder.CreateCondBr(condition, body_block, exit_block);
+ function->getBasicBlockList().push_back(body_block);
+ builder.SetInsertPoint(body_block);
+
+ if (!(*this)(x.body))
+ return false;
+
+ if (body_block->getTerminator() == 0)
+ builder.CreateBr(cond_block); // loop back
+
+ // Emit exit block
+ function->getBasicBlockList().push_back(exit_block);
+ builder.SetInsertPoint(exit_block);
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::return_statement const& x)
+ {
+ if (void_return)
+ {
+ if (x.expr)
+ {
+ error_handler(
+ x.id, "'void' function returning a value: ");
+ return false;
+ }
+ }
+ else
+ {
+ if (!x.expr)
+ {
+ error_handler(
+ x.id, current_function_name
+ + " function must return a value: ");
+ return false;
+ }
+ }
+
+ if (x.expr)
+ {
+ llvm::Value* return_val = (*this)(*x.expr);
+ if (return_val == 0)
+ return false;
+ builder.CreateStore(return_val, return_alloca);
+ }
+
+ builder.CreateBr(return_block);
+ return true;
+ }
+
+ llvm::Function* compiler::function_decl(ast::function const& x)
+ {
+ void_return = x.return_type == "void";
+ current_function_name = x.function_name.name;
+
+ llvm::Type* int_type =
+ llvm::Type::getIntNTy(context(), int_size);
+ llvm::Type* void_type = llvm::Type::getVoidTy(context());
+
+ std::vector<llvm::Type*> ints(x.args.size(), int_type);
+ llvm::Type* return_type = void_return ? void_type : int_type;
+
+ llvm::FunctionType* function_type =
+ llvm::FunctionType::get(void_return ? void_type : int_type, ints, false);
+
+ llvm::Function* function =
+ llvm::Function::Create(
+ function_type, llvm::Function::ExternalLinkage,
+ current_function_name, vm.module());
+
+ // If function conflicted, the function already exixts. If it has a
+ // body, don't allow redefinition or reextern.
+ if (function->getName() != current_function_name)
+ {
+ // Delete the one we just made and get the existing one.
+ function->eraseFromParent();
+ function = vm.module()->getFunction(current_function_name);
+
+ // If function already has a body, reject this.
+ if (!function->empty())
+ {
+ error_handler(
+ x.function_name.id,
+ "Duplicate function: " + x.function_name.name);
+ return 0;
+ }
+
+ // If function took a different number of args, reject.
+ if (function->arg_size() != x.args.size())
+ {
+ error_handler(
+ x.function_name.id,
+ "Redefinition of function with different # args: "
+ + x.function_name.name);
+ return 0;
+ }
+
+ // Set names for all arguments.
+ llvm::Function::arg_iterator iter = function->arg_begin();
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ iter->setName(arg.name);
+ ++iter;
+ }
+ }
+ return function;
+ }
+
+ void compiler::function_allocas(ast::function const& x, llvm::Function* function)
+ {
+ // CreateArgumentAllocas - Create an alloca for each argument and register the
+ // argument in the symbol table so that references to it will succeed.
+ llvm::Function::arg_iterator iter = function->arg_begin();
+ BOOST_FOREACH(ast::identifier const& arg, x.args)
+ {
+ // Create an alloca for this variable.
+ llvm::AllocaInst* alloca =
+ create_entry_block_alloca(function, arg.name, context());
+
+ // Store the initial value into the alloca.
+ builder.CreateStore(iter, alloca);
+
+ // Add arguments to variable symbol table.
+ named_values[arg.name] = alloca;
+ ++iter;
+ }
+
+ if (!void_return)
+ {
+ // Create an alloca for the return value
+ return_alloca =
+ create_entry_block_alloca(function, "return.val", context());
+ }
+ }
+
+ bool compiler::operator()(ast::function const& x)
+ {
+ ///////////////////////////////////////////////////////////////////////
+ // the signature:
+ llvm::Function* function = function_decl(x);
+ if (function == 0)
+ return false;
+
+ ///////////////////////////////////////////////////////////////////////
+ // the body:
+ if (x.body) // compile the body if this is not a prototype
+ {
+ // Create a new basic block to start insertion into.
+ llvm::BasicBlock* block =
+ llvm::BasicBlock::Create(context(), "entry", function);
+ builder.SetInsertPoint(block);
+
+ function_allocas(x, function);
+ return_block = llvm::BasicBlock::Create(context(), "return");
+
+ if (!(*this)(*x.body))
+ {
+ // Error reading body, remove function.
+ function->eraseFromParent();
+ return false;
+ }
+
+ llvm::BasicBlock* last_block =
+ &function->getBasicBlockList().back();
+
+ // If the last block is unterminated, connect it to return_block
+ if (last_block->getTerminator() == 0)
+ {
+ builder.SetInsertPoint(last_block);
+ builder.CreateBr(return_block);
+ }
+
+ function->getBasicBlockList().push_back(return_block);
+ builder.SetInsertPoint(return_block);
+
+ if (void_return)
+ builder.CreateRetVoid();
+ else
+ builder.CreateRet(builder.CreateLoad(return_alloca, "return.val"));
+
+ //~ vm.module()->dump();
+
+ // Validate the generated code, checking for consistency.
+ llvm::verifyFunction(*function);
+
+ // Optimize the function.
+ fpm.run(*function);
+ }
+
+ return true;
+ }
+
+ bool compiler::operator()(ast::function_list const& x)
+ {
+ BOOST_FOREACH(ast::function const& f, x)
+ {
+ named_values.clear(); // clear the variables
+ if (!(*this)(f))
+ return false;
+ }
+ return true;
+ }
+}}
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/compiler.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,115 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_COMPILER_HPP)
+#define BOOST_SPIRIT_CONJURE_COMPILER_HPP
+
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include "vm.hpp"
+#include <map>
+
+#include <boost/function.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/spirit/include/phoenix_core.hpp>
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/phoenix_operator.hpp>
+
+#include <llvm/DerivedTypes.h>
+#include <llvm/Constants.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Support/IRBuilder.h>
+
+namespace client { namespace code_gen
+{
+ ///////////////////////////////////////////////////////////////////////////
+ // The Compiler
+ ///////////////////////////////////////////////////////////////////////////
+ unsigned const int_size = 32;
+
+ struct compiler
+ {
+ typedef llvm::Value* result_type;
+
+ template <typename ErrorHandler>
+ compiler(vmachine& vm, ErrorHandler& error_handler_)
+ : vm(vm),
+ fpm(vm.module()),
+ builder(context())
+ {
+ using namespace boost::phoenix::arg_names;
+ namespace phx = boost::phoenix;
+ using boost::phoenix::function;
+
+ error_handler = function<ErrorHandler>(error_handler_)(
+ "Error! ", _2, phx::cref(error_handler_.iters)[_1]);
+
+ init_fpm();
+ }
+
+ llvm::Value* operator()(ast::nil) { BOOST_ASSERT(0); return 0; }
+ llvm::Value* operator()(unsigned int x);
+ llvm::Value* operator()(bool x);
+ llvm::Value* operator()(ast::identifier const& x);
+ llvm::Value* operator()(ast::unary const& x);
+ llvm::Value* operator()(ast::function_call const& x);
+ llvm::Value* operator()(ast::expression const& x);
+ llvm::Value* operator()(ast::assignment const& x);
+
+ bool operator()(ast::variable_declaration const& x);
+ bool operator()(ast::statement_list const& x);
+ bool operator()(ast::statement const& x);
+ bool operator()(ast::if_statement const& x);
+ bool operator()(ast::while_statement const& x);
+ bool operator()(ast::return_statement const& x);
+ bool operator()(ast::function const& x);
+ bool operator()(ast::function_list const& x);
+
+ private:
+
+ boost::function<
+ void(int tag, std::string const& what)>
+ error_handler;
+
+ bool void_return;
+ std::string current_function_name;
+ std::map<std::string, llvm::AllocaInst*> named_values;
+ llvm::BasicBlock* return_block;
+ llvm::AllocaInst* return_alloca;
+
+ vmachine& vm;
+ llvm::IRBuilder<> builder;
+ llvm::FunctionPassManager fpm;
+
+ llvm::LLVMContext& context() const
+ { return llvm::getGlobalContext(); }
+
+ llvm::Module* init_llvm();
+ void init_fpm();
+
+ llvm::Value* compile_binary_expression(
+ llvm::Value* lhs, llvm::Value* rhs, ast::optoken op);
+
+ llvm::Value* compile_expression(
+ int min_precedence,
+ llvm::Value* lhs,
+ std::list<ast::operation>::const_iterator& rest_begin,
+ std::list<ast::operation>::const_iterator rest_end);
+
+ struct statement_compiler;
+ statement_compiler& as_statement();
+
+ llvm::Function* function_decl(ast::function const& x);
+ void function_allocas(ast::function const& x, llvm::Function* function);
+ };
+}}
+
+#endif
\ No newline at end of file

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/config.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,51 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_CONFIG_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// The conjure lexer example can be built in 3 different variations:
+//
+// - With a lexer using runtime generated DFA tables
+// - With a lexer using pre-generated (static) DFA tables
+// - With a lexer using a pre-generated custom switch based state machine
+//
+// Use one of the following preprocessor constants to define, which of those
+// will be built:
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_DYNAMIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on pre-generated static DFA tables
+// #define CONJURE_LEXER_STATIC_TABLES 1
+
+///////////////////////////////////////////////////////////////////////////////
+// Use the lexer based on runtime generated DFA tables
+// #define CONJURE_LEXER_STATIC_SWITCH 1
+
+///////////////////////////////////////////////////////////////////////////////
+// The default is to use the dynamic table driven lexer
+#if CONJURE_LEXER_DYNAMIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_TABLES == 0 && \
+ CONJURE_LEXER_STATIC_SWITCH == 0
+
+#define CONJURE_LEXER_DYNAMIC_TABLES 1
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+// Make sure we have only one lexer type selected
+#if (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_TABLES != 0) || \
+ (CONJURE_LEXER_DYNAMIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0) || \
+ (CONJURE_LEXER_STATIC_TABLES != 0 && CONJURE_LEXER_STATIC_SWITCH != 0)
+
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+
+#endif
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,484 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUN__4_2011_19_46_16)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_JUN__4_2011_19_46_16
+
+#include <boost/detail/iterator.hpp>
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ enum {end_state_index, id_index, unique_id_index, state_index, bol_index,
+ eol_index, dead_state_index, dfa_offset};
+
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+ static std::size_t const lookup_[256] = {
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 7, 7, 41, 41, 7, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 7, 8, 41, 41, 41, 41, 9, 41,
+ 10, 11, 12, 13, 14, 15, 41, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 41, 19, 20, 21, 22, 41,
+ 41, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 18, 18, 18, 18, 18,
+ 18, 18, 18, 41, 41, 41, 41, 18,
+ 41, 23, 18, 18, 24, 25, 26, 18,
+ 27, 28, 18, 18, 29, 18, 30, 31,
+ 18, 18, 32, 33, 34, 35, 36, 37,
+ 18, 18, 18, 38, 39, 40, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 41, 41, 41, 41, 41, 41, 41 };
+ static std::size_t const dfa_alphabet_ = 42;
+ static std::size_t const dfa_[2604] = {
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 27, 13, 11, 20, 21, 18, 16,
+ 24, 17, 19, 2, 26, 25, 14, 12,
+ 15, 26, 26, 7, 4, 26, 6, 26,
+ 26, 26, 9, 26, 3, 26, 5, 8,
+ 22, 10, 23, 0, 1, 65645, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 2, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 28, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65636, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 29,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65636, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 30, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65636, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 32, 26,
+ 26, 26, 31, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 33, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65636, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 34, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65636, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 35, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 36, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 37,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 61, 26, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 38, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 327715, 20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 39,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 196627, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 40, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 196629,
+ 14, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 41, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 458777, 16, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 458778, 17, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 196635, 18, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 196636,
+ 19, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 42, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 40, 21, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 41, 22, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 123, 23, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 125,
+ 24, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 44, 25, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 59, 27, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 65636, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65638,
+ 30, 0, 0, 0, 0, 27, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 65636, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 43, 26, 26, 0, 0,
+ 0, 0, 1, 65636, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 44,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65636, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 45, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 46, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65641, 4, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65636, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 47, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65636, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 48, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 49, 26, 26, 26, 0, 0, 0, 0,
+ 1, 196620, 8, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 196621, 9, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 196625, 10, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 196626,
+ 11, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 196628, 13, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 196630, 15, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 42, 42, 42, 42, 42,
+ 50, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 42, 42,
+ 42, 42, 42, 42, 42, 42, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 51,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65636, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 43, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65636, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 52, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65640, 3, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 53,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65636, 28, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 54, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65636, 28, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 55, 26, 26,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 56, 56, 56, 56, 56,
+ 50, 56, 56, 56, 57, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 1, 65646,
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 1, 65639, 2, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 26, 26, 0, 0, 0, 0, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 0, 0,
+ 0, 0, 1, 65642, 5, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0, 1, 65636, 28, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 58, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 59, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 65637, 29, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 1, 65643, 6, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 26, 26, 0,
+ 0, 0, 0, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 0, 0, 0, 0, 1, 65636,
+ 28, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 26,
+ 26, 0, 0, 0, 0, 26, 26, 26,
+ 26, 26, 26, 26, 61, 26, 26, 26,
+ 26, 26, 26, 26, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 56,
+ 56, 56, 56, 56, 60, 56, 56, 56,
+ 57, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 1, 65644, 7, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 26, 26, 0, 0, 0,
+ 0, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26,
+ 0, 0, 0, 0 };
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ std::size_t const* ptr_ = dfa_ + dfa_alphabet_;
+ Iterator curr_ = start_token_;
+ bool end_state_ = *ptr_ != 0;
+ std::size_t id_ = *(ptr_ + id_index);
+ std::size_t uid_ = *(ptr_ + unique_id_index);
+ Iterator end_token_ = start_token_;
+
+ while (curr_ != end_)
+ {
+ std::size_t const state_ =
+ ptr_[lookup_[static_cast<unsigned char>(*curr_++)]];
+
+ if (state_ == 0) break;
+
+ ptr_ = &dfa_[state_ * dfa_alphabet_];
+
+ if (*ptr_)
+ {
+ end_state_ = true;
+ id_ = *(ptr_ + id_index);
+ uid_ = *(ptr_ + unique_id_index);
+ end_token_ = curr_;
+ }
+ }
+
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_lexer_generate.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,43 @@
+// Copyright (c) 2001-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// This small utility program generates the 2 static lexers, the static table
+// driven and the static switch based lexer.
+
+#include <fstream>
+#include <iostream>
+
+#include "lexer_def.hpp"
+#include <boost/spirit/include/lex_generate_static_lexertl.hpp>
+
+int main()
+{
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+
+ lexer_type lexer;
+
+ // first generate the static switch based lexer
+ std::ofstream out_static("conjure_static_switch_lexer.hpp");
+
+ bool result = boost::spirit::lex::lexertl::generate_static_switch(
+ lexer, out_static, "conjure_static_switch");
+ if (!result) {
+ std::cerr << "Failed to generate static switch based lexer\n";
+ return -1;
+ }
+
+ // now generate the static table based lexer
+ std::ofstream out("conjure_static_lexer.hpp");
+ result = boost::spirit::lex::lexertl::generate_static(
+ lexer, out, "conjure_static");
+ if (!result) {
+ std::cerr << "Failed to generate static table based lexer\n";
+ return -1;
+ }
+
+ return 0;
+}
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/conjure_static_switch_lexer.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,874 @@
+// Copyright (c) 2008-2009 Ben Hanson
+// Copyright (c) 2008-2011 Hartmut Kaiser
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file licence_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+// Auto-generated by boost::lexer, do not edit
+
+#if !defined(BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUN__4_2011_19_46_16)
+#define BOOST_SPIRIT_LEXER_NEXT_TOKEN_CONJURE_STATIC_SWITCH_JUN__4_2011_19_46_16
+
+#include <boost/detail/iterator.hpp>
+#include <boost/spirit/home/support/detail/lexer/char_traits.hpp>
+
+////////////////////////////////////////////////////////////////////////////////
+// the generated table of state names and the tokenizer have to be
+// defined in the boost::spirit::lex::lexertl::static_ namespace
+namespace boost { namespace spirit { namespace lex { namespace lexertl { namespace static_ {
+
+////////////////////////////////////////////////////////////////////////////////
+// this table defines the names of the lexer states
+char const* const lexer_state_names_conjure_static_switch[1] =
+{
+ "INITIAL"
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// this variable defines the number of lexer states
+std::size_t const lexer_state_count_conjure_static_switch = 1;
+
+////////////////////////////////////////////////////////////////////////////////
+// this function returns the next matched token
+template<typename Iterator>
+std::size_t next_token_conjure_static_switch (std::size_t& /*start_state_*/, bool& /*bol_*/,
+ Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+{
+ static std::size_t const npos = static_cast<std::size_t>(~0);
+
+ if (start_token_ == end_)
+ {
+ unique_id_ = npos;
+ return 0;
+ }
+
+ Iterator curr_ = start_token_;
+ bool end_state_ = false;
+ std::size_t id_ = npos;
+ std::size_t uid_ = npos;
+ Iterator end_token_ = start_token_;
+
+ char ch_ = 0;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+
+ if (ch_ == 't') goto state0_2;
+
+ if (ch_ == 'f') goto state0_3;
+
+ if (ch_ == 'v') goto state0_4;
+
+ if (ch_ == 'i') goto state0_5;
+
+ if (ch_ == 'e') goto state0_6;
+
+ if (ch_ == 'w') goto state0_7;
+
+ if (ch_ == 'r') goto state0_8;
+
+ if (ch_ == '|') goto state0_9;
+
+ if (ch_ == '&') goto state0_10;
+
+ if (ch_ == '=') goto state0_11;
+
+ if (ch_ == '!') goto state0_12;
+
+ if (ch_ == '<') goto state0_13;
+
+ if (ch_ == '>') goto state0_14;
+
+ if (ch_ == '+') goto state0_15;
+
+ if (ch_ == '-') goto state0_16;
+
+ if (ch_ == '*') goto state0_17;
+
+ if (ch_ == '/') goto state0_18;
+
+ if (ch_ == '(') goto state0_19;
+
+ if (ch_ == ')') goto state0_20;
+
+ if (ch_ == '{') goto state0_21;
+
+ if (ch_ == '}') goto state0_22;
+
+ if (ch_ == ',') goto state0_23;
+
+ if (ch_ == ';') goto state0_24;
+
+ if ((ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'g' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'q') || ch_ == 's' || ch_ == 'u' || (ch_ >= 'x' && ch_ <= 'z')) goto state0_25;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_1:
+ end_state_ = true;
+ id_ = 65645;
+ uid_ = 0;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9')) goto state0_1;
+ goto end;
+
+state0_2:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_27;
+ goto end;
+
+state0_3:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'b' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'a') goto state0_28;
+ goto end;
+
+state0_4:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'n') || (ch_ >= 'p' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'o') goto state0_29;
+ goto end;
+
+state0_5:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'e') || (ch_ >= 'g' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_30;
+
+ if (ch_ == 'f') goto state0_31;
+ goto end;
+
+state0_6:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_32;
+ goto end;
+
+state0_7:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'g') || (ch_ >= 'i' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'h') goto state0_33;
+ goto end;
+
+state0_8:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_34;
+ goto end;
+
+state0_9:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '|') goto state0_35;
+ goto end;
+
+state0_10:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '&') goto state0_36;
+ goto end;
+
+state0_11:
+ end_state_ = true;
+ id_ = 61;
+ uid_ = 26;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_37;
+ goto end;
+
+state0_12:
+ end_state_ = true;
+ id_ = 327715;
+ uid_ = 20;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_38;
+ goto end;
+
+state0_13:
+ end_state_ = true;
+ id_ = 196627;
+ uid_ = 12;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_39;
+ goto end;
+
+state0_14:
+ end_state_ = true;
+ id_ = 196629;
+ uid_ = 14;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '=') goto state0_40;
+ goto end;
+
+state0_15:
+ end_state_ = true;
+ id_ = 458777;
+ uid_ = 16;
+ end_token_ = curr_;
+ goto end;
+
+state0_16:
+ end_state_ = true;
+ id_ = 458778;
+ uid_ = 17;
+ end_token_ = curr_;
+ goto end;
+
+state0_17:
+ end_state_ = true;
+ id_ = 196635;
+ uid_ = 18;
+ end_token_ = curr_;
+ goto end;
+
+state0_18:
+ end_state_ = true;
+ id_ = 196636;
+ uid_ = 19;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_41;
+ goto end;
+
+state0_19:
+ end_state_ = true;
+ id_ = 40;
+ uid_ = 21;
+ end_token_ = curr_;
+ goto end;
+
+state0_20:
+ end_state_ = true;
+ id_ = 41;
+ uid_ = 22;
+ end_token_ = curr_;
+ goto end;
+
+state0_21:
+ end_state_ = true;
+ id_ = 123;
+ uid_ = 23;
+ end_token_ = curr_;
+ goto end;
+
+state0_22:
+ end_state_ = true;
+ id_ = 125;
+ uid_ = 24;
+ end_token_ = curr_;
+ goto end;
+
+state0_23:
+ end_state_ = true;
+ id_ = 44;
+ uid_ = 25;
+ end_token_ = curr_;
+ goto end;
+
+state0_24:
+ end_state_ = true;
+ id_ = 59;
+ uid_ = 27;
+ end_token_ = curr_;
+ goto end;
+
+state0_25:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_26:
+ end_state_ = true;
+ id_ = 65638;
+ uid_ = 30;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '\t' && ch_ <= '\n') || ch_ == '\r' || ch_ == ' ') goto state0_26;
+ goto end;
+
+state0_27:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_42;
+ goto end;
+
+state0_28:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_43;
+ goto end;
+
+state0_29:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_44;
+ goto end;
+
+state0_30:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_45;
+ goto end;
+
+state0_31:
+ end_state_ = true;
+ id_ = 65641;
+ uid_ = 4;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_32:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_46;
+ goto end;
+
+state0_33:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'h') || (ch_ >= 'j' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'i') goto state0_47;
+ goto end;
+
+state0_34:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 's') || (ch_ >= 'u' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 't') goto state0_48;
+ goto end;
+
+state0_35:
+ end_state_ = true;
+ id_ = 196620;
+ uid_ = 8;
+ end_token_ = curr_;
+ goto end;
+
+state0_36:
+ end_state_ = true;
+ id_ = 196621;
+ uid_ = 9;
+ end_token_ = curr_;
+ goto end;
+
+state0_37:
+ end_state_ = true;
+ id_ = 196625;
+ uid_ = 10;
+ end_token_ = curr_;
+ goto end;
+
+state0_38:
+ end_state_ = true;
+ id_ = 196626;
+ uid_ = 11;
+ end_token_ = curr_;
+ goto end;
+
+state0_39:
+ end_state_ = true;
+ id_ = 196628;
+ uid_ = 13;
+ end_token_ = curr_;
+ goto end;
+
+state0_40:
+ end_state_ = true;
+ id_ = 196630;
+ uid_ = 15;
+ end_token_ = curr_;
+ goto end;
+
+state0_41:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_41;
+
+ if (ch_ == '*') goto state0_49;
+ goto end;
+
+state0_42:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_50;
+ goto end;
+
+state0_43:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'r') || (ch_ >= 't' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 's') goto state0_42;
+ goto end;
+
+state0_44:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'c') || (ch_ >= 'e' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'd') goto state0_51;
+ goto end;
+
+state0_45:
+ end_state_ = true;
+ id_ = 65640;
+ uid_ = 3;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_46:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_52;
+ goto end;
+
+state0_47:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'k') || (ch_ >= 'm' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'l') goto state0_53;
+ goto end;
+
+state0_48:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 't') || (ch_ >= 'v' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'u') goto state0_54;
+ goto end;
+
+state0_49:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ == '*') goto state0_49;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+ goto end;
+
+state0_50:
+ end_state_ = true;
+ id_ = 65646;
+ uid_ = 1;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_51:
+ end_state_ = true;
+ id_ = 65639;
+ uid_ = 2;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_52:
+ end_state_ = true;
+ id_ = 65642;
+ uid_ = 5;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_53:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'd') || (ch_ >= 'f' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'e') goto state0_57;
+ goto end;
+
+state0_54:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'q') || (ch_ >= 's' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'r') goto state0_58;
+ goto end;
+
+state0_55:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*') goto state0_55;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_56:
+ end_state_ = true;
+ id_ = 65637;
+ uid_ = 29;
+ end_token_ = curr_;
+ goto end;
+
+state0_57:
+ end_state_ = true;
+ id_ = 65643;
+ uid_ = 6;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+ goto end;
+
+state0_58:
+ end_state_ = true;
+ id_ = 65636;
+ uid_ = 28;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'm') || (ch_ >= 'o' && ch_ <= 'z')) goto state0_25;
+
+ if (ch_ == 'n') goto state0_60;
+ goto end;
+
+state0_59:
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if (ch_ != '*' && ch_ != '/') goto state0_55;
+
+ if (ch_ == '/') goto state0_56;
+
+ if (ch_ == '*') goto state0_59;
+ goto end;
+
+state0_60:
+ end_state_ = true;
+ id_ = 65644;
+ uid_ = 7;
+ end_token_ = curr_;
+
+ if (curr_ == end_) goto end;
+ ch_ = *curr_;
+ ++curr_;
+
+ if ((ch_ >= '0' && ch_ <= '9') || (ch_ >= 'A' && ch_ <= 'Z') || ch_ == '_' || (ch_ >= 'a' && ch_ <= 'z')) goto state0_25;
+
+end:
+ if (end_state_)
+ {
+ // return longest match
+ start_token_ = end_token_;
+ }
+ else
+ {
+ id_ = npos;
+ uid_ = npos;
+ }
+
+ unique_id_ = uid_;
+ return id_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// this defines a generic accessors for the information above
+struct lexer_conjure_static_switch
+{
+ // version number and feature-set of compatible static lexer engine
+ enum
+ {
+ static_version = 65536,
+ supports_bol = false,
+ supports_eol = false
+ };
+
+ // return the number of lexer states
+ static std::size_t state_count()
+ {
+ return lexer_state_count_conjure_static_switch;
+ }
+
+ // return the name of the lexer state as given by 'idx'
+ static char const* state_name(std::size_t idx)
+ {
+ return lexer_state_names_conjure_static_switch[idx];
+ }
+
+ // return the next matched token
+ template<typename Iterator>
+ static std::size_t next(std::size_t &start_state_, bool& bol_
+ , Iterator &start_token_, Iterator const& end_, std::size_t& unique_id_)
+ {
+ return next_token_conjure_static_switch(start_state_, bol_, start_token_, end_, unique_id_);
+ }
+};
+
+}}}}} // namespace boost::spirit::lex::lexertl::static_
+
+#endif

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/error_handler.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,97 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP)
+#define BOOST_SPIRIT_CONJURE_ERROR_HANDLER_HPP
+
+#include <iostream>
+#include <string>
+#include <vector>
+
+namespace client
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The error handler
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator, typename Iterator>
+ struct error_handler
+ {
+ template <typename, typename, typename>
+ struct result { typedef void type; };
+
+ error_handler(BaseIterator first, BaseIterator last)
+ : first(first), last(last) {}
+
+ template <typename Message, typename What>
+ void operator()(
+ Message const& message,
+ What const& what,
+ Iterator err_pos) const
+ {
+ // retrieve underlying iterator from current token
+ BaseIterator err_pos_base = err_pos->matched().begin();
+
+ int line;
+ BaseIterator line_start = get_pos(err_pos_base, line);
+ if (err_pos_base != last)
+ {
+ std::cout << message << what << " line " << line << ':' << std::endl;
+ std::cout << get_line(line_start) << std::endl;
+ for (; line_start != err_pos_base; ++line_start)
+ std::cout << ' ';
+ std::cout << '^' << std::endl;
+ }
+ else
+ {
+ std::cout << "Unexpected end of file. ";
+ std::cout << message << what << " line " << line << std::endl;
+ }
+ }
+
+ BaseIterator get_pos(BaseIterator err_pos, int& line) const
+ {
+ line = 1;
+ BaseIterator i = first;
+ BaseIterator line_start = first;
+ while (i != err_pos)
+ {
+ bool eol = false;
+ if (i != err_pos && *i == '\r') // CR
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (i != err_pos && *i == '\n') // LF
+ {
+ eol = true;
+ line_start = ++i;
+ }
+ if (eol)
+ ++line;
+ else
+ ++i;
+ }
+ return line_start;
+ }
+
+ std::string get_line(BaseIterator err_pos) const
+ {
+ BaseIterator i = err_pos;
+ // position i to the next EOL
+ while (i != last && (*i != '\r' && *i != '\n'))
+ ++i;
+ return std::string(err_pos, i);
+ }
+
+ BaseIterator first;
+ BaseIterator last;
+ std::vector<Iterator> iters;
+ };
+}
+
+#endif
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "expression_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::expression<iterator_type, lexer_type>;

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,58 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_EXPRESSION_HPP)
+#define BOOST_SPIRIT_CONJURE_EXPRESSION_HPP
+
+///////////////////////////////////////////////////////////////////////////////
+// Spirit v2.5 allows you to suppress automatic generation
+// of predefined terminals to speed up complation. With
+// BOOST_SPIRIT_NO_PREDEFINED_TERMINALS defined, you are
+// responsible in creating instances of the terminals that
+// you need (e.g. see qi::uint_type uint_ below).
+#define BOOST_SPIRIT_NO_PREDEFINED_TERMINALS
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Uncomment this if you want to enable debugging
+// #define BOOST_SPIRIT_QI_DEBUG
+///////////////////////////////////////////////////////////////////////////////
+
+#include <boost/spirit/include/qi.hpp>
+#include "ast.hpp"
+#include "error_handler.hpp"
+#include <vector>
+
+namespace client { namespace parser
+{
+ namespace qi = boost::spirit::qi;
+ namespace ascii = boost::spirit::ascii;
+
+ ///////////////////////////////////////////////////////////////////////////////
+ // The expression grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct expression : qi::grammar<Iterator, ast::expression()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ expression(error_handler_type& error_handler, Lexer const& l);
+
+ Lexer const& lexer;
+
+ qi::rule<Iterator, ast::expression()> expr;
+ qi::rule<Iterator, ast::operand()> unary_expr, primary_expr;
+ qi::rule<Iterator, ast::function_call()> function_call;
+ qi::rule<Iterator, std::list<ast::expression>()> argument_list;
+ qi::rule<Iterator, std::string()> identifier;
+ };
+}}
+
+#endif
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/expression_def.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,94 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "expression.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+#include <boost/spirit/include/phoenix_function.hpp>
+#include <boost/spirit/include/lex_plain_token.hpp>
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ expression<Iterator, Lexer>::expression(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : expression::base_type(expr), lexer(l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::tokenid_mask_type tokenid_mask;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Main expression grammar
+ expr =
+ unary_expr
+ >> *(tokenid_mask(ast::op_binary) > unary_expr)
+ ;
+
+ unary_expr =
+ primary_expr
+ | (tokenid_mask(ast::op_unary) > primary_expr)
+ ;
+
+ primary_expr =
+ lexer.uint_
+ | function_call
+ | identifier
+ | lexer.bool_
+ | '(' > expr > ')'
+ ;
+
+ function_call =
+ (identifier >> '(')
+ > argument_list
+ > ')'
+ ;
+
+ argument_list = -(expr % ',');
+
+ identifier = lexer.identifier;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (expr)
+ (unary_expr)
+ (primary_expr)
+ (function_call)
+ (argument_list)
+ (identifier)
+ );
+
+ ///////////////////////////////////////////////////////////////////////
+ // Error handling: on error in expr, call error_handler.
+ on_error<fail>(expr,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ ///////////////////////////////////////////////////////////////////////
+ // Annotation: on success in primary_expr, call annotation.
+ on_success(primary_expr,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "function_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::function<iterator_type, lexer_type>;

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,36 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_FUNCTION_HPP)
+#define BOOST_SPIRIT_CONJURE_FUNCTION_HPP
+
+#include "statement.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The function grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct function : qi::grammar<Iterator, ast::function()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ function(error_handler_type& error_handler, Lexer const& l);
+
+ statement<Iterator, Lexer> body;
+
+ qi::rule<Iterator, ast::identifier()> identifier;
+ qi::rule<Iterator, std::list<ast::identifier>()> argument_list;
+ qi::rule<Iterator, ast::function()> start;
+ };
+}}
+
+#endif
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/function_def.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,66 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "token_ids.hpp"
+#include "function.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ function<Iterator, Lexer>::function(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : function::base_type(start), body(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::token_type token;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ identifier = body.expr.identifier;
+ argument_list = -(identifier % ',');
+
+ start = (token(lexer::ID_VOID_KWD) | token(lexer::ID_INT_KWD))
+ > identifier
+ > '(' > argument_list > ')'
+ > (';' | '{' > body > '}')
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (identifier)
+ (argument_list)
+ (start)
+ );
+
+ // Error handling: on error in start, call error_handler.
+ on_error<fail>(start,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in start, call annotation.
+ on_success(identifier,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,15 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+template client::lexer::conjure_tokens<base_iterator_type>::conjure_tokens();

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,82 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_LEXER_HPP)
+#define BOOST_SPIRIT_CONJURE_LEXER_HPP
+
+#include "config.hpp"
+#include "token_ids.hpp"
+
+#if CONJURE_LEXER_STATIC_TABLES != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_lexer.hpp"
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+#include <boost/spirit/include/lex_static_lexertl.hpp>
+#include "conjure_static_switch_lexer.hpp"
+#endif
+
+namespace client { namespace lexer
+{
+ ///////////////////////////////////////////////////////////////////////////
+ namespace detail
+ {
+ namespace lex = boost::spirit::lex;
+
+ template <typename BaseIterator>
+ struct get_lexer_type
+ {
+ // Our token needs to be able to carry several token values:
+ // std::string, unsigned int, and bool
+ typedef boost::mpl::vector<std::string, unsigned int, bool>
+ token_value_types;
+
+ // Using the position_token class as the token type to be returned
+ // from the lexer iterators allows to retain positional information
+ // as every token instance stores an iterator pair pointing to the
+ // matched input sequence.
+ typedef lex::lexertl::position_token<
+ BaseIterator, token_value_types, boost::mpl::false_
+ > token_type;
+
+#if CONJURE_LEXER_DYNAMIC_TABLES != 0
+ // use the lexer based on runtime generated DFA tables
+ typedef lex::lexertl::actor_lexer<token_type> type;
+#elif CONJURE_LEXER_STATIC_TABLES != 0
+ // use the lexer based on pre-generated static DFA tables
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static
+ > type;
+#elif CONJURE_LEXER_STATIC_SWITCH != 0
+ // use the lexer based on pre-generated static code
+ typedef lex::lexertl::static_actor_lexer<
+ token_type
+ , boost::spirit::lex::lexertl::static_::lexer_conjure_static_switch
+ > type;
+#else
+#error "Configuration problem: please select exactly one type of lexer to build"
+#endif
+ };
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ template <typename BaseIterator>
+ struct conjure_tokens
+ : lex::lexer<typename detail::get_lexer_type<BaseIterator>::type>
+ {
+ typedef BaseIterator base_iterator_type;
+
+ conjure_tokens();
+
+ lex::token_def<std::string> identifier;
+ lex::token_def<unsigned int> uint_;
+ lex::token_def<bool> bool_;
+ };
+}}
+
+#endif
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/lexer_def.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,62 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+
+#include "lexer.hpp"
+
+namespace client { namespace lexer
+{
+ template <typename BaseIterator>
+ conjure_tokens<BaseIterator>::conjure_tokens()
+ : identifier("[a-zA-Z_][a-zA-Z_0-9]*", ID_IDENTIFIER)
+ , uint_("[0-9]+", ID_UINT)
+ , bool_("true|false", ID_BOOL)
+ {
+ lex::_pass_type _pass;
+
+ this->self = uint_ | bool_;
+
+ this->self.add
+ ("void", ID_VOID_KWD)
+ ("int", ID_INT_KWD)
+ ("if", ID_IF_KWD)
+ ("else", ID_ELSE_KWD)
+ ("while", ID_WHILE_KWD)
+ ("return", ID_RETURN_KWD)
+ ;
+
+ this->self.add
+ ("\\|\\|", ID_OP_LOGICAL_OR)
+ ("&&", ID_OP_LOGICAL_AND)
+ ("==", ID_OP_EQUAL)
+ ("!=", ID_OP_NOT_EQUAL)
+ ("<", ID_OP_LESS)
+ ("<=", ID_OP_LESS_EQUAL)
+ (">", ID_OP_GREATER)
+ (">=", ID_OP_GREATER_EQUAL)
+ ("\\+", ID_OP_PLUS)
+ ("\\-", ID_OP_MINUS)
+ ("\\*", ID_OP_TIMES)
+ ("\\/", ID_OP_DIVIDE)
+ ("!", ID_OP_NOT)
+ ;
+
+ this->self += lex::char_('(') | ')' | '{' | '}' | ',' | '=' | ';';
+
+ this->self +=
+ identifier
+ | lex::string("\\/\\*[^*]*\\*+([^/*][^*]*\\*+)*\\/", ID_COMMENT)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ | lex::string("[ \t\n\r]+", ID_WHITESPACE)
+ [
+ lex::_pass = lex::pass_flags::pass_ignore
+ ]
+ ;
+ }
+}}
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/main.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,159 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+///////////////////////////////////////////////////////////////////////////////
+//
+// Not a calculator anymore, right? :-)
+//
+// [ JDG April 10, 2007 ] spirit2
+// [ JDG February 18, 2011 ] Pure attributes. No semantic actions.
+// [ HK June 3, 2011 ] Adding lexer
+//
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Define this to enable debugging
+//#define BOOST_SPIRIT_QI_DEBUG
+
+#include "config.hpp"
+#include "function.hpp"
+#include "vm.hpp"
+#include "compiler.hpp"
+#include "lexer.hpp"
+#include <boost/lexical_cast.hpp>
+#include <fstream>
+
+///////////////////////////////////////////////////////////////////////////////
+// Main program
+///////////////////////////////////////////////////////////////////////////////
+int main(int argc, char **argv)
+{
+ char const* filename;
+ if (argc > 1)
+ {
+ filename = argv[1];
+ }
+ else
+ {
+ std::cerr << "Error: No input file provided." << std::endl;
+ return 1;
+ }
+
+ std::ifstream in(filename, std::ios_base::in);
+
+ if (!in)
+ {
+ std::cerr << "Error: Could not open input file: "
+ << filename << std::endl;
+ return 1;
+ }
+
+ std::string source_code; // We will read the contents here.
+ in.unsetf(std::ios::skipws); // No white space skipping!
+ std::copy(
+ std::istream_iterator<char>(in),
+ std::istream_iterator<char>(),
+ std::back_inserter(source_code));
+
+ typedef std::string::const_iterator base_iterator_type;
+ typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+ typedef lexer_type::iterator_type iterator_type;
+
+ lexer_type lexer; // Our lexer
+
+ base_iterator_type first = source_code.begin();
+ base_iterator_type last = source_code.end();
+
+ iterator_type iter = lexer.begin(first, last);
+ iterator_type end = lexer.end();
+
+ client::vmachine vm; // Our virtual machine
+ client::ast::function_list ast; // Our AST
+
+ client::error_handler<base_iterator_type, iterator_type>
+ error_handler(first, last); // Our error handler
+ client::parser::function<iterator_type, lexer_type>
+ function(error_handler, lexer); // Our parser
+ client::code_gen::compiler
+ compiler(vm, error_handler); // Our compiler
+
+ // note: we don't need a skipper
+ bool success = parse(iter, end, +function, ast);
+
+ std::cout << "-------------------------\n";
+
+ if (success && iter == end)
+ {
+ if (compiler(ast))
+ {
+ // JIT the main function
+ client::function main_function = vm.get_function("main");
+ if (!main_function)
+ {
+ std::cerr << "function main not found" << std::endl;
+ return 1;
+ }
+
+ int nargs = argc-2;
+ if (main_function.arity() != nargs)
+ {
+ std::cerr << "Error: main function requires "
+ << main_function.arity() << " arguments." << std::endl;
+ std::cerr << nargs << " supplied." << std::endl;
+ return 1;
+ }
+
+ std::cout << "Success\n";
+ std::cout << "-------------------------\n";
+ std::cout << "Assembler----------------\n\n";
+ vm.print_assembler();
+
+ // Call the main function
+ int r;
+ char** args = argv + 2;
+ switch (nargs)
+ {
+ case 0: r = main_function(); break;
+
+ case 1: r = main_function(
+ boost::lexical_cast<int>(args[0]));
+ break;
+
+ case 2: r = main_function(
+ boost::lexical_cast<int>(args[0]),
+ boost::lexical_cast<int>(args[1]));
+ break;
+
+ case 3: r = main_function(
+ boost::lexical_cast<int>(args[0]),
+ boost::lexical_cast<int>(args[1]),
+ boost::lexical_cast<int>(args[2]));
+ break;
+
+ default:
+ std::cerr << "Function calls with more " <<
+ "than 3 arguments not supported" << std::endl;
+ return 1;
+ }
+
+ std::cout << "-------------------------\n";
+ std::cout << "Result: " << r << std::endl;
+ std::cout << "-------------------------\n\n";
+ }
+ else
+ {
+ std::cout << "Compile failure\n";
+ }
+ }
+ else
+ {
+ std::cout << "Parse failure\n";
+ }
+ return 0;
+}
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,20 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if defined(_MSC_VER)
+# pragma warning(disable: 4345)
+#endif
+
+#include "config.hpp"
+#include "lexer.hpp"
+#include "statement_def.hpp"
+
+typedef std::string::const_iterator base_iterator_type;
+typedef client::lexer::conjure_tokens<base_iterator_type> lexer_type;
+typedef lexer_type::iterator_type iterator_type;
+
+template struct client::parser::statement<iterator_type, lexer_type>;

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,42 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_STATEMENT_HPP)
+#define BOOST_SPIRIT_CONJURE_STATEMENT_HPP
+
+#include "expression.hpp"
+
+namespace client { namespace parser
+{
+ ///////////////////////////////////////////////////////////////////////////////
+ // The statement grammar
+ ///////////////////////////////////////////////////////////////////////////////
+ template <typename Iterator, typename Lexer>
+ struct statement : qi::grammar<Iterator, ast::statement_list()>
+ {
+ typedef error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+
+ statement(error_handler_type& error_handler, Lexer const& l);
+
+ expression<Iterator, Lexer> expr;
+
+ qi::rule<Iterator, ast::statement_list()>
+ statement_list, compound_statement;
+
+ qi::rule<Iterator, ast::statement()> statement_;
+ qi::rule<Iterator, ast::variable_declaration()> variable_declaration;
+ qi::rule<Iterator, ast::assignment()> assignment;
+ qi::rule<Iterator, ast::if_statement()> if_statement;
+ qi::rule<Iterator, ast::while_statement()> while_statement;
+ qi::rule<Iterator, ast::return_statement()> return_statement;
+ };
+}}
+
+#endif
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/statement_def.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,117 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "token_ids.hpp"
+#include "statement.hpp"
+#include "error_handler.hpp"
+#include "annotation.hpp"
+
+namespace client { namespace parser
+{
+ template <typename Iterator, typename Lexer>
+ statement<Iterator, Lexer>::statement(
+ error_handler<typename Lexer::base_iterator_type, Iterator>& error_handler
+ , Lexer const& l)
+ : statement::base_type(statement_list), expr(error_handler, l)
+ {
+ qi::_1_type _1;
+ qi::_2_type _2;
+ qi::_3_type _3;
+ qi::_4_type _4;
+
+ qi::_val_type _val;
+ qi::raw_token_type raw_token;
+
+ using qi::on_error;
+ using qi::on_success;
+ using qi::fail;
+ using boost::phoenix::function;
+
+ typedef client::error_handler<typename Lexer::base_iterator_type, Iterator>
+ error_handler_type;
+ typedef function<error_handler_type> error_handler_function;
+ typedef function<client::annotation<Iterator> > annotation_function;
+
+ statement_list =
+ +statement_
+ ;
+
+ statement_ =
+ variable_declaration
+ | assignment
+ | compound_statement
+ | if_statement
+ | while_statement
+ | return_statement
+ ;
+
+ variable_declaration =
+ raw_token(lexer::ID_INT_KWD)
+ > expr.identifier
+ > -('=' > expr)
+ > ';'
+ ;
+
+ assignment =
+ expr.identifier
+ > '='
+ > expr
+ > ';'
+ ;
+
+ if_statement =
+ raw_token(lexer::ID_IF_KWD)
+ > '('
+ > expr
+ > ')'
+ > statement_
+ >
+ -(
+ raw_token(lexer::ID_ELSE_KWD)
+ > statement_
+ )
+ ;
+
+ while_statement =
+ raw_token(lexer::ID_WHILE_KWD)
+ > '('
+ > expr
+ > ')'
+ > statement_
+ ;
+
+ compound_statement =
+ '{' >> -statement_list >> '}'
+ ;
+
+ return_statement =
+ raw_token(lexer::ID_RETURN_KWD)
+ > -expr
+ > ';'
+ ;
+
+ // Debugging and error handling and reporting support.
+ BOOST_SPIRIT_DEBUG_NODES(
+ (statement_list)
+ (variable_declaration)
+ (assignment)
+ );
+
+ // Error handling: on error in statement_list, call error_handler.
+ on_error<fail>(statement_list,
+ error_handler_function(error_handler)(
+ "Error! Expecting ", _4, _3));
+
+ // Annotation: on success in assignment, call annotation.
+ on_success(assignment,
+ annotation_function(error_handler.iters)(_val, _1));
+ on_success(return_statement,
+ annotation_function(error_handler.iters)(_val, _1));
+ }
+}}
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/token_ids.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/token_ids.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,55 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Hartmut Kaiser
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_TOKEN_IDS_HPP)
+#define BOOST_SPIRIT_CONJURE_TOKEN_IDS_HPP
+
+#include <boost/spirit/include/lex_lexertl.hpp>
+#include <boost/spirit/include/lex_lexertl_position_token.hpp>
+
+namespace client { namespace lexer
+{
+ namespace lex = boost::spirit::lex;
+
+ enum tokenids
+ {
+ ID_OP_OPERATOR = 0x10000,
+ ID_OP_BINARY = 0x20000,
+ ID_OP_UNARY = 0x40000,
+
+ // the token ids (added values below) have to correspond to the
+ // sequence numbers used in the ast::optoken enumeration
+ ID_OP_LOGICAL_OR = (ID_OP_OPERATOR | ID_OP_BINARY) + 12,
+ ID_OP_LOGICAL_AND = (ID_OP_OPERATOR | ID_OP_BINARY) + 13,
+ ID_OP_EQUAL = (ID_OP_OPERATOR | ID_OP_BINARY) + 17,
+ ID_OP_NOT_EQUAL = (ID_OP_OPERATOR | ID_OP_BINARY) + 18,
+ ID_OP_LESS = (ID_OP_OPERATOR | ID_OP_BINARY) + 19,
+ ID_OP_LESS_EQUAL = (ID_OP_OPERATOR | ID_OP_BINARY) + 20,
+ ID_OP_GREATER = (ID_OP_OPERATOR | ID_OP_BINARY) + 21,
+ ID_OP_GREATER_EQUAL = (ID_OP_OPERATOR | ID_OP_BINARY) + 22,
+ ID_OP_PLUS = (ID_OP_OPERATOR | ID_OP_UNARY | ID_OP_BINARY) + 25,
+ ID_OP_MINUS = (ID_OP_OPERATOR | ID_OP_UNARY | ID_OP_BINARY) + 26,
+ ID_OP_TIMES = (ID_OP_OPERATOR | ID_OP_BINARY) + 27,
+ ID_OP_DIVIDE = (ID_OP_OPERATOR | ID_OP_BINARY) + 28,
+ ID_OP_NOT = (ID_OP_OPERATOR | ID_OP_UNARY) + 35,
+
+ ID_IDENTIFIER = ID_OP_OPERATOR + 100,
+ ID_COMMENT,
+ ID_WHITESPACE,
+ ID_VOID_KWD,
+ ID_INT_KWD,
+ ID_IF_KWD,
+ ID_ELSE_KWD,
+ ID_WHILE_KWD,
+ ID_RETURN_KWD,
+ ID_UINT,
+ ID_BOOL
+ };
+}}
+
+#endif
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.cpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,43 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#include "config.hpp"
+#include "vm.hpp"
+#include <iostream>
+
+#if defined(_MSC_VER)
+# pragma warning(disable: 4800) // forcing value to bool 'true' or 'false'
+ // (performance warning)
+#endif
+
+namespace client
+{
+ vmachine::vmachine()
+ {
+ llvm::InitializeNativeTarget();
+ llvm::LLVMContext& context = llvm::getGlobalContext();
+
+ // Make the module, which holds all the code.
+ module_ = new llvm::Module("Conjure JIT", context);
+
+ // Create the JIT. This takes ownership of the module.
+ std::string error;
+ execution_engine_ =
+ llvm::EngineBuilder(module_).setErrorStr(&error).create();
+
+ BOOST_ASSERT(execution_engine_ != 0);
+ if (!execution_engine_)
+ {
+ std::cerr <<
+ "Could not create ExecutionEngine: " <<
+ error << std::endl;
+
+ exit(1);
+ }
+ }
+}
+
+

Added: trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/spirit/example/qi/compiler_tutorial/conjure3/vm.hpp 2011-07-18 00:06:05 EDT (Mon, 18 Jul 2011)
@@ -0,0 +1,121 @@
+/*=============================================================================
+ Copyright (c) 2001-2011 Joel de Guzman
+
+ Distributed under the Boost Software License, Version 1.0. (See accompanying
+ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+=============================================================================*/
+#if !defined(BOOST_SPIRIT_CONJURE_VM_HPP)
+#define BOOST_SPIRIT_CONJURE_VM_HPP
+
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/ExecutionEngine/JIT.h>
+#include <llvm/LLVMContext.h>
+#include <llvm/Module.h>
+#include <llvm/Target/TargetData.h>
+#include <llvm/Target/TargetSelect.h>
+
+#include <boost/assert.hpp>
+
+namespace client
+{
+ class vmachine;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // A light wrapper to a function pointer returning int and accepting
+ // from 0 to 3 arguments, where arity is determined at runtime.
+ ///////////////////////////////////////////////////////////////////////////
+ class function
+ {
+ public:
+
+ typedef int result_type;
+
+ int operator()() const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 0);
+ int (*fp)() = (int(*)())(intptr_t)fptr;
+ return fp();
+ }
+
+ int operator()(int _1) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 1);
+ int (*fp)(int) = (int(*)(int))(intptr_t)fptr;
+ return fp(_1);
+ }
+
+ int operator()(int _1, int _2) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 2);
+ int (*fp)(int, int) = (int(*)(int, int))(intptr_t)fptr;
+ return fp(_1, _2);
+ }
+
+ int operator()(int _1, int _2, int _3) const
+ {
+ BOOST_ASSERT(fptr != 0);
+ BOOST_ASSERT(arity() == 3);
+ int (*fp)(int, int, int) = (int(*)(int, int, int))(intptr_t)fptr;
+ return fp(_1, _2, _3);
+ }
+
+ unsigned arity() const { return arity_; }
+ bool operator!() const { return fptr == 0; }
+
+ private:
+
+ friend class vmachine;
+ function(void* fptr, unsigned arity_)
+ : fptr(fptr), arity_(arity_) {}
+
+ void* fptr;
+ unsigned arity_;
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // The Virtual Machine (light wrapper over LLVM JIT)
+ ///////////////////////////////////////////////////////////////////////////
+ class vmachine
+ {
+ public:
+
+ vmachine();
+
+ llvm::Module* module() const
+ {
+ return module_;
+ }
+
+ llvm::ExecutionEngine* execution_engine() const
+ {
+ return execution_engine_;
+ }
+
+ void print_assembler() const
+ {
+ module_->dump();
+ }
+
+ function get_function(char const* name)
+ {
+ llvm::Function* callee = module_->getFunction(name);
+ if (callee == 0)
+ return function(0, 0);
+
+ // JIT the function
+ void *fptr = execution_engine_->getPointerToFunction(callee);
+ return function(fptr, callee->arg_size());
+ }
+
+ private:
+
+ llvm::Module* module_;
+ llvm::ExecutionEngine* execution_engine_;
+ };
+}
+
+#endif
+


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk