about summary refs log tree commit diff
path: root/third_party/nix/src/libexpr/parser.hh
blob: 7b8f955731768893172d51dbb8d5d3f42c7f4a2a (plain) (blame)
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
// Parser utilities for use in parser.y
#pragma once

// TODO(tazjin): Audit these includes, they were in parser.y
#include <optional>
#include <variant>

#include <glog/logging.h>

#include "libexpr/eval.hh"
#include "libexpr/nixexpr.hh"
#include "libutil/util.hh"

#define YY_DECL                                                               \
  int yylex(YYSTYPE* yylval_param, YYLTYPE* yylloc_param, yyscan_t yyscanner, \
            nix::ParseData* data)

#define CUR_POS makeCurPos(*yylocp, data)

namespace nix {

struct ParseData : public gc {
  EvalState& state;
  SymbolTable& symbols;
  Expr* result;
  Path basePath;
  std::optional<Symbol> path;
  std::string error;
  Symbol sLetBody;

  ParseData(EvalState& state)
      : state(state),
        symbols(state.symbols),
        sLetBody(symbols.Create("<let-body>")){};
};

// Clang fails to identify these functions as used, probably because
// of some interaction between the lexer/parser codegen and something
// else.
//
// To avoid warnings for that we disable -Wunused-function in this block.

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"

// TODO(tazjin): move dupAttr to anonymous namespace
static void dupAttr(const AttrPath& attrPath, const Pos& pos,
                    const Pos& prevPos) {
  throw ParseError(format("attribute '%1%' at %2% already defined at %3%") %
                   showAttrPath(attrPath) % pos % prevPos);
}

static void dupAttr(Symbol attr, const Pos& pos, const Pos& prevPos) {
  throw ParseError(format("attribute '%1%' at %2% already defined at %3%") %
                   attr % pos % prevPos);
}

void addAttr(ExprAttrs* attrs, AttrPath& attrPath, Expr* e, const Pos& pos);

void addFormal(const Pos& pos, Formals* formals, const Formal& formal);

Expr* stripIndentation(const Pos& pos, SymbolTable& symbols,
                       std::vector<Expr*>& es);

Path resolveExprPath(Path path);

// implementations originally from lexer.l

static Expr* unescapeStr(SymbolTable& symbols, const char* s, size_t length) {
  std::string t;
  t.reserve(length);
  char c;
  while ((c = *s++)) {
    if (c == '\\') {
      assert(*s);
      c = *s++;
      if (c == 'n') {
        t += '\n';
      } else if (c == 'r') {
        t += '\r';
      } else if (c == 't') {
        t += '\t';
      } else
        t += c;
    } else if (c == '\r') {
      /* Normalise CR and CR/LF into LF. */
      t += '\n';
      if (*s == '\n') {
        s++;
      } /* cr/lf */
    } else
      t += c;
  }
  return new ExprString(symbols.Create(t));
}

#pragma clang diagnostic pop  // re-enable -Wunused-function

}  // namespace nix