我正在为一个名为编译器的类创建一个自定义语言作为一个项目。整个项目使用Java语言,使用JFlex作为我的词法分析器,使用杯子作为语法分析器。
我为该语言创建了一个简单的文本编辑器,它基本上由一个JTextPane组成,用户可以在其中键入将被解析的自定义代码。这个JTextPane有一个DefaultStyledDocument,用于设置字符属性,例如,为JTextPane内的代码(文本)更改关键字、注释、字符串、数字等的颜色。
下面是我使用的代码:
DefaultStyledDocument doc = new DefaultStyledDocument() {
@Override
public void insertString(int offset, String str, AttributeSet a) throws BadLocationException { //cuando se insertan caracteres.
super.insertString(offset, str, a);
String text = getText(0, getLength());
syntax = new SyntaxHighlighter(new java.io.StringReader(text));
Token val;
try {
while ((val = syntax.yylex()) != null) {
switch (val.type) {
case TokenType.KEYWORD:
setCharacterAttributes(val.start, val.length, keyword, true);
break;
case TokenType.COMMENT:
setCharacterAttributes(val.start, val.length, comment, true);
break;
case TokenType.STRING:
setCharacterAttributes(val.start, val.length, string, true);
break;
case TokenType.FUNCTION:
setCharacterAttributes(val.start, val.length, function, true);
break;
case TokenType.NUMBER:
setCharacterAttributes(val.start, val.length, plain, true);
break;
case TokenType.OPERATOR:
setCharacterAttributes(val.start, val.length, operator, true);
break;
case TokenType.READ:
setCharacterAttributes(val.start, val.length, number, true);
break;
default:
setCharacterAttributes(val.start, val.length, plain, true);
break;
}
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(rootPane, "Oops! Exception triggered\n" + ex.getMessage());
}
}
@Override
//this is the method I want to optimize
public void remove(int offs, int len) throws BadLocationException {
super.remove(offs, len);
String text = getText(0, getLength());
syntax = new SyntaxHighlighter(new java.io.StringReader(text));
Token val;
try {
while ((val = syntax.yylex()) != null) {
switch (val.type) {
case TokenType.KEYWORD:
setCharacterAttributes(val.start, val.length, keyword, true);
break;
case TokenType.COMMENT:
setCharacterAttributes(val.start, val.length, comment, true);
break;
case TokenType.STRING:
setCharacterAttributes(val.start, val.length, string, true);
break;
case TokenType.FUNCTION:
setCharacterAttributes(val.start, val.length, function, true);
break;
case TokenType.NUMBER:
setCharacterAttributes(val.start, val.length, plain, true);
break;
case TokenType.OPERATOR:
setCharacterAttributes(val.start, val.length, operator, true);
break;
case TokenType.READ:
setCharacterAttributes(val.start, val.length, number, true);
break;
default:
setCharacterAttributes(val.start, val.length, plain, true);
break;
}
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(rootPane, "Oops! Exception triggered\n" + ex.getMessage());
}
}
};
this.codeTextPane.setStyledDocument(doc);SyntaxHighlighter类基本上是一个词法器(由JFlex生成),仅用作搜索特定文本片段(关键字、字符串等)的方法。一切都很完美但是..。
问题:
当JTextPane中有相当数量的文本时,按住后退键移除文本会使程序延迟相当困难。我认为发生这种情况的原因可能是因为SyntaxHighlighter运行时每个字符都被删除,因为按住backspace键调用每个被删除字符的remove()函数。插入文本并不是一个真正的问题,因为您可以从一个文件加载代码(在该文件中的整个文本将由SyntaxHighlighter作为一个整体进行分析),或者您不能以足够快的速度键入以注意到延迟。
有什么方法可以优化这个吗?谢谢大家!
发布于 2015-05-12 15:42:31
总之,这些代码似乎是结构化的,而且很清楚,我很快就理解了它。因此,我的建议是:尽可能长地保留它(强制开放-封闭原则)。
我建议的唯一改变是将字符删除与突出显示分开。这一点已经提过了。但是,您应该这样做的原因是:您将能够延迟语法高亮显示,直到用户删除了一部分字符。因此,语法突出显示不会每次删除一个字符时都会被忽略。
我认为您应该将主文本分解为句法单元,然后只在已更改的句法单元上应用突出显示语法。主要问题是分析和识别变化的单元。
正如前面的作者所提到的,将语法突出显示到分离的线程中也会提高性能。
这些变化不是琐碎的,而是可能的。
发布于 2015-05-12 15:36:41
我的第一反应是采取加窗的策略。在您的代码中,维护一棵树或其他能够表示自包含范围的结构。然后,调整语法高亮符和代码的其他部分,使其只在树的部分(或他们所知道的任何部分)上工作。
抽象地说,你们可能有这样的关系:
class
|
+----------+
method1 method2
|
+--------+--------+
line1 line2 line3..。,它允许在不更改内容的上下文中理解line3中的删除。
发布于 2015-05-14 06:17:10
定义类字段javax.swing.Timer syntaxTimer。
在每个insert()或remove()上检查syntaxTimer是否为null。
如果为null,则创建具有500 msec延迟的syntaxTimer实例(可以是300或1000,如您所愿)并启动syntaxTimer。如果不只是跳过计时器初始化,因为您已经初始化了它。
当调用syntaxTimer的actionPerformed()时,执行与SyntaxHighlighter相关的逻辑并清除syntaxTimer (停止并设置syntaxTimer=null)。
https://stackoverflow.com/questions/30194784
复制相似问题