PDA

View Full Version : QTextEdit parenthesis matcher works - but only partially



heinzkde
27th May 2010, 09:03
Hello dear llist,

writing an interactive Lisp-editor I added a parenthesis matcher. I found a nice solution in Qt Quarterly issue 31/2009 at

http://doc.trolltech.com/qq/

Works well basically, but has a minor bug somewhere. Marking a left parenthesis always marks the corresponding right parenthesis correctly.

But vice versa - so marking a right parenthesis - won't work in some cases. Examples how marking the last right parenthesis will behave:

;; fails
(defun primep
((= 0 (mod x 2)) nil)
)

;; works
(defun primep
((= 0 (mod x 2)) nil))

;; works
(defun nextprime (x)
(loop for i from x
when (primep i) return i))

;; fails
(defun primep (x)
(cond
((not (integerp x)) nil)
((< x 2) nil)
((= x 2) 2)
((= 0 (mod x 2)) nil)
(t (loop for i from 3 to (isqrt x) by 2
never (= 0 (mod x i))))))

;; fails
(defun infix2prefix (infix-expression)
(list (second infix-expression)
(first infix-expression)
(third infix-expression)))

To try it out, paste it in the example code, which could be found at the link mentioned above or as attachment.

To give you a more detailed pointer and to spare your time: The hot spot is near the end of "textedit.cpp", where you find the three functions:

matchParentheses()
matchLeftParenthesis(...
matchRightParenthesis(...

matchLeftParenthesis always works regardless how the code is formatted or how parenthesis are nested. matchRightParenthesis will work mostly, but not in every case. Interestingly matchRightParenthesis is only a mirror image from the left-function. So one would expect, that it will work as well as the left counterpart.

Tried out a lot, but I am running out of ideas. Hope that some more clever people than I could give me a pointer.


Kind regards, Heinz

heinzkde
28th May 2010, 10:51
Hello dear list,

now wonder, that nobody came up with a solution. The patch is quite short, but tricky too because the Qt4 Quarterly solution only fails with more complex recursion levels.

When interested look at the attachment. Please note that my "patch" is inherited from "mainWindow" instead of the original "TextEdit" and my Q(Plain)TextEdit is my own "textEdit" instead of "this". For sure you can abstract this minor difference only affecting a few lines.

So what really changed?

a) matchParentheses()
.. only added a reset for new parenthesis counters

b) matchLeftParenthesis(...
nothing as this stuff works perfect

c) matchRightParenthesis(...
added some missing checks and an additional recursion level when necessary

All other functions/files from the original Qt4 Quarterly code can stay completely unchanged.


Kind regards, Heinz

heinzkde
31st May 2010, 13:31
Hello dear list,

my last patch to the "parenthesis matcher" from Qt Quarterly was a lot better/functional than the original Qt/Nokia-code. But less elegant too and - more important - it fails for some complicated nesting too.

When anybody is interested in my final and working solution:

http://qt-apps.org/content/show.php/CLedit?content=125532

Look near the end of mainwindow.cpp. There you will find an elegant and - independent from nesting levels - always corrected solution for the task "parenthesis match".


Kind regards, Heinz