summaryrefslogtreecommitdiff
path: root/src/macros.hpp
blob: ff6f0dbdd375fc1a941ddbd509897aeaeea62819 (plain)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#ifndef MACROS_HPP_INCLUDED
#define MACROS_HPP_INCLUDED

#include "parse/lex.hpp"
#include "parse/tokentree.hpp"
#include <map>
#include <memory>
#include <cstring>

class MacroExpander;

namespace AST {
    class Module;
}

class MacroRuleEnt:
    public Serialisable
{
    friend class MacroExpander;

    Token   tok;
    ::std::string   name;
    ::std::vector<MacroRuleEnt> subpats;
public:
    MacroRuleEnt():
        tok(TOK_NULL),
        name("")
    {
    }
    MacroRuleEnt(Token tok):
        tok(tok),
        name("")
    {
    }
    MacroRuleEnt(::std::string name):
        name(name)
    {
    }
    MacroRuleEnt(Token tok, ::std::vector<MacroRuleEnt> subpats):
        tok(tok),
        subpats(subpats)
    {
    }

    friend ::std::ostream& operator<<(::std::ostream& os, const MacroRuleEnt& x) {
        os << "MacroRuleEnt(";
        if(x.name.size())
            os << "'"<<x.name<<"'";
        else if( x.subpats.size() )
            os << x.tok << " [" << x.subpats << "]";
        else
            os << x.tok;
        os << ")";
        return os;
    }

    SERIALISABLE_PROTOTYPES();
};
struct MacroPatEnt:
    public Serialisable
{
    ::std::string   name;
    Token   tok;
    
    ::std::vector<MacroPatEnt>  subpats;
    
    enum Type {
        PAT_TOKEN,
        PAT_TT,
        PAT_PAT,
        PAT_IDENT,
        PAT_PATH,
        PAT_TYPE,
        PAT_EXPR,
        PAT_STMT,
        PAT_BLOCK,
        PAT_META,
        PAT_LOOP,   // Enables use of subpats
    } type;

    MacroPatEnt():
        tok(TOK_NULL),
        type(PAT_TOKEN)
    {
    }
    MacroPatEnt(Token tok):
        tok(tok),
        type(PAT_TOKEN)
    {
    }
    
    MacroPatEnt(::std::string name, Type type):
        name(name),
        tok(),
        type(type)
    {
    }
    
    MacroPatEnt(Token sep, bool need_once, ::std::vector<MacroPatEnt> ents):
        name( need_once ? "+" : "*" ),
        tok(sep),
        subpats( move(ents) ),
        type(PAT_LOOP)
    {
    }

    friend ::std::ostream& operator<<(::std::ostream& os, const MacroPatEnt& x) {
        os << "MacroPatEnt(";
        switch(x.type)
        {
        case PAT_TOKEN: os << "token "; break;
        case PAT_TT:    os << "tt ";    break;
        case PAT_PAT:   os << "pat ";   break;
        case PAT_IDENT: os << "ident "; break;
        case PAT_PATH:  os << "path ";  break;
        case PAT_TYPE:  os << "type ";  break;
        case PAT_EXPR:  os << "expr ";  break;
        case PAT_STMT:  os << "stmt ";  break;
        case PAT_BLOCK: os << "block "; break;
        case PAT_META:  os << "meta "; break;
        case PAT_LOOP:  os << "loop ";  break;
        }
        if(x.name.size())
            os << "'"<<x.name<<"'";
        else if( x.subpats.size() )
            os << x.tok << " [" << x.subpats << "]";
        else
            os << x.tok;
        os << ")";
        return os;
    }
    
    SERIALISABLE_PROTOTYPES();
};

/// A rule within a macro_rules! blcok
class MacroRule:
    public Serialisable
{
public:
    ::std::vector<MacroPatEnt>  m_pattern;
    ::std::vector<MacroRuleEnt> m_contents;
    
    SERIALISABLE_PROTOTYPES();
};

/// A sigle 'macro_rules!' block
typedef ::std::vector<MacroRule>    MacroRules;

extern ::std::unique_ptr<TokenStream>   Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input);
extern ::std::unique_ptr<TokenStream>   Macro_Invoke(const TokenStream& lex, const ::std::string& name, TokenTree input);

#endif // MACROS_HPP_INCLUDED