Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@2972 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61shortcuts
14 changed files with 511 additions and 57 deletions
@ -0,0 +1,90 @@
@@ -0,0 +1,90 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using ICSharpCode.NRefactory.Ast; |
||||
using ICSharpCode.NRefactory.Visitors; |
||||
|
||||
namespace ICSharpCode.NRefactory.Parser.CSharp |
||||
{ |
||||
sealed class ConditionalCompilation : AbstractAstVisitor |
||||
{ |
||||
static readonly object SymbolDefined = new object(); |
||||
Dictionary<string, object> symbols = new Dictionary<string, object>(); |
||||
|
||||
public IDictionary<string, object> Symbols { |
||||
get { return symbols; } |
||||
} |
||||
|
||||
public void Define(string symbol) |
||||
{ |
||||
symbols[symbol] = SymbolDefined; |
||||
} |
||||
|
||||
public void Undefine(string symbol) |
||||
{ |
||||
symbols.Remove(symbol); |
||||
} |
||||
|
||||
public bool Evaluate(Expression condition) |
||||
{ |
||||
return condition.AcceptVisitor(this, null) == SymbolDefined; |
||||
} |
||||
|
||||
public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) |
||||
{ |
||||
if (primitiveExpression.Value is bool) |
||||
return (bool)primitiveExpression.Value ? SymbolDefined : null; |
||||
else |
||||
return null; |
||||
} |
||||
|
||||
public override object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) |
||||
{ |
||||
return symbols.ContainsKey(identifierExpression.Identifier) ? SymbolDefined : null; |
||||
} |
||||
|
||||
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) |
||||
{ |
||||
if (unaryOperatorExpression.Op == UnaryOperatorType.Not) { |
||||
return unaryOperatorExpression.Expression.AcceptVisitor(this, data) == SymbolDefined ? null : SymbolDefined; |
||||
} else { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) |
||||
{ |
||||
bool lhs = binaryOperatorExpression.Left.AcceptVisitor(this, data) == SymbolDefined; |
||||
bool rhs = binaryOperatorExpression.Right.AcceptVisitor(this, data) == SymbolDefined; |
||||
bool result; |
||||
switch (binaryOperatorExpression.Op) { |
||||
case BinaryOperatorType.LogicalAnd: |
||||
result = lhs && rhs; |
||||
break; |
||||
case BinaryOperatorType.LogicalOr: |
||||
result = lhs || rhs; |
||||
break; |
||||
case BinaryOperatorType.Equality: |
||||
result = lhs == rhs; |
||||
break; |
||||
case BinaryOperatorType.InEquality: |
||||
result = lhs != rhs; |
||||
break; |
||||
default: |
||||
return null; |
||||
} |
||||
return result ? SymbolDefined : null; |
||||
} |
||||
|
||||
public override object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) |
||||
{ |
||||
return parenthesizedExpression.Expression.AcceptVisitor(this, data); |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,142 @@
@@ -0,0 +1,142 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using NUnit.Framework; |
||||
using ICSharpCode.NRefactory.Parser; |
||||
using ICSharpCode.NRefactory.Parser.CSharp; |
||||
using ICSharpCode.NRefactory.PrettyPrinter; |
||||
using NUnit.Framework.SyntaxHelpers; |
||||
|
||||
namespace ICSharpCode.NRefactory.Tests.Lexer.CSharp |
||||
{ |
||||
[TestFixture] |
||||
public class PreprocessingTests |
||||
{ |
||||
ILexer GenerateLexer(string text) |
||||
{ |
||||
ILexer lexer = ParserFactory.CreateLexer(SupportedLanguage.CSharp, new StringReader(text)); |
||||
lexer.EvaluateConditionalCompilation = true; |
||||
lexer.ConditionalCompilationSymbols["TEST"] = null; |
||||
return lexer; |
||||
} |
||||
|
||||
int[] GetTokenKinds(string text) |
||||
{ |
||||
List<int> list = new List<int>(); |
||||
ILexer lexer = GenerateLexer(text); |
||||
Token token; |
||||
while ((token = lexer.NextToken()) != null) { |
||||
list.Add(token.kind); |
||||
if (token.kind == Tokens.EOF) |
||||
break; |
||||
} |
||||
Assert.AreEqual("", lexer.Errors.ErrorOutput); |
||||
return list.ToArray(); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestEmptyIfdef() |
||||
{ |
||||
Assert.AreEqual(new int[] { Tokens.Int, Tokens.EOF }, GetTokenKinds("#if true\n#endif\nint")); |
||||
Assert.AreEqual(new int[] { Tokens.Int, Tokens.EOF }, GetTokenKinds("#if false\n#endif\nint")); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestBooleanPrimitives() |
||||
{ |
||||
Assert.AreEqual(new int[] { Tokens.True, Tokens.EOF }, GetTokenKinds("#if true \n true \n #else \n false \n #endif")); |
||||
Assert.AreEqual(new int[] { Tokens.False, Tokens.EOF }, GetTokenKinds("#if false \n true \n #else \n false \n #endif")); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestDefinedSymbols() |
||||
{ |
||||
Assert.AreEqual(new int[] { Tokens.True, Tokens.EOF }, GetTokenKinds("#if TEST \n true \n #else \n false \n #endif")); |
||||
Assert.AreEqual(new int[] { Tokens.False, Tokens.EOF }, GetTokenKinds("#if DEBUG \n true \n #else \n false \n #endif")); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestDefineUndefineSymbol() |
||||
{ |
||||
Assert.AreEqual(new int[] { Tokens.False, Tokens.EOF }, GetTokenKinds("#undef TEST \n #if TEST \n true \n #else \n false \n #endif")); |
||||
Assert.AreEqual(new int[] { Tokens.True, Tokens.EOF }, GetTokenKinds("#define DEBUG \n #if DEBUG \n true \n #else \n false \n #endif")); |
||||
Assert.AreEqual(new int[] { Tokens.True, Tokens.EOF }, GetTokenKinds("#define DEBUG // comment \n #if DEBUG \n true \n #else \n false \n #endif")); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestNestedIfDef() |
||||
{ |
||||
string program = @"
|
||||
#if A
|
||||
public |
||||
#if B
|
||||
abstract |
||||
#elif C
|
||||
virtual |
||||
#endif
|
||||
void |
||||
#elif B
|
||||
protected |
||||
#if C // this is a comment
|
||||
sealed |
||||
#endif
|
||||
string |
||||
#else
|
||||
class |
||||
#endif
|
||||
";
|
||||
Assert.AreEqual(new int[] { Tokens.Class, Tokens.EOF }, GetTokenKinds(program)); |
||||
Assert.AreEqual(new int[] { Tokens.Public, Tokens.Void, Tokens.EOF }, GetTokenKinds("#define A\n" + program)); |
||||
Assert.AreEqual(new int[] { Tokens.Public, Tokens.Abstract, Tokens.Void, Tokens.EOF }, |
||||
GetTokenKinds("#define A\n#define B\n" + program)); |
||||
Assert.AreEqual(new int[] { Tokens.Public, Tokens.Virtual, Tokens.Void, Tokens.EOF }, |
||||
GetTokenKinds("#define A\n#define C\n" + program)); |
||||
Assert.AreEqual(new int[] { Tokens.Public, Tokens.Abstract, Tokens.Void, Tokens.EOF }, |
||||
GetTokenKinds("#define A\n#define B\n#define C\n" + program)); |
||||
Assert.AreEqual(new int[] { Tokens.Protected, Tokens.String, Tokens.EOF }, |
||||
GetTokenKinds("#define B\n" + program)); |
||||
Assert.AreEqual(new int[] { Tokens.Protected, Tokens.Sealed, Tokens.String, Tokens.EOF }, |
||||
GetTokenKinds("#define B\n#define C\n" + program)); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestDefineInIfDef() |
||||
{ |
||||
string program = @"
|
||||
#if !A
|
||||
#define B
|
||||
class |
||||
#else
|
||||
int |
||||
#endif
|
||||
#if B
|
||||
struct |
||||
#endif
|
||||
";
|
||||
Assert.AreEqual(new int[] { Tokens.Class, Tokens.Struct, Tokens.EOF }, GetTokenKinds(program)); |
||||
Assert.AreEqual(new int[] { Tokens.Int, Tokens.EOF }, GetTokenKinds("#define A\n" + program)); |
||||
} |
||||
|
||||
[Test] |
||||
public void TestMultilineCommentStartInIfDef() |
||||
{ |
||||
string program = @"
|
||||
#if X
|
||||
struct |
||||
/* |
||||
#else
|
||||
/* */ class |
||||
#endif
|
||||
";
|
||||
Assert.AreEqual(new int[] { Tokens.Class, Tokens.EOF }, GetTokenKinds(program)); |
||||
Assert.AreEqual(new int[] { Tokens.Struct, Tokens.Class, Tokens.EOF }, GetTokenKinds("#define X\n" + program)); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue