Browse Source

Merge pull request #934 from tritao/parser_refactor

[parser] Refactor some code in the parser layer.
pull/937/head
João Matos 8 years ago committed by GitHub
parent
commit
4a21598d12
  1. 16
      src/CppParser/Parser.cpp
  2. 1
      src/Generator.Tests/ASTTestFixture.cs
  3. 53
      src/Generator/Driver.cs
  4. 46
      src/Parser/Parser.cs
  5. 131
      src/Parser/ParserOptions.cs
  6. 119
      src/Parser/Project.cs

16
src/CppParser/Parser.cpp

@ -4210,22 +4210,6 @@ ParserTargetInfo* Parser::GetTargetInfo() @@ -4210,22 +4210,6 @@ ParserTargetInfo* Parser::GetTargetInfo()
AST = &c->getASTContext();
// Initialize enough Clang codegen machinery so we can get at ABI details.
llvm::LLVMContext Ctx;
std::unique_ptr<llvm::Module> M(new llvm::Module("", Ctx));
M->setTargetTriple(AST->getTargetInfo().getTriple().getTriple());
M->setDataLayout(AST->getTargetInfo().getDataLayout());
std::unique_ptr<clang::CodeGen::CodeGenModule> CGM(
new clang::CodeGen::CodeGenModule(c->getASTContext(), c->getHeaderSearchOpts(),
c->getPreprocessorOpts(), c->getCodeGenOpts(), *M, c->getDiagnostics()));
std::unique_ptr<clang::CodeGen::CodeGenTypes> CGT(
new clang::CodeGen::CodeGenTypes(*CGM.get()));
codeGenTypes = CGT.get();
auto parserTargetInfo = new ParserTargetInfo();
auto& TI = AST->getTargetInfo();

1
src/Generator.Tests/ASTTestFixture.cs

@ -30,7 +30,6 @@ namespace CppSharp.Generator.Tests @@ -30,7 +30,6 @@ namespace CppSharp.Generator.Tests
};
Driver.Setup();
Driver.BuildParseOptions();
if (!Driver.ParseCode())
throw new Exception("Error parsing the code");

53
src/Generator/Driver.cs

@ -20,7 +20,6 @@ namespace CppSharp @@ -20,7 +20,6 @@ namespace CppSharp
{
public DriverOptions Options { get; private set; }
public ParserOptions ParserOptions { get; set; }
public Project Project { get; private set; }
public BindingContext Context { get; private set; }
public Generator Generator { get; private set; }
@ -29,7 +28,6 @@ namespace CppSharp @@ -29,7 +28,6 @@ namespace CppSharp
public Driver(DriverOptions options)
{
Options = options;
Project = new Project();
ParserOptions = new ParserOptions();
}
@ -74,9 +72,9 @@ namespace CppSharp @@ -74,9 +72,9 @@ namespace CppSharp
Generator = CreateGeneratorFromKind(Options.GeneratorKind);
}
void OnSourceFileParsed(IList<SourceFile> files, ParserResult result)
void OnSourceFileParsed(IEnumerable<string> files, ParserResult result)
{
OnFileParsed(files.Select(f => f.Path), result);
OnFileParsed(files, result);
}
void OnFileParsed(string file, ParserResult result)
@ -117,7 +115,7 @@ namespace CppSharp @@ -117,7 +115,7 @@ namespace CppSharp
}
}
public ParserOptions BuildParserOptions(SourceFile file = null)
public ParserOptions BuildParserOptions(string file = null)
{
var options = new ParserOptions
{
@ -177,7 +175,7 @@ namespace CppSharp @@ -177,7 +175,7 @@ namespace CppSharp
}
foreach (var module in Options.Modules.Where(
m => file == null || m.Headers.Contains(file.Path)))
m => file == null || m.Headers.Contains(file)))
{
foreach (var include in module.IncludeDirs)
options.AddIncludeDirs(include);
@ -197,30 +195,37 @@ namespace CppSharp @@ -197,30 +195,37 @@ namespace CppSharp
public bool ParseCode()
{
var parser = new ClangParser(new Parser.AST.ASTContext());
var astContext = new Parser.AST.ASTContext();
var parser = new ClangParser(astContext);
parser.SourcesParsed += OnSourceFileParsed;
parser.ParseProject(Project, Options.UnityBuild);
foreach (var source in Project.Sources.Where(s => s.Options != null))
source.Options.Dispose();
var sourceFiles = Options.Modules.SelectMany(m => m.Headers);
Context.TargetInfo = parser.GetTargetInfo(ParserOptions);
Context.ASTContext = ClangParser.ConvertASTContext(parser.ASTContext);
if (Options.UnityBuild)
{
var parserOptions = BuildParserOptions();
var result = parser.ParseSourceFiles(sourceFiles, parserOptions);
result.Dispose();
}
else
{
var results = new List<ParserResult>();
return !hasParsingErrors;
}
foreach (var sourceFile in sourceFiles)
{
var parserOptions = BuildParserOptions(sourceFile);
results.Add(parser.ParseSourceFile(sourceFile, parserOptions));
}
public void BuildParseOptions()
{
foreach (var header in Options.Modules.SelectMany(m => m.Headers))
{
var source = Project.AddFile(header);
if (!Options.UnityBuild)
source.Options = BuildParserOptions(source);
foreach (var result in results)
result.Dispose();
}
if (Options.UnityBuild)
Project.Sources[0].Options = BuildParserOptions();
Context.TargetInfo = parser.GetTargetInfo(ParserOptions);
Context.ASTContext = ClangParser.ConvertASTContext(astContext);
return !hasParsingErrors;
}
public void SortModulesByDependencies()
@ -480,8 +485,6 @@ namespace CppSharp @@ -480,8 +485,6 @@ namespace CppSharp
if (!options.Quiet)
Diagnostics.Message("Parsing code...");
driver.BuildParseOptions();
if (!driver.ParseCode())
{
Diagnostics.Error("CppSharp has encountered an error while parsing code.");

46
src/Parser/Parser.cs

@ -18,7 +18,7 @@ namespace CppSharp @@ -18,7 +18,7 @@ namespace CppSharp
/// <summary>
/// Fired when source files are parsed.
/// </summary>
public Action<IList<SourceFile>, ParserResult> SourcesParsed = delegate {};
public Action<IEnumerable<string>, ParserResult> SourcesParsed = delegate {};
/// <summary>
/// Fired when library files are parsed.
@ -36,10 +36,8 @@ namespace CppSharp @@ -36,10 +36,8 @@ namespace CppSharp
}
/// <summary>
/// Get info about that target
/// Gets target information for a specific target triple.
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
public ParserTargetInfo GetTargetInfo(ParserOptions options)
{
options.ASTContext = ASTContext;
@ -48,47 +46,27 @@ namespace CppSharp @@ -48,47 +46,27 @@ namespace CppSharp
}
/// <summary>
/// Parses a C++ source file to a translation unit.
/// Parses a C++ source file as a translation unit.
/// </summary>
private ParserResult ParseSourceFile(SourceFile file)
public ParserResult ParseSourceFile(string file, ParserOptions options)
{
var options = file.Options;
options.ASTContext = ASTContext;
options.AddSourceFiles(file.Path);
var result = Parser.ClangParser.ParseHeader(options);
SourcesParsed(new[] { file }, result);
return result;
return ParseSourceFiles(new [] { file }, options);
}
/// <summary>
/// Parses C++ source files to a translation unit.
/// Parses a set of C++ source files as a single translation unit.
/// </summary>
private void ParseSourceFiles(IList<SourceFile> files)
public ParserResult ParseSourceFiles(IEnumerable<string> files, ParserOptions options)
{
var options = files[0].Options;
options.ASTContext = ASTContext;
foreach (var file in files)
options.AddSourceFiles(file.Path);
using (var result = Parser.ClangParser.ParseHeader(options))
SourcesParsed(files, result);
}
options.AddSourceFiles(file);
/// <summary>
/// Parses the project source files.
/// </summary>
public void ParseProject(Project project, bool unityBuild)
{
// TODO: Search for cached AST trees on disk
// TODO: Do multi-threaded parsing of source files
if (unityBuild)
ParseSourceFiles(project.Sources);
else
foreach (var parserResult in project.Sources.Select(s => ParseSourceFile(s)).ToList())
parserResult.Dispose();
var result = Parser.ClangParser.ParseHeader(options);
SourcesParsed(files, result);
return result;
}
/// <summary>

131
src/Parser/ParserOptions.cs

@ -1,8 +1,45 @@ @@ -1,8 +1,45 @@
using CppSharp.Parser.AST;
using System.Reflection;
using LanguageVersion = CppSharp.Parser.LanguageVersion;
namespace CppSharp.Parser
{
public enum LanguageVersion
{
/// <summary>
/// C programming language (year 1999).
/// </summary>
C99,
/// <summary>
/// C programming language (year 1999, GNU variant).
/// </summary>
C99_GNU,
/// <summary>
/// C++ programming language (year 1998).
/// </summary>
CPP98,
/// <summary>
/// C++ programming language (year 1998, GNU variant).
/// </summary>
CPP98_GNU,
/// <summary>
/// C++ programming language (year 2011).
/// </summary>
CPP11,
/// <summary>
/// C++ programming language (year 2011, GNU variant).
/// </summary>
CPP11_GNU,
/// <summary>
/// C++ programming language (year 2014).
/// </summary>
CPP14,
/// <summary>
/// C++ programming language (year 2014, GNU variant).
/// </summary>
CPP14_GNU
};
public class ParserOptions : CppParserOptions
{
public ParserOptions()
@ -12,12 +49,12 @@ namespace CppSharp.Parser @@ -12,12 +49,12 @@ namespace CppSharp.Parser
CurrentDir = Assembly.GetExecutingAssembly().Location;
}
public bool IsItaniumLikeAbi { get { return Abi != CppAbi.Microsoft; } }
public bool IsMicrosoftAbi { get { return Abi == CppAbi.Microsoft; } }
public bool EnableRtti { get; set; }
public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.GNUPlusPlus11;
public bool IsItaniumLikeAbi => Abi != CppAbi.Microsoft;
public bool IsMicrosoftAbi => Abi == CppAbi.Microsoft;
public bool EnableRTTI { get; set; }
public LanguageVersion? LanguageVersion { get; set; }
/// Sets up the parser options to work with the given Visual Studio toolchain.
public void SetupMSVC()
{
VisualStudioVersion vsVersion = VisualStudioVersion.Latest;
@ -43,9 +80,13 @@ namespace CppSharp.Parser @@ -43,9 +80,13 @@ namespace CppSharp.Parser
#pragma warning restore 162
}
SetupMSVC(vsVersion);
}
/// <summary>
/// Sets up the parser options to work with the given Visual Studio toolchain.
/// </summary>
public void SetupMSVC(VisualStudioVersion vsVersion)
{
MicrosoftMode = true;
@ -57,6 +98,10 @@ namespace CppSharp.Parser @@ -57,6 +98,10 @@ namespace CppSharp.Parser
var includes = MSVCToolchain.GetSystemIncludes(vsVersion, out foundVsVersion);
foreach (var include in includes)
AddSystemIncludeDirs(include);
if (!LanguageVersion.HasValue)
LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU;
var clVersion = MSVCToolchain.GetCLVersion(foundVsVersion);
ToolSetToUse = clVersion.Major * 10000000 + clVersion.Minor * 100000;
@ -85,15 +130,20 @@ namespace CppSharp.Parser @@ -85,15 +130,20 @@ namespace CppSharp.Parser
public void Setup()
{
SetupArguments();
SetupIncludes();
if (!NoBuiltinIncludes)
SetupIncludes();
}
private void SetupArguments()
{
if (!LanguageVersion.HasValue)
LanguageVersion = CppSharp.Parser.LanguageVersion.CPP14_GNU;
switch (LanguageVersion)
{
case LanguageVersion.C:
case LanguageVersion.GNUC:
case CppSharp.Parser.LanguageVersion.C99:
case CppSharp.Parser.LanguageVersion.C99_GNU:
AddArguments("-xc");
break;
default:
@ -103,64 +153,47 @@ namespace CppSharp.Parser @@ -103,64 +153,47 @@ namespace CppSharp.Parser
switch (LanguageVersion)
{
case LanguageVersion.C:
case CppSharp.Parser.LanguageVersion.C99:
AddArguments("-std=c99");
break;
case LanguageVersion.GNUC:
case CppSharp.Parser.LanguageVersion.C99_GNU:
AddArguments("-std=gnu99");
break;
case LanguageVersion.CPlusPlus98:
case CppSharp.Parser.LanguageVersion.CPP98:
AddArguments("-std=c++98");
break;
case LanguageVersion.GNUPlusPlus98:
case CppSharp.Parser.LanguageVersion.CPP98_GNU:
AddArguments("-std=gnu++98");
break;
case LanguageVersion.CPlusPlus11:
AddArguments(MicrosoftMode ? "-std=c++14" : "-std=c++11");
case CppSharp.Parser.LanguageVersion.CPP11:
AddArguments("-std=c++11");
break;
default:
AddArguments(MicrosoftMode ? "-std=gnu++14" : "-std=gnu++11");
case CppSharp.Parser.LanguageVersion.CPP11_GNU:
AddArguments("-std=gnu++11");
break;
case CppSharp.Parser.LanguageVersion.CPP14:
AddArguments("-std=c++14");
break;
case CppSharp.Parser.LanguageVersion.CPP14_GNU:
AddArguments("-std=gnu++14");
break;
}
if (!EnableRtti)
if (!EnableRTTI)
AddArguments("-fno-rtti");
}
private void SetupIncludes()
{
if (Platform.IsMacOS)
SetupXcode();
else if (Platform.IsWindows && !NoBuiltinIncludes)
SetupMSVC();
switch(Platform.Host)
{
case TargetPlatform.Windows:
SetupMSVC();
break;
case TargetPlatform.MacOS:
SetupXcode();
break;
}
}
}
public enum LanguageVersion
{
/**
* The C programming language.
*/
C,
/**
* The C programming language (GNU version).
*/
GNUC,
/**
* The C++ programming language year 1998; supports deprecated constructs.
*/
CPlusPlus98,
/**
* The C++ programming language year 1998; supports deprecated constructs (GNU version).
*/
GNUPlusPlus98,
/**
* The C++ programming language year 2011.
*/
CPlusPlus11,
/**
* The C++ programming language year 2011 (GNU version).
*/
GNUPlusPlus11
};
}

119
src/Parser/Project.cs

@ -1,119 +0,0 @@ @@ -1,119 +0,0 @@
using System.Collections.Generic;
using CppSharp.AST;
using CppSharp.Parser;
namespace CppSharp
{
/// <summary>
/// Represents a reference to a source file.
/// </summary>
public class SourceFile
{
/// <summary>
/// Gets the file name.
/// </summary>
public string Name
{
get { return System.IO.Path.GetFileName(Path); }
}
/// <summary>
/// Gets the file path.
/// </summary>
public string Path { get; private set; }
/// <summary>
/// Gets/sets the parser options for the file.
/// </summary>
public ParserOptions Options { get; set; }
/// <summary>
/// Gets/sets the AST representation of the file.
/// </summary>
public TranslationUnit Unit { get; set; }
public SourceFile(string path)
{
Path = path;
}
public override string ToString()
{
return Path;
}
}
/// <summary>
/// Represents a C++ project with source and library files.
/// </summary>
public class Project
{
/// <summary>
/// List of per-project C/C++ preprocessor defines.
/// </summary>
public IList<string> Defines { get; private set; }
/// <summary>
/// List of per-project C/C++ include directories.
/// </summary>
public IList<string> IncludeDirs { get; private set; }
/// <summary>
/// List of per-project C/C++ system include directories.
/// </summary>
public IList<string> SystemIncludeDirs { get; private set; }
/// <summary>
/// List of source files in the project.
/// </summary>
public IList<SourceFile> Sources { get; private set; }
/// <summary>
/// Main AST context with translation units for the sources.
/// </summary>
public ASTContext ASTContext { get; private set; }
/// <summary>
/// Main symbols context with indexed library symbols.
/// </summary>
public SymbolContext SymbolsContext { get; private set; }
public Project()
{
Defines = new List<string>();
IncludeDirs = new List<string>();
SystemIncludeDirs = new List<string>();
Sources = new List<SourceFile>();
}
/// <summary>
/// Adds a new source file to the project.
/// </summary>
public SourceFile AddFile(string path)
{
var sourceFile = new SourceFile(path);
Sources.Add(sourceFile);
return sourceFile;
}
/// <summary>
/// Adds a group of source files to the project.
/// </summary>
public void AddFiles(IEnumerable<string> paths)
{
foreach (var path in paths)
AddFile(path);
}
/// <summary>
/// Adds a new source file to the project.
/// </summary>
public void AddFolder(string path)
{
var sourceFile = new SourceFile(path);
Sources.Add(sourceFile);
}
}
}
Loading…
Cancel
Save