libdparser integration

This commit is contained in:
Vadim Lopatin 2015-02-18 12:15:41 +03:00
parent 353a8fc8a2
commit e8cd7b882c
2 changed files with 125 additions and 0 deletions

View File

@ -214,6 +214,7 @@
<File path="src\dlangide\tools\d\dcdinterface.d" />
<File path="src\dlangide\tools\d\dcdserver.d" />
<File path="src\dlangide\tools\d\deditortool.d" />
<File path="src\dlangide\tools\d\dparser.d" />
<File path="src\dlangide\tools\d\dsyntaxhighlighter.d" />
</Folder>
<File path="src\dlangide\tools\editortool.d" />

View File

@ -0,0 +1,124 @@
module dlangide.tools.d.dparser;
import std.d.lexer;
import std.d.parser;
import std.d.ast;
import std.algorithm;
import std.string;
import std.path;
import std.file;
import std.conv;
class DParsedModule {
protected string _moduleName;
protected string _moduleFile;
protected StringCache* _cache;
protected Module _ast;
const(Token)[] _tokens;
LexerConfig _lexerConfig;
@property string filename() {
return _moduleFile;
}
this(StringCache* cache, string filename) {
_cache = cache;
_moduleFile = filename;
}
void parse(ubyte[] sourceCode) {
_tokens = getTokensForParser(sourceCode, _lexerConfig, _cache);
_ast = parseModule(_tokens, _moduleFile);
}
}
/// D source code parsing service
class DParsingService {
protected static __gshared DParsingService _instance;
/// singleton
static @property DParsingService instance() {
if (!_instance) {
_instance = new DParsingService();
}
return _instance;
}
/// destroy singleton
static void shutdown() {
destroy(_instance);
_instance = null;
}
protected StringCache _cache;
protected string[] _importPaths;
protected DParsedModule[] _modules;
protected DParsedModule[string] _moduleByName;
protected DParsedModule[string] _moduleByFile;
protected bool[string] _notFoundModules;
this() {
_cache = StringCache(16);
}
DParsedModule scan(ubyte[] sourceCode, string filename) {
destroy(_notFoundModules);
DParsedModule res = new DParsedModule(&_cache, filename);
res.parse(sourceCode);
return res;
}
/// converts some.module.name to some/module/name.d
string moduleNameToPackagePath(string moduleName) {
string[] pathSegments = moduleName.split(".");
string normalized = buildNormalizedPath(pathSegments);
return normalized ~ ".d";
}
string findModuleFile(string moduleName) {
string packagePath = moduleNameToPackagePath(moduleName);
foreach(ip; _importPaths) {
string path = buildNormalizedPath(ip, packagePath);
if (path.exists && path.isFile)
return path;
}
return null;
}
DParsedModule getOrParseModule(string moduleName) {
if (auto m = moduleName in _moduleByName) {
return *m;
}
if (moduleName in _notFoundModules)
return null; // already listed as not found
string filename = findModuleFile(moduleName);
if (!filename) {
_notFoundModules[moduleName] = true;
return null;
}
try {
DParsedModule res = new DParsedModule(&_cache, filename);
ubyte[] sourceCode = cast(ubyte[])read(filename);
res.parse(sourceCode);
_moduleByName[moduleName] = res;
_moduleByFile[filename] = res;
return res;
} catch (Exception e) {
_notFoundModules[moduleName] = true;
return null;
}
}
void addImportPaths(string[] paths) {
foreach(p; paths) {
string ap = absolutePath(buildNormalizedPath(p));
bool found = false;
foreach(ip; _importPaths)
if (ip.equal(ap)) {
found = true;
break;
}
if (!found)
_importPaths ~= ap;
}
}
}