carl.d.soren...@gmail.com writes: > I'd be lying if I said I understood everything going on here, but I > think I get the gist.
Same here. > I like moving this way! > > I like the approach of simplifying things. > > I like having optional predicates, and optional predicates with > defaults. > > I will trust you that it is O(n) and that all the shift-reduce conflicts > have been resolved. No need to trust: I was talking about O(n) concerning the number of rules. Since there are no longer rules with EXPECT_A EXPECT_B _combinations_, adding new types will add a number of rules to the grammar that is proportional to the number of new types. The cost is that one needs to either a) have a precedence rule for _every_ terminal symbol that may start a function argument b) be prepared to ignore a large number of shift/reduce conflicts. There are also two restrictions that may be arbitrary: a) if you leave out an optional argument, all immediately following optional arguments are also skipped. The reason is that I don't want a puzzle game for filling optional arguments into a list of argument types A A B C A C . If you get arguments A C in the input, where will they end up? b) the last argument needs to be non-optional. Otherwise a call ending with five optional arguments can look five syntactic arguments ahead in the input before deciding it does not want any. I don't actually think that the parser can deal with this kind of lookahead, so this may cut down expectations to a more reasonable level. As to performance: that is more or less O(n*l) where n is input size and l is the average lookahead piling up. Lookahead is pretty much limited: this mostly assigns arguments left to right, skipping optional argument lists once the first input does not fit. I wanted the code to be simpler but that is really hard. Anyway, here is an application:
afterGrace = #(define-music-function (parser location main dur grace) (ly:music? (ly:duration?) ly:music?) (_i "Create @var{grace} note(s) after a @var{main} music expression. An optional duration between the expressions gives the point of time where the grace notes are placed. ") (let ((main-length (ly:music-length main)) (fraction (ly:parser-lookup parser 'afterGraceFraction))) (make-simultaneous-music (list main (make-sequential-music (list (make-music 'SkipMusic 'duration (or dur (ly:make-duration 0 0 (* (ly:moment-main-numerator main-length) (car fraction)) (* (ly:moment-main-denominator main-length) (cdr fraction))))) (make-music 'GraceMusic 'element grace))))))) \new Voice { \afterGrace { c'1 } { c'16 d' } \afterGrace { c'1 } 1*7/8 { c'16 d' } \afterGrace { c'1} 4 {c'16 d' } \afterGrace c'2 {c'16 d'} d'2}
As you can see when comparing with the original in ly/music-functions-init.ly, the source code is minimally more complex. Since the default duration needs to be calculated at run time when left unspecified, we let the optional argument default to #f (defaults are no longer checked for the correct type, so this works) and splice in the default calculation with (or dur ...). > I'm not a parser expert, so it doesn't mean much coming from me, but I > think this looks good. Neither am I. > http://codereview.appspot.com/5023044/ -- David Kastrup
_______________________________________________ lilypond-devel mailing list lilypond-devel@gnu.org https://lists.gnu.org/mailman/listinfo/lilypond-devel