blob: d564c3a2a65cea271186dd43daba2dce5da84007 [file] [log] [blame]
/*=============================================================================
Copyright (c) 2001-2010 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_CALC7C)
#define BOOST_SPIRIT_CALC7C
#include "calc7.hpp"
///////////////////////////////////////////////////////////////////////////////
// Our statement grammar and compiler
///////////////////////////////////////////////////////////////////////////////
template <typename Iterator>
statement<Iterator>::statement(std::vector<int>& code)
: statement::base_type(statement_list)
, code(code)
, nvars(0)
, expr(code, vars)
, add_var(vars)
, op(code)
{
using qi::lexeme;
using qi::lit;
using qi::raw;
using namespace qi::labels;
using qi::on_error;
using qi::fail;
using ascii::alnum;
using ascii::alpha;
identifier %=
raw[lexeme[alpha >> *(alnum | '_')]]
;
var_ref =
lexeme
[
vars [_val = _1]
>> !(alnum | '_') // make sure we have whole words
]
;
var_decl =
lexeme[
"var"
>> !(alnum | '_') // make sure we have whole words
]
> !var_ref // make sure the variable isn't redeclared
> identifier [add_var(_1, ref(nvars))]
> (';' | '=' > assignment_rhs(ref(nvars)-1))
;
assignment =
var_ref [_a = _1]
>> '='
> assignment_rhs(_a)
;
assignment_rhs =
expr
> lit(';') [op(op_store, _r1)]
;
if_statement =
lit("if")
>> '('
> expr [
op(op_jump_if, 0), // we shall fill this (0) in later
_a = size(ref(code))-1 // mark its position
]
> ')'
> statement_ [
// now we know where to jump to (after the if branch)
ref(code)[_a] = size(ref(code))
]
>>
-(
lexeme[
"else"
>> !(alnum | '_') // make sure we have whole words
]
[
ref(code)[_a] += 2, // adjust for the "else" jump
op(op_jump, 0), // we shall fill this (0) in later
_a = size(ref(code))-1 // mark its position
]
> statement_ [
// now we know where to jump to (after the else branch)
ref(code)[_a] = size(ref(code))
]
)
;
while_statement =
lit("while") [
_a = size(ref(code)) // mark our position
]
>> '('
> expr [
op(op_jump_if, 0), // we shall fill this (0) in later
_b = size(ref(code))-1 // mark its position
]
> ')'
> statement_ [
op(op_jump, _a), // loop back
// now we know where to jump to (to exit the loop)
ref(code)[_b] = size(ref(code))
]
;
compound_statement =
'{' >> -statement_list >> '}'
;
statement_ =
var_decl
| assignment
| compound_statement
| if_statement
| while_statement
;
statement_list = +statement_;
identifier.name("identifier");
var_ref.name("variable-reference");
var_decl.name("variable-declaration");
assignment.name("assignment");
assignment_rhs.name("assignment-rhs");
if_statement.name("if-statement");
while_statement.name("while-statement");
compound_statement.name("compound-statement");
statement_.name("statement");
statement_list.name("statement-list");
on_error<fail>(statement_list, error_handler(_4, _3, _2));
}
#endif