blob: b7b0c17a16db79821dfe71914723f38d5269e631 (
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
|
#include "cyclomatic.h"
#include "html_utils.h"
#include "lexcer.h"
#include "lexconst.h"
#include <stack>
using HTMLUtils::writeToOutput;
using LexCer::TokenClass;
using LexCer::Tokenizer;
// Writing a full parser would give us the change of
// making the cyclomatic graph of the function.
// #courseproject
unsigned ParCer::outputWithCyclomaticComplexity(FILE *in, FILE *out) {
Tokenizer tokenizer (in, out);
std::string lexeme;
double number;
TokenClass type;
Token currentToken;
std::stack<short> history;
bool inFunction = false;
#define PAREN false
std::stack<bool> openedBlocks;
std::string className = "a";
unsigned counter = 1;
unsigned complexity = 1;
do {
currentToken = tokenizer.nextToken(&lexeme, &number);
type = currentToken.type;
if (!inFunction) {
history.push(type);
} else {
if (type == TokenClass::RightCurly) {
if (openedBlocks.empty()) { // end of a function. What one does to avoid parsing 'C'
inFunction = false;
fputs("<!-- ", out);
char closingDiv[100];
sprintf(closingDiv, "%d --></div>", complexity);
fputs(closingDiv, out);
complexity = 1;
} else {
openedBlocks.pop();
}
}
else if (type == TokenClass::LeftCurly) {
openedBlocks.push(PAREN);
}
else if (type == TokenClass::Keyword) {
if (!lexeme.compare("if") ||
!lexeme.compare("while") ||
!lexeme.compare("for") ||
!lexeme.compare("case") ||
!lexeme.compare("default"))
{
++complexity;
}
}
}
if (!inFunction && type == TokenClass::LeftCurly) {
history.pop();
while (!history.empty() && history.top() == TokenClass::Skip) {
history.pop();
}
if (history.top() == TokenClass::RightParen) {
while (!history.empty() && history.top() != TokenClass::LeftParen)
history.pop();
if (!history.empty())
history.pop();
while (!history.empty() && history.top() == TokenClass::Skip)
history.pop();
if (!history.empty() && history.top() == TokenClass::Identifier) { // We are in a function
char openingDiv[100];
sprintf(openingDiv, "<div class=\"func\">", className.c_str());
fputs(openingDiv, out);
inFunction = true;
history = std::stack<short>{};
}
}
}
if (!writeToOutput(out, currentToken))
break;
lexeme = "";
number = 0.0;
} while (type != TokenClass::Eof ||
type != TokenClass::Invalid);
return counter - 1;
}
|