summaryrefslogtreecommitdiff
path: root/lib/Basic/Token.cpp
blob: 104be84f0ad78639fc7a5b5c9a88e3dd7a4d93a0 (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
//===--- Token.cpp - Token implementation ---------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Token interface.
//
//===----------------------------------------------------------------------===//

#include "flang/Basic/Token.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "flang/Basic/LLVM.h"

namespace flang {

static inline bool isHorizontalWhitespace(char C) {
  return C == ' ' || C == '\t' || C == '\f' || C == '\v';
}

/// CleanLiteral - Return the literal cleaned up of any line continuations.
std::string Token::CleanLiteral(SmallVectorImpl<StringRef> &Spelling) const {
  if (!needsCleaning())
    return Spelling[0].str();

  std::string Name;
  Name.reserve(256);
  for (llvm::SmallVectorImpl<StringRef>::const_iterator
         I = Spelling.begin(), E = Spelling.end(); I != E; ++I)
    Name += *I;

  return Name;
}

/// CleanCharContext - Clean up a character context which is "dirty" (has
/// continuations in it).
llvm::Twine Token::CleanCharContext() {
  assert(is(tok::char_literal_constant) && needsCleaning() &&
         "Trying to clean a pristene character context!");
  llvm::Twine CharContext;
  const char *CurPtr = getLiteralData();
  const char *Start = Start;

  while (true) {
    while (*CurPtr != '&') {
      if (*CurPtr != '\'')
        ++CurPtr;
      else if (CurPtr[1] == '\'')
        CurPtr += 2;
      else
        break;
    }

    if (*CurPtr == '\'') break;

    const char *Amp = CurPtr++;
    while (isHorizontalWhitespace(*CurPtr))
      ++CurPtr;

    if (*CurPtr != '\n' && *CurPtr != '\r')
      continue;

    CharContext.concat(
      llvm::Twine(llvm::StringRef(Start, Amp - Start)));

    while (true) {
      while (isHorizontalWhitespace(*CurPtr) ||
             *CurPtr == '\n' || *CurPtr == '\r')
        ++CurPtr;

      if (*CurPtr == '!') {
        while (*CurPtr != '\n' && *CurPtr != '\r')
          ++CurPtr;
      } else {
        break;
      }
    }

    Start = ++CurPtr;
  }

  return CharContext +
    llvm::Twine(llvm::StringRef(CurPtr, Start - CurPtr));
}

} //namespace flang