1

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 に適切な量のテキストがある場合、バックスペース キーを押したままにしてテキストを削除すると、プログラムの遅延がかなり大きくなります。これが発生すると私が考える理由は、バックスペース キーを押したままにすると、削除される各文字に対して remove() 関数が呼び出されるため、SyntaxHighlighter がすべての文字が削除された状態で実行されるためだと考えられます。ファイルからコードをロードするか (そのファイル内のテキスト全体が SyntaxHighlighter によって全体として分析される)、または遅延に気付くほど速く入力できないため、テキストの挿入は実際には問題ではありません。

これを最適化する方法はありますか?皆さん、ありがとうございました!

4

3 に答える 3

1

私の最初の本能は、ウィンドウ戦略を採用することです。コード内で、自己完結型のスコープを表すことができるツリーまたはその他の構造を維持します。次に、構文ハイライターとコードの他の部分を調整して、影響を受けることがわかっているツリーの部分 (または何でも) でのみ機能するようにします。

抽象的には、次のような関係があります。

class
  |
+----------+
method1    method2
              |
           +--------+--------+
           line1    line2    line3

...これにより、変更されていないもののコンテキストで3行目の削除を理解できます

于 2015-05-12T15:36:41.837 に答える
0

全体として、このコードは構造化されていて明確であるように思われ、非常に速く理解できました。したがって、私の提案は、可能な限りそのままにしておくことです (開閉の原則を強制します)。

私が提案する唯一の変更は、強調表示から文字の削除を分離することです。これはすでに述べた。ただし、これを行う必要がある理由は次のとおりです。ユーザーが文字のチャンクを削除するまで、構文の強調表示を遅らせることができます。そのため、1 文字だけを削除するたびに構文の強調表示がトリガーされるわけではありません。

本文を構文単位に分割し、変更された構文単位にのみ構文強調表示を適用する必要があると思います。主な問題は、変更された単位の解析と識別です。

前の著者が述べたように、構文の強調表示を別のスレッドに分離すると、パフォーマンスも向上します。

これらの変更は些細なことではありませんが、可能です。

于 2015-05-12T15:42:31.820 に答える
0

クラス フィールドを定義しますjavax.swing.Timer syntaxTimer

それぞれのinsert()またはが nullremove()かどうかを確認します。syntaxTimer

null のsyntaxTimer場合は、500 ミリ秒の遅延 (必要に応じて 300 または 1000 にすることができます) でインスタンスを作成し、syntaxTimer. すでに初期化されているため、タイマーの初期化をスキップしない場合。

syntaxTimeractionPerformed()呼び出されたら、関連SyntaxHighlighterするロジックを実行し、 をクリアしますsyntaxTimer(停止して を設定しますsyntaxTimer=null)。

于 2015-05-14T06:17:10.413 に答える