aboutsummaryrefslogtreecommitdiff
path: root/build/parser
blob: 94bf7f3189533dd53ba6d31dc3b370d620e82832 (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
// file      : build/parser -*- C++ -*-
// copyright : Copyright (c) 2014-2015 Code Synthesis Tools CC
// license   : MIT; see accompanying LICENSE file

#ifndef BUILD_PARSER
#define BUILD_PARSER

#include <string>
#include <iosfwd>
#include <utility> // move()

#include <build/path>
#include <build/token>
#include <build/name>
#include <build/spec>
#include <build/variable>    // list_value
#include <build/diagnostics>

namespace build
{
  class scope;
  class target;
  class lexer;

  class parser
  {
  public:
    parser (): fail (&path_) {}

    // Issue diagnostics and throw failed in case of an error.
    //
    void
    parse_buildfile (std::istream&, const path&, scope& root, scope& base);

    buildspec
    parse_buildspec (std::istream&, const std::string& name);

    token
    parse_variable (lexer&, scope&, std::string name, token_type kind);

    list_value
    export_value ()
    {
      list_value r (std::move (export_value_));
      export_value_.clear (); // Empty state.
      return r;
    }

    // Recursive descent parser.
    //
  private:
    typedef build::names names_type;

    void
    clause (token&, token_type&);

    void
    print (token&, token_type&);

    void
    source (token&, token_type&);

    void
    include (token&, token_type&);

    void
    import (token&, token_type&);

    void
    export_ (token&, token_type&);

    void
    using_ (token&, token_type&);

    void
    variable (token&, token_type&, std::string name, token_type kind);

    names_type
    names (token& t, token_type& tt)
    {
      names_type ns;
      names (t, tt, ns, 0, nullptr, nullptr);
      return ns;
    }

    void
    names (token&, token_type&,
           names_type&, std::size_t pair,
           const dir_path* dir, const std::string* type);

    // Buildspec.
    //
    buildspec
    buildspec_clause (token&, token_type&, token_type end);

    // Utilities.
    //
  private:
    // Switch to new root scope and return the previous one.
    //
    scope*
    switch_root (scope*);

    void
    process_default_target (token&);

    // Lexer.
    //
  private:
    token_type
    next (token&, token_type&);

    token_type
    peek ();

    const token&
    peeked () const
    {
      assert (peeked_);
      return peek_;
    }

    // Diagnostics.
    //
  private:
    const fail_mark<failed> fail;

  private:
    const std::string* path_; // Path processed by diag_relative().
    lexer* lexer_;
    scope* scope_; // Current base scope (out_base).
    scope* root_;  // Current root scope (out_root).
    const dir_path* out_root_;
    const dir_path* src_root_;
    target* default_target_;
    list_value export_value_;

    token peek_ {token_type::eos, false, 0, 0};
    bool peeked_ {false};
  };
}

#endif // BUILD_PARSER