File: line_parser.cc

package info (click to toggle)
arachne-pnr 0.1%2B20190728gitc40fb22-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,080 kB
  • sloc: cpp: 10,681; python: 230; sh: 167; makefile: 164
file content (126 lines) | stat: -rw-r--r-- 2,687 bytes parent folder | download | duplicates (3)
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
/* Copyright (C) 2015 Cotton Seed
   
   This file is part of arachne-pnr.  Arachne-pnr is free software;
   you can redistribute it and/or modify it under the terms of the GNU
   General Public License version 2 as published by the Free Software
   Foundation.
   
   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program. If not, see <http://www.gnu.org/licenses/>. */

#include "line_parser.hh"
#include "util.hh"

std::ostream &
operator<<(std::ostream &s, const LexicalPosition &lp)
{
  if (lp.internal)
    s << "<internal>";
  else
    s << lp.file << ":" << lp.line;
  return s;
}

void
LexicalPosition::fatal(const std::string &msg) const
{
  std::cerr << *this << ": fatal error: " << msg << "\n";
  exit(EXIT_FAILURE);
}

void
LexicalPosition::warning(const std::string &msg) const
{
  std::cerr << *this << ": warning: " << msg << "\n";
}

void
LineParser::split_line()
{
  words.clear();
  
  std::string t;
  bool instr = false,
    quote = false;
  
  for (char ch : line)
    {
      if (instr)
        {
          t.push_back(ch);
          if (quote)
            quote = false;
          else if (ch == '\\')
            quote = true;
          else if (ch == '"')
            {
              words.push_back(unescape(t));
              t.clear();
              instr = false;
            }
        }
      else if (isspace(ch))
        {
          if (!t.empty())
            {
              words.push_back(t);
              t.clear();
            }
        }
      else
        {
          t.push_back(ch);
          if (ch == '"')
            instr = true;
        }
    }
  if (instr)
    fatal("unterminated string constant");
  else if (!t.empty())
    {
      words.push_back(t);
      t.clear();
    }
}

void
LineParser::read_line()
{
  words.clear();
  do {
    line.clear();
    if (s.eof())
      return;
    
    lp.next_line();
    std::getline(s, line);
    
  L:
    std::size_t p = line.find('#');
    if (p != std::string::npos)
      line.resize(p);
    else if (!line.empty()
             && line.back() == '\\')
      {
        if (s.eof())
          fatal("unexpected backslash before eof");
        
        // drop backslash
        line.pop_back();
        
        std::string line2;
        lp.next_line();
        std::getline(s, line2);
        
        line.append(line2);
        goto L;
      }
    
    split_line();
  } while (words.empty());
}