C# 访问未被解析器规则引用的ANTLR令牌
我正试图基于Java语言,用C#编写一个Java语法高亮程序。为了做到这一点,我目前正试图跟踪访问者中的C# 访问未被解析器规则引用的ANTLR令牌,c#,.net,parsing,antlr,antlr4,C#,.net,Parsing,Antlr,Antlr4,我正试图基于Java语言,用C#编写一个Java语法高亮程序。为了做到这一点,我目前正试图跟踪访问者中的\u index字段,我每次通过一个节点时都会添加该字段。代码如下: private class Visitor : JavaBaseVisitor<object> { private readonly string _rawText; private readonly SpannableString _text; private readonly ISyn
\u index
字段,我每次通过一个节点时都会添加该字段。代码如下:
private class Visitor : JavaBaseVisitor<object>
{
private readonly string _rawText;
private readonly SpannableString _text;
private readonly ISyntaxStyler _styler;
private int _index;
internal Visitor(string text, ISyntaxStyler styler)
{
_rawText = text;
_text = new SpannableString(text);
_styler = styler;
}
public override object VisitAnnotation([NotNull] JavaParser.AnnotationContext context)
{
Advance("@", SyntaxKind.Annotation);
VisitAnnotationName(context.annotationName());
this.VisitChildren(context, 2);
return null;
}
public override object VisitPackageDeclaration([NotNull] JavaParser.PackageDeclarationContext context)
{
int index = 0;
var child = context.GetChild(0);
while (child is JavaParser.AnnotationContext)
{
Visit(child);
child = context.GetChild(++index);
}
Advance("package", SyntaxKind.Keyword);
this.VisitChildren(context, index + 1);
return null;
}
public override object VisitTerminal(ITerminalNode node)
{
Advance(node.Symbol.Text, SyntaxKind.Identifier);
return null;
}
internal SpannableString HighlightText()
{
Visit(CreateTree(_rawText));
return _text;
}
private void Advance(int count, SyntaxKind kind)
{
var span = _styler.GetSpan(kind);
_text.SetSpan(span, _index, _index + count, SpanTypes.InclusiveExclusive);
_index += count;
}
private void Advance(string toSkip, SyntaxKind kind)
{
int count = toSkip.Length;
Debug.Assert(string.Compare(_rawText, _index, toSkip, 0, count) == 0);
Advance(count, kind);
}
private static JavaParser.CompilationUnitContext CreateTree(string text)
{
var inputStream = new AntlrInputStream(text);
var lexer = new JavaLexer(inputStream);
var tokenStream = new CommonTokenStream(lexer);
var parser = new JavaParser(tokenStream);
return parser.compilationUnit();
}
}
直到处理包
之后,当前标记的索引与原始文本中的索引相同。但是,当处理a
时,\u索引
的空格没有增加,因此它比应该的值落后1。当<代码>代码>已处理,它将落后于它应该的2。然后
将获得a
的着色,a
将获得下一个
的着色,d
将获得的着色代码>,等等
有没有一种方法可以在访问者中提取空白标记,这样索引就不会被弄乱?谢谢。你说得对,语法吃空格。但是lexer没有。我处理语法突出显示,因此也处理显式标记处理,包括空格,如下所示。主要的事情是覆盖lexer的Emit
方法。这是我在这里概述的过程的一部分
一个小类,允许我在令牌源中记录类型、开始和停止长度
public class TokenExtent
{
public string Name { get; set; }
public int Start { get; set; }
public int Length { get; set; }
public TokenExtent(string name, int start, int stop)
{
Name = name;
Start = start;
Length = stop - start + 1;
}
}
我用每次解析填充的标记扩展数据块列表
public static List<TokenExtent> TokenExtents = new List<TokenExtent>();
我应用样式的表单中的Higlight()
方法:
private void Highlight()
{
foreach (TokenExtent ext in BasicEnvironment.TokenExtents)
{
switch (ext.Name)
{
case "ID" :
{
etCode2.Select(ext.Start, ext.Length);
etCode2.SelectionColor = Color.Blue;
break;
}
case "COMMENT" :
{
etCode2.Select(ext.Start, ext.Length);
etCode2.SelectionColor = Color.DimGray;
break;
}
case "WS":
{
etCode2.Select(ext.Start, ext.Length);
etCode2.SelectionBackColor = Color.BurlyWood;
break;
}
}
}
}
我更改了空白的背景色以使其更加突出,因此它看起来是这样的:
如您所见,如果您使用lexer进入其中,您可以将这些空白标记与lexer规则命名的任何其他标记一样对待
public class BailLexer : LISBASICLexer
{
public BailLexer(ICharStream input) : base(input) { }
public override IToken Emit()
{
IToken token = base.Emit();
switch (token.Type)
{
case ID :
{
TokenExtent extent = new TokenExtent("ID", token.StartIndex, token.StopIndex);
BasicEnvironment.TokenExtents.Add(extent);
break;
}
case COMMENT :
{
TokenExtent extent = new TokenExtent("COMMENT", token.StartIndex, token.StopIndex);
BasicEnvironment.TokenExtents.Add(extent);
break;
}
case WS:
{
TokenExtent extent = new TokenExtent("WS", token.StartIndex, token.StopIndex);
BasicEnvironment.TokenExtents.Add(extent);
break;
}
private void Highlight()
{
foreach (TokenExtent ext in BasicEnvironment.TokenExtents)
{
switch (ext.Name)
{
case "ID" :
{
etCode2.Select(ext.Start, ext.Length);
etCode2.SelectionColor = Color.Blue;
break;
}
case "COMMENT" :
{
etCode2.Select(ext.Start, ext.Length);
etCode2.SelectionColor = Color.DimGray;
break;
}
case "WS":
{
etCode2.Select(ext.Start, ext.Length);
etCode2.SelectionBackColor = Color.BurlyWood;
break;
}
}
}
}