@specs-feup/clava
Version:
A C/C++ source-to-source compiler written in Typescript
140 lines • 5.42 kB
JavaScript
import Io from "@specs-feup/lara/api/lara/Io.js";
import Check from "@specs-feup/lara/api/lara/Check.js";
import System from "@specs-feup/lara/api/lara/System.js";
import Strings from "@specs-feup/lara/api/lara/Strings.js";
import Clava from "../Clava.js";
import ClavaJoinPoints from "../ClavaJoinPoints.js";
import { debug } from "@specs-feup/lara/api/lara/core/LaraCore.js";
import { FileJp } from "../../Joinpoints.js";
/**
* Parses C/C++ files.
*/
export default class BatchParser {
basePath;
/**
* The source files found on the given path
*/
sourceFiles;
/**
* Maps header file names to the corresponding File objects
*/
headerFilesMap = new Map();
static _IMPLEMENTATION_PATTERNS = ["*.c", "*.cpp"];
static _HEADER_PATTERNS = ["*.h", "*.hpp"];
constructor(srcPath) {
this.basePath = srcPath;
this.sourceFiles = Io.getFiles(srcPath, BatchParser._IMPLEMENTATION_PATTERNS, true);
const headerFiles = Io.getFiles(srcPath, BatchParser._HEADER_PATTERNS, true);
for (const headerFile of headerFiles) {
this.headerFilesMap.set(headerFile.getName(), headerFile);
}
}
getSourceFiles() {
return this.sourceFiles;
}
parse(sourceFile) {
debug("Parsing " + sourceFile.toString() + "...");
const parsingStart = System.nanos();
const $literalFile = Clava.getProgram().addFileFromPath(sourceFile);
// Rebuild tree
const $parsedFile = this.rebuildFile($literalFile);
const parsingTime = System.toc(parsingStart);
debug("Parsing took " + parsingTime);
return $parsedFile;
}
/**
* Tries to rebuild the current tree, using several methods to fix any problem it finds
*/
rebuildFile($literalFile) {
let parsing = true;
while (parsing) {
const $parsedFile = $literalFile.rebuildTry();
// Check if it is a file
if ($parsedFile instanceof FileJp) {
return $parsedFile;
}
// It is an exception
parsing = this.solveRebuildFile($parsedFile, $literalFile);
}
return undefined;
}
solveRebuildFile($exception, $literalFile) {
// Get error message
const message = $exception.message;
// Check if correct type
if ($exception.exceptionType !== "ClavaParserException") {
throw $exception.exception;
}
const lines = Strings.asLines(message);
// Check first line
if (lines === undefined || lines.length === 0) {
throw new Error("Could not parse error message: " + message);
}
Check.strings(lines[0], "There are errors in the source code:");
// Parse first error
return this.parseError(lines.subList(1, lines.length), $literalFile);
}
parseError(lines, $literalFile) {
const errorLine = lines[0];
const filename = $literalFile.name;
// Find name of file in line
const nameIndex = errorLine.indexOf(filename);
if (nameIndex === -1) {
throw "Could not find filename '" + filename + "' in " + errorLine;
}
// Remove filename
let parsedLine = errorLine
.substring(nameIndex + filename.length, errorLine.length)
.trim();
// Remove location
const locationSep = parsedLine.indexOf(" ");
if (locationSep !== -1) {
parsedLine = parsedLine
.substring(locationSep + 1, parsedLine.length)
.trim();
}
// Check if fatal error
if (parsedLine.startsWith("fatal error:")) {
const fatalError = "fatal error:";
parsedLine = parsedLine
.substring(fatalError.length, parsedLine.length)
.trim();
return this.parseFatalError(parsedLine);
}
console.log("Line 0: " + lines[0]);
console.log("Parsed line: " + parsedLine);
return false;
}
parseFatalError(error) {
if (error.endsWith("' file not found")) {
const fileNotFound = "' file not found";
const endIndex = error.length - fileNotFound.length;
let parsedError = error.substring(0, endIndex).trim();
if (!parsedError.startsWith("'")) {
throw "Expected file not found string to start with ':" + parsedError;
}
parsedError = parsedError.substring(1, parsedError.length).trim();
// Normalize
parsedError.replace("\\\\", "/");
let filename = parsedError;
let path = undefined;
// Extract path
const slashIndex = parsedError.lastIndexOf("/");
if (slashIndex !== -1) {
filename = parsedError.substring(slashIndex + 1);
path = parsedError.substring(0, slashIndex);
}
console.log("File: " + filename);
console.log("Path: " + path);
let pathname = filename;
if (path !== undefined) {
pathname = path + "/" + filename;
}
debug("Adding file " + pathname);
const newFile = ClavaJoinPoints.file(filename, path);
Clava.getProgram().addFile(newFile);
return true;
}
}
}
//# sourceMappingURL=BatchParser.js.map