Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/Highlighter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Tempest\Highlight\Languages\Bash\BashLanguage;
use Tempest\Highlight\Languages\BBCode\BBCodeLanguage;
use Tempest\Highlight\Languages\Blade\BladeLanguage;
use Tempest\Highlight\Languages\CSharp\CSharpLanguage;
use Tempest\Highlight\Languages\C\CLanguage;
use Tempest\Highlight\Languages\Cpp\CppLanguage;
use Tempest\Highlight\Languages\Css\CssLanguage;
Expand Down Expand Up @@ -78,6 +79,7 @@ public function __construct(
->addLanguage(new BashLanguage())
->addLanguage(new BBCodeLanguage())
->addLanguage(new BladeLanguage())
->addLanguage(new CSharpLanguage())
->addLanguage(new CLanguage())
->addLanguage(new CppLanguage())
->addLanguage(new CssLanguage())
Expand Down
58 changes: 58 additions & 0 deletions src/Languages/CSharp/CSharpLanguage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp;

use Override;
use Tempest\Highlight\Languages\Base\BaseLanguage;
use Tempest\Highlight\Languages\CLike\Patterns\CLikeCommentPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpAttributePattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpCallablePattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpDeclarationPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpDelegatePattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpKeywordPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpLiteralPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpNamespacePattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpNumberPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpOperatorPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpPreprocessorPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpPropertyPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpStringPattern;
use Tempest\Highlight\Languages\CSharp\Patterns\CSharpTypePattern;

final class CSharpLanguage extends BaseLanguage
{
public function getName(): string
{
return 'csharp';
}

#[Override]
public function getAliases(): array
{
return ['cs', 'c#'];
}

#[Override]
public function getPatterns(): array
{
return [
...parent::getPatterns(),
new CLikeCommentPattern(),
new CSharpStringPattern(),
new CSharpPreprocessorPattern(),
new CSharpAttributePattern(),
new CSharpNamespacePattern(),
new CSharpNumberPattern(),
new CSharpLiteralPattern(),
new CSharpKeywordPattern(),
new CSharpDeclarationPattern(),
new CSharpDelegatePattern(),
new CSharpCallablePattern(),
new CSharpPropertyPattern(),
new CSharpTypePattern(),
new CSharpOperatorPattern(),
];
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpAttributePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: '[Obsolete]', output: 'Obsolete')]
#[PatternTest(input: '[assembly: Guid("x")]', output: 'Guid')]
final readonly class CSharpAttributePattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\[\h*(?:(?:assembly|module|field|event|method|param|property|return|type):\h*)?(?<match>[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?:Attribute)?)';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::ATTRIBUTE;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpCallablePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'Render()', output: 'Render')]
#[PatternTest(input: 'Method<int>()', output: 'Method')]
final readonly class CSharpCallablePattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '(?<![\w@])(?!(?:catch|checked|do|for|foreach|if|lock|sizeof|switch|typeof|unchecked|using|while)\b)(?<match>@?[A-Za-z_]\w*)(?=\h*(?:<[^<>]*>\h*)?\()';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::PROPERTY;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpDeclarationPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'class User {}', output: 'User')]
#[PatternTest(input: 'record Point(int X);', output: 'Point')]
final readonly class CSharpDeclarationPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\b(?:class|interface|struct|record|enum)\h+(?<match>@?[A-Za-z_]\w*)';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::TYPE;
}
}
26 changes: 26 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpDelegatePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'delegate int Callback(int value);', output: 'Callback')]
final readonly class CSharpDelegatePattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\bdelegate\h+(?:[A-Za-z_]\w*(?:\h*<[^<>]*>)?(?:\h*\[\h*])?\??)\h+(?<match>@?[A-Za-z_]\w*)(?=\h*(?:<[^<>]*>\h*)?\()';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::TYPE;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpKeywordPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'namespace Example;', output: 'namespace')]
#[PatternTest(input: 'async Task Run()', output: 'async')]
final readonly class CSharpKeywordPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\b(?<match>abstract|add|alias|and|as|ascending|async|await|base|break|by|case|catch|checked|class|const|continue|default|delegate|descending|do|else|enum|equals|event|explicit|extern|file|finally|fixed|for|foreach|from|get|global|goto|group|if|implicit|in|init|interface|internal|into|is|join|let|lock|managed|nameof|namespace|new|not|notnull|on|operator|or|orderby|out|override|params|partial|private|protected|public|readonly|record|ref|remove|required|return|scoped|sealed|select|set|sizeof|stackalloc|static|struct|switch|this|throw|try|typeof|unchecked|unmanaged|unsafe|using|value|virtual|volatile|when|where|while|with|yield)\b';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::KEYWORD;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpLiteralPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'true', output: 'true')]
#[PatternTest(input: 'null', output: 'null')]
final readonly class CSharpLiteralPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\b(?<match>true|false|null)\b';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::LITERAL;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpNamespacePattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'namespace Example.App;', output: 'Example.App')]
#[PatternTest(input: 'using System.Text;', output: 'System.Text')]
final readonly class CSharpNamespacePattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '\b(?:namespace|using)\h+(?:static\h+|global\h+)?(?:[A-Za-z_]\w*\h*=\h*)?(?<match>(?:global::)?[A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::TYPE;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpNumberPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: '1_000m', output: '1_000m')]
#[PatternTest(input: '0xFF', output: '0xFF')]
final readonly class CSharpNumberPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?<![\w.])(?<match>(?:0[xX][\dA-Fa-f](?:_?[\dA-Fa-f])*|0[bB][01](?:_?[01])*|(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?|\.\d(?:_?\d)*)(?:[eE][+-]?\d(?:_?\d)*)?)(?:[uUlLfFdDmM]{1,2})?)(?![\w.])/';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::NUMBER;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpOperatorPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'x => x + 1', output: '=>')]
#[PatternTest(input: 'user?.Name', output: '?.')]
final readonly class CSharpOperatorPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?<match>=>|\?\?=|\?\?|\?\.|\?\[|\.\.|<<=?|>>=?|\+\+|--|&&|\|\||==|!=|<=|>=|[-+*\/%&|^~!<>=]=?|[?:;,.{}()\[\]])/';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::OPERATOR;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpPreprocessorPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: '#nullable enable', output: '#nullable')]
#[PatternTest(input: '#region Setup', output: '#region')]
final readonly class CSharpPreprocessorPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?m)^\h*(?<match>#\h*(?:define|undef|if|elif|else|endif|line|error|warning|region|endregion|pragma|nullable|r|load)\b)/';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::KEYWORD;
}
}
27 changes: 27 additions & 0 deletions src/Languages/CSharp/Patterns/CSharpPropertyPattern.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Tempest\Highlight\Languages\CSharp\Patterns;

use Tempest\Highlight\IsPattern;
use Tempest\Highlight\Pattern;
use Tempest\Highlight\PatternTest;
use Tempest\Highlight\Tokens\TokenTypeEnum;

#[PatternTest(input: 'user.Name', output: 'Name')]
#[PatternTest(input: 'Name { get; }', output: 'Name')]
final readonly class CSharpPropertyPattern implements Pattern
{
use IsPattern;

public function getPattern(): string
{
return '/(?:(?:\?\.|\.)\K|(?<![\w@])(?=@?[A-Za-z_]\w*\h*(?:\{|=>)))(?<match>@?[A-Za-z_]\w*)(?!\h*\()/';
}

public function getTokenType(): TokenTypeEnum
{
return TokenTypeEnum::PROPERTY;
}
}
Loading
Loading