Re: Order of definitions in source-highlight 2.10

Lorenzo Bettini <[email protected]> Fri, 05 Sep 2008 01:28:29 +0200
Newsgroups gmane.comp.gnu.source-highlight.general
Message-ID <[email protected]>
[email protected] wrote:
> I just upgraded source-highlight to 2.10 and I am noticing some strange 
> behavior.
> 
> Suppose we have the file foo.lang:
> 
> symbol = "/"
> comment start "//"
> 
> And the file test.foo:
> 
> // foo
> 
> The language definition is taken from the source-highlight manual, 
> section 7.4: "Order of definitions".  Note that the definitions are in 
> the wrong order, according to the manual: "The first expression will 
> always be matched first, and the second expression will never be 
> matched."  And yet:
> 
> $ source-highlight --lang-def=foo.lang -c foo.css --no-doc -i test.foo
> <!-- Generator: GNU source-highlight 2.10
> by Lorenzo Bettini
> http://www.lorenzobettini.it
> http://www.gnu.org/software/src-highlite -->
> <pre><tt><span class="comment">// foo</span>
> </tt></pre>
> 
> This was different with version 2.9:
> 
> $ source-highlight --lang-def=foo.lang -c foo.css --no-doc -i test.foo
> <!-- Generator: GNU source-highlight 2.9
> by Lorenzo Bettini
> http://www.lorenzobettini.it
> http://www.gnu.org/software/src-highlite -->
> <pre><tt><span class="symbol">//</span><span class="normal"> foo</span>
> </tt></pre>
> 
> What has changed between version 2.9 and 2.10?

Hi there

as I had already written in the previous email, the matching strategy 
changed between 2.9 and 2.10:

"The strategy used by source-highlight is to select the first rule that 
matches the longest part of the text with the smallest prefix (i.e., the 
initial part of the line that contains no language element). (Thus, as 
already noted in the previous sections, the order of language 
definitions is crucial.)"

however, when working on the documentation, I actually realized that 
this strategy is too involved and a little bit confusing, not to mention 
that it has a lot of overhead, since it tests ALL the rules in a state.

Then, I realized that basically the rule that should be selected is the 
one with the smallest prefix, but we could stop testing rules as soon as 
we find a rule that matches and whose prefix (i.e., the part of the 
string before the matched one) contains only spaces (or it's empty).  I 
think this is also the strategy used by standard regular expression 
engines, or at least, this one seems to be enough for programming languages.

Thus, for instance, if I have

i = null;

if I match null as a keyword, its prefix is "i = " and I should not stop 
testing other rules, since otherwise I would not test the symbol rule 
(that is defined later).

While, if I have

    if (exp)

as soon as I match "if" as a keyword, since its prefix is "   ", I can 
stop testing other rules (this way, I don't even risk to match "if(exp)" 
as a function call (note that with the previous strategy this would 
match better since it matches more characters).

I think this is the right strategy and it brings the example in the 
documentation to work again as described.

I've uploaded a temporary version that uses this strategy (and it also 
performs faster as expected) here:

http://gdn.dsi.unifi.it/~bettini/source-highlight-2.10.1.tar.gz

I'd really appreciate to get some feedback, especially do you think that 
this new strategy makes sense?

There's also a new test in the tests directory: test_string_stop.lang:

keyword = "if|class"

type = 'int'

comment delim "/*" "*/"

# thus this won't catch "/* */ /" as a regexp,
# since comment elem definition comes first
regexp = '/.*/.*/'

# this won't match if ( ) as a function,
# since keyword elem definition comes first
function = '([[:alpha:]]|_)[[:word:]]*[[:blank:]]*\(*[[:blank:]]*\)'

# the following order is conceptually wrong,
# since "//" won't be highlighted as a comment, but as two symbols
symbol = "/"
comment start "//"

which can be used with the input file test_string_stop.java, which 
produces the attached output, which is the one expected with the new 
strategy.

cheers
	Lorenzo

-- 
Lorenzo Bettini, PhD in Computer Science, DI, Univ. Torino
ICQ# lbetto, 16080134     (GNU/Linux User # 158233)
HOME: http://www.lorenzobettini.it MUSIC: http://www.purplesucker.com
http://www.myspace.com/supertrouperabba
BLOGS: http://tronprog.blogspot.com  http://longlivemusic.blogspot.com
http://www.gnu.org/software/src-highlite
http://www.gnu.org/software/gengetopt
http://www.gnu.org/software/gengen http://doublecpp.sourceforge.net

_______________________________________________
Help-source-highlight mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/help-source-highlight
test_string_stop.html (text/html, 565 B)
<!-- Generator: GNU source-highlight 
by Lorenzo Bettini
http://www.lorenzobettini.it
http://www.gnu.org/software/src-highlite -->
<pre><tt><i><font color="#9A1900">/* comment */</font></i> final <font color="#990000">/</font>
<font color="#FF6600">/my/regexp/</font>
  <b><font color="#0000FF">if</font></b> ( ) {
    <b><font color="#0000FF">class</font></b>;
    <b><font color="#000000">myfun ( )</font></b>;
  }
  <font color="#009900">int</font> i;
  <font color="#009900">int</font> ( );
<font color="#990000">//</font> comment? or two symbols?

</tt></pre>