我正在将一个自定义语言作为一个名为Compilers的类的项目。整个项目都是Java,使用JFlex作为我的词法分析器,Cup作为我的句法分析器。
我为该语言创建了一个简单的文本编辑器,它基本上由一个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在删除每个字符的情况下运行,因为按住退格键会为每个被删除的字符调用remove()函数。插入文本确实不是问题,因为您可以从文件中加载代码(整个文本中的整个文本将由SyntaxHighlighter整体分析),或者您输入的速度不足以注意滞后。
有没有办法可以优化这个?谢谢大家!
答案 0 :(得分:1)
我的第一直觉是采用窗口策略。在您的代码中维护一个树或一些能够表示自包含范围的结构。然后调整语法高亮显示和代码的其他部分,使其仅适用于他们知道受影响的树的部分(或其他)。
抽象地说,你可能有这样的关系:
class
|
+----------+
method1 method2
|
+--------+--------+
line1 line2 line3
...允许在不更改
的上下文中理解第3行中的删除答案 1 :(得分:0)
总而言之,这些代码似乎结构清晰,我理解得非常快。所以我的建议是:尽可能长时间保持原样(强制开闭原则)。
我建议的唯一变化是将字符删除与突出显示分开。这已经提到了。但是你应该这样做的原因是:你将能够延迟语法高亮,直到用户删除了一大块字符。因此,每次只删除一个字符时,语法突出显示都不会被删除。
我认为你应该将主要文本分解为语法单元,然后仅在更改的语法单元上应用语法高亮。主要问题是解析和识别已更改的单位。
正如之前的作者所提到的,将语法突出显示隔离到一个单独的线程中也会提高性能。
这些改变并非易事,但可能。
答案 2 :(得分:0)
定义类字段javax.swing.Timer syntaxTimer
。
在每个insert()
或remove()
上检查syntaxTimer
是否为空。
如果它为null,则创建具有500毫秒延迟的syntaxTimer
实例(可以根据需要为300或1000)并启动syntaxTimer
。如果不是只是跳过定时器初始化,因为你已经初始化了它。
调用syntaxTimer
的{{1}}时,请执行actionPerformed()
相关逻辑并清除SyntaxHighlighter
(停止并设置syntaxTimer
)。< / p>