farsamiscutilities.cpp
1 /********************************************************************************
2  * FARSA Utilities Library *
3  * Copyright (C) 2007-2012 *
4  * Gianluca Massera <emmegian@yahoo.it> *
5  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
6  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
21  ********************************************************************************/
22 
23 #include "farsamiscutilities.h"
24 
25 namespace farsa {
26 
27 QString removeComments(const QString& program, CommentsPositions* commentsPos, StringsPositions* stringsPos)
28 {
29  // We create the list of comments and strings in any case, even if we don't have to return them
30  CommentsPositions cpos;
31  StringsPositions spos;
32 
33  // To remove comments we read one character at a time and check if it is a comment or not
34  QString cleaned;
35  // The possible states
36  enum RemoveCommentsState {
37  FirstSlash,
38  StartEndCComment,
39  InCComment,
40  InCppComment,
41  InString,
42  InCharacter,
43  NormalCode
44  } state = NormalCode;
45  CommentPosition curComment;
46  StringPosition curString;
47  for (int i = 0; i < program.size(); i++) {
48  switch (state) {
49  case FirstSlash:
50  if (program[i] == '/') {
51  state = InCppComment;
52  curComment.type = CommentPosition::CppComment;
53  } else if (program[i] == '*') {
54  state = InCComment;
55  curComment.type = CommentPosition::CComment;
56  } else {
57  cleaned += '/';
58  cleaned += program[i];
59  state = NormalCode;
60 
61  // Checking for strings. We don't change or remove them but we have to report them
62  if ((program[i] == '\"') && ((i == 0) || (program[i - 1] != '\\'))) {
63  state = InString;
64  curString.originalStart = i;
65  curString.parsedStart = cleaned.size() - 1;
66  curString.type = StringPosition::String;
67  } else if ((program[i] == '\'') && ((i == 0) || (program[i - 1] != '\\'))) {
68  state = InCharacter;
69  curString.originalStart = i;
70  curString.parsedStart = cleaned.size() - 1;
71  curString.type = StringPosition::Character;
72  }
73  }
74  break;
75  case StartEndCComment:
76  state = InCComment;
77  if (program[i] == '/') {
78  state = NormalCode;
79  // Adding a whitespace for the cases of comments between two elements which should be separated
80  cleaned += ' ';
81  curComment.originalEnd = i;
82  curComment.parsedPosition = cleaned.size() - 1;
83  cpos.append(curComment);
84  } else if (program[i] == '*') {
85  state = StartEndCComment;
86  }
87  break;
88  case InCComment:
89  if (program[i] == '*') {
90  state = StartEndCComment;
91  }
92  break;
93  case InCppComment:
94  if ((program[i] == '\n') || (program[i] == '\r')) {
95  cleaned += program[i];
96  state = NormalCode;
97  curComment.originalEnd = i - 1;
98  curComment.parsedPosition = cleaned.size() - 1;
99  cpos.append(curComment);
100  }
101  break;
102  case InString:
103  cleaned += program[i];
104 
105  if ((program[i] == '"') && ((i == 0) || (program[i - 1] != '\\'))) {
106  state = NormalCode;
107  curString.originalEnd = i;
108  curString.parsedEnd = cleaned.size() - 1;
109  spos.append(curString);
110  }
111  break;
112  case InCharacter:
113  cleaned += program[i];
114 
115  // Here we don't check that there is only one character enclosed in '',
116  // the code won't compile anyway if there is more than one character
117  if ((program[i] == '\'') && ((i == 0) || (program[i - 1] != '\\'))) {
118  state = NormalCode;
119  curString.originalEnd = i;
120  curString.parsedEnd = cleaned.size() - 1;
121  spos.append(curString);
122  }
123  break;
124  case NormalCode:
125  if (program[i] == '/') {
126  state = FirstSlash;
127  curComment.originalStart = i;
128  } else {
129  cleaned += program[i];
130 
131  // Checking for strings. We don't change or remove them but we have to report them
132  if ((program[i] == '\"') && ((i == 0) || (program[i - 1] != '\\'))) {
133  state = InString;
134  curString.originalStart = i;
135  curString.parsedStart = cleaned.size() - 1;
136  curString.type = StringPosition::String;
137  } else if ((program[i] == '\'') && ((i == 0) || (program[i - 1] != '\\'))) {
138  state = InCharacter;
139  curString.originalStart = i;
140  curString.parsedStart = cleaned.size() - 1;
141  curString.type = StringPosition::Character;
142  }
143  }
144  break;
145  }
146  }
147 
148  // Whe have to check if we are still in a comment or string/character to add it
149  switch (state) {
150  case StartEndCComment:
151  case InCComment:
152  case InCppComment:
153  cleaned += ' ';
154  curComment.originalEnd = program.size() - 1;
155  curComment.parsedPosition = cleaned.size() - 1;
156  cpos.append(curComment);
157  break;
158  case InString:
159  case InCharacter:
160  curString.originalEnd = program.size() - 1;
161  curString.parsedEnd = cleaned.size() - 1;
162  spos.append(curString);
163  break;
164  default:
165  break;
166  }
167 
168  if (commentsPos != NULL) {
169  *commentsPos = cpos;
170  }
171  if (stringsPos != NULL) {
172  *stringsPos = spos;
173  }
174 
175  return cleaned;
176 }
177 
178 } // end namespace farsa
a file with miscellaneous functions
QList< StringPosition > StringsPositions
A list of positions of strings.
QList< CommentPosition > CommentsPositions
A list of positions of comments.
unsigned int originalEnd
The ending position of the comment in the original program (i.e. the position of the closing " or ') ...
A macro to deprecate functions.
unsigned int parsedStart
The starting position of the comment in the parsed program (i.e. the position of the opening " or ') ...
QString removeComments(const QString &program, CommentsPositions *commentsPos, StringsPositions *stringsPos)
A simple function to remove all C and C++ comments from a program.
unsigned int originalStart
The starting position of the comment in the original program (i.e. the position of the opening " or '...
unsigned int originalStart
The starting position of the comment in the original program (i.e. the position of the first characte...
unsigned int originalEnd
The ending position of the comment in the original program (i.e. the position of the last character) ...
CommentType type
The type of comment.
A structure keeping the position of C/C++ strings or characters in a program.
unsigned int parsedPosition
The position of the space with which the comment was substituted in the parsed program.
Type type
Whether this is a string or a character.
A structure keeping the position of C/C++ comments in a string.
unsigned int parsedEnd
The ending position of the comment in the parsed program (i.e. the position of the closing " or ') ...