-
Notifications
You must be signed in to change notification settings - Fork 3
/
ParserGcc.ts
142 lines (126 loc) · 4.28 KB
/
ParserGcc.ts
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
/* CoCoPa - Compiler Command Parser, a Parser to extract include directories,
* defines, arguments and more from compiler command line invocations.
*
* Copyright (C) 2020 Uli Franke - Elektronik Workshop
*
* Distributed under the MIT license. See LICENSE file for details.
*
* All rights reserved.
*/
import * as shlex from "shlex";
import {Result, ResultCppStandard} from "./Result";
import {Parser} from "./Parser";
import {BuiltInInfoParserGcc} from "./BuiltInInfoParserGcc";
import {IParserTrigger} from "./helpers";
/**
* Compiler command parsing engine for gcc compilers.
*/
export class ParserGcc extends Parser {
constructor(trigger: IParserTrigger) {
super(trigger, new BuiltInInfoParserGcc());
}
protected parse(line: string): Result {
const result = new Result();
for (let arg of shlex.split(line)) {
// drop empty arguments
if (!arg.length) {
continue;
}
// We currently don't handle this.
// -U__STRICT_ANSI__ ?
// Unpack quoted arguments like the following
//
// "-DMBEDTLS_CONFIG_FILE=\"mbedtls/esp_config.h\""
// "-DARDUINO_BOARD=\"ESP32_DEV\""
// "-DARDUINO_VARIANT=\"doitESP32devkitV1\""
//
const packed = arg.match(/^"(.+)"$/);
if (packed) {
arg = packed[1];
// revert escaped quotes inside the quoted arguments
arg = arg.replace(/\\"/g, '"');
}
// extract defines
const define = arg.match(/^-D(.+)/);
if (define) {
result.defines.push(define[1]);
continue;
}
// extract includes
const include = arg.match(/^-I(.+)/);
if (include) {
result.includes.push(include[1]);
continue;
}
// extract the compiler executable
const c = arg.match(/(?:^|-)g\+\+$/);
if (c) {
result.compiler = arg;
continue;
}
// filter out option trash
const t = arg.match(/^-o|^-O|^-g|^-c|cpp(?:\.o){0,1}$/);
if (t) {
result.trash.push(arg);
continue;
}
// collect options
const o = arg.match(/^-/);
if (o) {
result.options.push(arg);
continue;
}
// collect the rest
result.trash.push(arg);
}
ParserGcc.parseCppStd(result);
return result;
}
/**
* Regular expression to parse gcc options to find the C++ standard.
* @see https://gcc.gnu.org/projects/cxx-status.html
*/
static readonly CppStandardOptionRegex = /^-std=(?:c\+\+|gnu\+\+)([0-9]+)$/;
/**
* Tries to extract the C++ standard from gcc compiler options.
* @param result The compiler options of this result will be
* searched for a valid C++ standard flag. The C++ standard
* of this object will be set accordingly.
*/
public static parseCppStd(result: Result) {
// Initialize C++ standard from parsed options
const lut = new Map<string, ResultCppStandard>([
["98", ResultCppStandard.Cpp98],
["11", ResultCppStandard.Cpp11],
["14", ResultCppStandard.Cpp14],
["17", ResultCppStandard.Cpp17],
["20", ResultCppStandard.Cpp20],
]);
for (const o of result.options) {
const m = o.match(ParserGcc.CppStandardOptionRegex);
if (!m) {
continue;
}
const std = lut.get(m[1]);
if (std) {
result.cppStandard = std;
return;
}
}
}
}
/*
* Here's a custom argument splitter but it's susceptible to more complex
* escapes. It seems to work for Arduino compile commands on windows
* and UNIX systems. I left it here fore reference.
*
* const split = (str: string) => {
* let ret: string[] = [];
* const splitregex = /"(?:\\"|[^"])+"|\S+/g;
* let match;
* while ((match = splitregex.exec(str)) !== null) {
* ret.push(match[0]);
* }
* return ret;
* }
*/