-
Notifications
You must be signed in to change notification settings - Fork 3
/
program-grammar.hpp
87 lines (73 loc) · 3.26 KB
/
program-grammar.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
/*=============================================================================
Copyright (c) 2001-2009 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(PROGRAM_GRAMMAR_HPP)
#define PROGRAM_GRAMMAR_HPP
#include "program.hpp"
#include "error_handler.hpp"
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
///////////////////////////////////////////////////////////////////////////////
// Our program grammar and compiler
///////////////////////////////////////////////////////////////////////////////
template <typename Iterator>
program<Iterator>::program(std::vector<int>& code)
: program::base_type(start)
, code(code)
, statement_(code, functions)
, add_function(function_adder(functions))
, state_reset(function_state_reset(code, statement_.vars, statement_.nvars))
, op(code)
{
using namespace boost::spirit::qi;
//using namespace boost::spirit;
//using namespace boost::phoenix;
//using boost::phoenix::function;
using boost::phoenix::ref;
using boost::phoenix::size;
bool& has_return = statement_.has_return;
int& nvars = statement_.nvars;
boost::phoenix::function<var_adder>& add_var = statement_.add_var;
identifier %=
raw[lexeme[alpha >> *(alnum | '_')]]
;
using boost::phoenix::ref;
function_definition =
(
lit("void") [ref(has_return) = false]
| lit("int") [ref(has_return) = true]
)
>> !functions // no duplicate functions!
>> identifier [_a = _1]
>> '('
> -(
identifier [add_var(_1)]
>> *(',' > identifier [add_var(_1)])
)
> ')'
> lit('{') [ // actually this one requires the phoenix
// statement include which overrides
// the comma operator :-/
_b = size(boost::phoenix::ref(code)),
add_function(
_a // function name
, ref(nvars) // arity
, size(boost::phoenix::ref(code)) // address
),
op(op_stk_adj, 0) // adjust this later
]
> statement_
> lit('}') [state_reset(_b)]
;
start =
+function_definition
;
identifier.name("identifier");
function_definition.name("function_definition");
start.name("program");
on_error<fail>(start, ::error_handler(_4, _3, _2));
}
#endif // PROGRAM_GRAMMAR_HPP