-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
replacing ly.slexer and ly.lex #139
Comments
|
I'm no expert but I like what you're doing!
I would avoid |
Sounds like a big leap forward, nice work! If |
I think the new ly module will provide more than only functionality based on parce, but just use parce for parsing (and the Document functionality that's also in parce). |
I settled on the name I added a transform module to parce, and it is shaping up very well to be able to have a living music expression as-you-type in Frescobaldi. When typing, parce quickly updates the tokenized/lexed tree structure and calls the transformer (like current |
(related to #3, #55, and possibly others).
Dear Friends,
on the Salzburg conference I announced that I am writing a new lexer that wil replace
ly.slexer
and thely.lex.xxx
definition modules.The reason is that it is almost impossible to inherit from, say,
ly.lex.lilypond
to implement small changes in lexing between versions of LilyPond, because when one changes a class, all references still point to the old one. Also, the tokens generated by the slexer module are instances of different classes, making it necessary to import the lexing definitions to be able to refer to classes and e.g. find instances. And finally, the linear structure of the tokens in the currently
module makes it tedious to find ranges in a text where e.g. a certain parser state is active (e.g. find the start of a lyrics expression, etc).ly.document.Source
andRunner
try to adress that a little but basically they are a PITA to work with (I can say that because I wrote them 7 years ago:-) )The module that will replace
ly.slexer
andly.lex
will be a generic parsing package which I'm writing right now; I first called it LiveLex, but because that coincides with a German company name, I renamed itparce
.parce
addresses all of the aforementioned shortcomings:slexer
calls aParser
(or a context) is a lexicon (which is basically a class method yielding the parsing rules).It is very simple to inherit from a language definition and override just one lexicon to make a few adjustments. Because a lexicon is basically a class method, targets in other lexicons automatically refer to the inherited version of the lexicon. So supporting multiple versions of LilyPond becomes possible.
slexer
calls a Token instance is a token, but the "type" is stored in anaction
attribute. So there are no classes anymore for every possible token, and manipulating tokens does not require one to import a language module to get all the definitions. And all theisinstance(token, ly.lex.lilypond.BlaBla)
calls can go!parce
module creates a tree structure of the tokens, nested in contexts, and can update the structure when the user types in the document. So starting from a token, it is as simple as accessing itsparent
attribute to get the encompassing context. You can easily navigate to sibling or child tokens and there is a very powerfulquery
method on every node, to search for anything in the tree structure.This
parce
package already works very well, and I created good quality documentation and a web site for it, see https://parce.info/ . To get an idea of what a language definition looks like, compare ly.lex.lilypond (1659 lines) with parce.lang.lilypond (currently 534 lines).Parsing and updating can be done in a background thread. There is already a small package bringing
parce
to Qt's QTextDocument, which can be used later to enable highlighting of text in Frescobaldi using the new lexer.Right now, in
ly
and Frescobaldi, the music manipulation functionality uses either plainslexer
tokens (such as the rhythm functions) or thely.music
tree structure. But also code such as the MusicXml output uses both the Music tree and also the original tokens.Both can be ported to the new parser/lexer. But because that causes a rewrite of almost the whole of the
ly
package, I propose to create a new package from scratch, providing the same (and more) functionality, and that can be developed until the moment that it is possible to port Frescobaldi to it.It is still desirable to have a tree structure like
ly.music
, but now theparce
tree structure can probably form a solid base of such a structure.(How/whether
parce
can support a custom data structure attached to aparce
tree is yet to be determined. But we could also opt for an independent tree, which can replacely.music
and, while at it, also has a simpler structure (with fewer classes as currently.music
). Becauseparce
can exactly report which part of the tree got updated, it is easy to invalidate just the modified part of a music tree instead of rebuilding it completely after every change, as is the case now.)So, we could think of a name for the new ly module. We could use
ly2
but I don't like the number in the name. I am currently thinking ofquickly
. :-)The text was updated successfully, but these errors were encountered: