Recent

Author Topic: TSynFacilSyn -- How Flexible?  (Read 3789 times)

EganSolo

  • Sr. Member
  • ****
  • Posts: 290
TSynFacilSyn -- How Flexible?
« on: January 26, 2017, 09:20:38 am »
As I continue to explore the best avenue to implement my own highlighter (and nothing seems to come easy here), I've looked at TSynFacilSyn. I've read the docs and started building my xml config file. I do have a few questions, some easier than others :)

  • How can I make sure that a block is not recursive? Say I have a block with the following syntax: $Description { } which cannot contain a nested $Description{}. Can I specify that in my xml language configuration file? Can it be done programmatically?
  • How can I restrict the set of acceptable symbols in a block. Say I have a block Class ClassName { } in which the period (.) is not valid. I would like to highlight it with a squiggly line. How can I do that?
  • I would like to define a set of special keywords that all start with the $ which is then followed by a-z,A-Z but I have a small subset of valid strings. Is there a way to specify those? Is the XML snipet blow valid?
  • Programmatically, How can I use fRange to quickly determine if a given token has a certain characteristic? Basically this has to do with the ability of the highlighter to dim an $IfDef $Foo { }  if  $Foo is not defined by a prior $Define $Foo statement. I could walk the block chain backward to see if I can find a $Define $Foo upstream but that may be onerous. When I encounter the $IfDef $Foo, I can make that check, and then I could add a flag to fRange that is set to true if I did find a $Define $Foo. When I hit a token inside the $IfDef $Foo block, again, I'm hoping that fRange could tell me that I'm inside that block and then tell me quickly whether this block is enabled or not so that I could either return the attribute for the token as is or return a dimmed version of it.

I know it may be a lot to ask for but that's what I'm trying to build. Any help or suggestion would be greatly appreciated.

Here is the snipet for defining a new token type called 'Directive' and restricting it to a small list. Is this even possible?
Code: XML  [Select][+][-]
  1. <Token CharsStart="$" Content='A..Za..z' Attribute='Directive'>
  2.         $Description
  3.         $Short
  4.         $Long
  5.         $IfDef
  6.         $IfNotDef
  7.         $Else
  8.         $Define
  9.         $UnDefine
  10.         $Region
  11.     </Token>
  12.    

Edson

  • Hero Member
  • *****
  • Posts: 1302
Re: TSynFacilSyn -- How Flexible?
« Reply #1 on: January 26, 2017, 03:53:04 pm »
Too many questions  :o for just one day, for just a not a good english speaker. I will do my try.

First of all, I must say SynFacilSyn was designed to be fast more than flexible. That's why his regex support is very basic.  But if you find other similar highlighter faster, I will retire from programming and start to cook.  :D

Here is the snipet for defining a new token type called 'Directive' and restricting it to a small list. Is this even possible?
Code: XML  [Select][+][-]
  1. <Token CharsStart="$" Content='A..Za..z' Attribute='Directive'>
  2.         $Description
  3.         $Short
  4.         $Long
  5.         $IfDef
  6.         $IfNotDef
  7.         $Else
  8.         $Define
  9.         $UnDefine
  10.         $Region
  11.     </Token>
  12.    

It's possible to define, but it won't work as you expected. Only the definition of token will be accepted. the words, will be ignored. 
In SynFacilSyn, it's called "subset of a token". And there are only two token types which accept "subsets": Identifiers and Symbols. So if you want to use "subsets", you could use a more general definition for identifiers:

Code: XML  [Select][+][-]
  1.  
  2.   <Identifiers CharsStart= "$A..Za..z_" Content = "A..Za..z">
  3.     <token attribute="Directive">
  4.         $Description
  5.         $Short
  6.         $Long
  7.         $IfDef
  8.     </token>
  9.   </Identifiers>
  10.  

You can define many "subsets" for identifiers, each one, with a different token type, and attributes. All the other tokens wich match the definition of identifier, but not is part of a subset, will be considered as a token of type "identifier".

« Last Edit: January 26, 2017, 03:56:54 pm by Edson »
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Edson

  • Hero Member
  • *****
  • Posts: 1302
Re: TSynFacilSyn -- How Flexible?
« Reply #2 on: January 26, 2017, 04:16:17 pm »
  • How can I make sure that a block is not recursive? Say I have a block with the following syntax: $Description { } which cannot contain a nested $Description{}. Can I specify that in my xml language configuration file? Can it be done programmatically?

Block definitions have a parameter called "Parent". If Parent="None", the block will be valid in any context, Therefore it can be used recursively. If Parent='Some_name_of_a_block', it will be opened just once, inside the parent block. Others block openning will be ignored.

Playing with "Parent" and "Name" of a block, it's possible restrict the level of the Nesting.

All this configuration can be done programmatically or by XML. All of what can be done in XML, can be done programmatically.

Maybe, this is not the best way to work with block, but this is what SynFacilSyn offers.
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Edson

  • Hero Member
  • *****
  • Posts: 1302
Re: TSynFacilSyn -- How Flexible?
« Reply #3 on: January 26, 2017, 04:25:47 pm »
   How can I restrict the set of acceptable symbols in a block. Say I have a block Class ClassName { } in which the period (.) is not valid. I would like to highlight it with a squiggly line. How can I do that?

It cannot be done.  This would represent some multi-syntax highlighter. And SynFacilSyn is not that. This is a feature, I have tryed to include in SynFacilSyn (like others), but no enough time for now. When I have to separate a block of syntax (like the Assembler code inside a Pascal source), I just define a multi-line delimited token, and make all this block have the same text color or something like this.

   I would like to define a set of special keywords that all start with the $ which is then followed by a-z,A-Z but I have a small subset of valid strings. Is there a way to specify those? Is the XML snipet blow valid?
Answered.
« Last Edit: January 26, 2017, 05:03:26 pm by Edson »
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

Edson

  • Hero Member
  • *****
  • Posts: 1302
Re: TSynFacilSyn -- How Flexible?
« Reply #4 on: January 26, 2017, 09:36:46 pm »
        Programmatically, How can I use fRange to quickly determine if a given token has a certain characteristic? Basically this has to do with the ability of the highlighter to dim an $IfDef $Foo { }  if  $Foo is not defined by a prior $Define $Foo statement. I could walk the block chain backward to see if I can find a $Define $Foo upstream but that may be onerous. When I encounter the $IfDef $Foo, I can make that check, and then I could add a flag to fRange that is set to true if I did find a $Define $Foo. When I hit a token inside the $IfDef $Foo block, again, I'm hoping that fRange could tell me that I'm inside that block and then tell me quickly whether this block is enabled or not so that I could either return the attribute for the token as is or return a dimmed version of it.

This kind of processing, is not in the level of a lexer (where SynFacilSyn works more). It's parsing, and SynFacilSyn have limited features at this level. Blocks definitions, cannot change according to previous definiitons. It would need a more smart scanning of the text, maybe adapting SynFacilSyn, with extra processing.
There are a pair of events in blocks: OnBeforeOpen, OnBeforeClose, that can help on "powerize" the block processing, but I'm not user, it can help.
Lazarus 2.2.6 - FPC 3.2.2 - x86_64-win64 on Windows 10

 

TinyPortal © 2005-2018