martijnversluis / ChordSheetJS

A JavaScript library for parsing and formatting ChordPro chord sheets
GNU General Public License v2.0
311 stars 48 forks source link

PeggySyntaxError: Expected [a-z,A-Z,\-,_] but "^" found #907

Closed ChrisMBarr closed 1 year ago

ChrisMBarr commented 1 year ago

I am trying to parse this ChordPro song but chordsheetjs throws an error. Here is the song and my code:

import { ChordProParser } from 'chordsheetjs';

const chordProTestSong = `{title: Our Father}
{artist: Bethel Music}
{key: G}
{comment: Words and Music by Marcus Meier}

{gc:Intro:}
[G]  [C/E]  [C]

{sov}
Verse:
Our Fa[G]ther in Heaven
Hal[C]lowed be Your [D]name
Your Kin[G]gdom come quickly
Your w[C]ill be done the s[D]ame
{eov}

{soc}
Chorus:
On E[C]arth a[G/B]s it[Am] is in [Em]Heaven
Let He[D]aven come to
[C]Earth [G/B]as i[Am]t is in[Em] Heaven
Let He[D]aven [G]come
{eoc}

{sob}
Bridge 1:
Let Heaven c[C]ome, let Heaven[Em] come
Let Heaven c[C]ome, let Heaven[Em] come
{eob}

Bridge 2:
[C]Yours is the Kingdom, Yours is the p[D]ower
[Em]Yours is the glory [G/B]forever, amen
[C]Yours is the Kingdom, Yours is the p[D]ower
[Em]Yours is the glory [G/B]forever amen

{start_of_grid}
|| Am . . . | C . . . | D  . . . | F  . . . |
|  Am . . . | C . . . | E  . . . | E  . . . |
|  Am . . . | C . . . | D  . . . | F  . . . |
|  Am . . . | E . . . | Am . . . | Am . . . ||
{end_of_grid}

{start_of_abc}
X:1
T:The Gentle Breeze
M:2/4
L:1/8
R:Air
K:Em
E>F G/2E/2-E| {A}B2{^c/2B/2}A>B| G/2E/2-E d2| B/2^c/2d B/2c/2d| e>f d>f|\
e3 B| g>B f>B| ef| eB F>B| E4:|

{end_of_abc}

{start_of_ly}
\\relative { g'8\\( a b[ c b\\) a] g4 }
{end_of_ly}
`;

const parser = new ChordProParser();
const doc = parser.parse(chordProTestSong);
console.log(doc);

The above song will produce this error:

"PeggySyntaxError: Expected [a-z,A-Z,\-,_] but "^" found.
    at peg$buildStructuredError (http://localhost:4200/vendor.js:4966:12)
    at $182dbf639c88db75$var$peg$parse (http://localhost:4200/vendor.js:6105:11)
    at $8e2b91641771a21c$var$ChordProParser.parseWithParser (http://localhost:4200/vendor.js:4554:17)
    at $8e2b91641771a21c$var$ChordProParser.parse (http://localhost:4200/vendor.js:6120:17)
    at InputTypeChordPro.extractSongData (http://localhost:4200/main.js:969:24)
    at ConvertComponent.getConvertersAndExtractData (http://localhost:4200/main.js:654:41)
    at Object.next (http://localhost:4200/main.js:577:12)
    at ConsumerObserver.next (http://localhost:4200/vendor.js:20376:25)
    at SafeSubscriber._next (http://localhost:4200/vendor.js:20345:22)
    at SafeSubscriber.next (http://localhost:4200/vendor.js:20318:12)"

I assume it's due to this line in the song: E>F G/2E/2-E| {A}B2{^c/2B/2}A>B| G/2E/2-E d2| B/2^c/2d B/2c/2d| e>f d>f|\ since that's the only place I see a ^ character

martijnversluis commented 1 year ago

Hey @FiniteLooper. Thanks for reaching out!

I must say I'm not that familiar with some of the constructs used in this song. The issue, though, is that { is a reserved character, indicating a ChordPro directive. The error is raised because ^ is not a valid character for a directive name. You can use a backslash to "escape" the curly brace. Because a backslash has the same meaning in JavaScript, a string literal will require a double backslash \\.

When properly escaping all curly braces, there is one last issue with the \\relative part. \\r would mean an escaped r, which is not a thing. You could only use this notation when escaping the backslashes, resulting in \\\\.

I created an online diff showing the required changes to fix the parsing errors: https://www.diffchecker.com/YxW4kXvU/.

Please let me know if this answers your questions and solves the issue.

ChrisMBarr commented 1 year ago

Are you sure? According the the ChordPro Docs for the ly directives it seems that the use of a { character is perfectly fine and expected usage.

That song with the (admittedly) odd formatting is just one I have in my folder of test songs. I'd love to move off of my custom parser onto something more "official", but right now it looks like mine can deal with this syntax so I guess I'll be sticking with it for now. Mine also doesn't care about pulling out anything except lyrics, so it throws away chords, tabs, etc. so it's probably not something that could be incorporated in many places.

ChrisMBarr commented 1 year ago

Ha, after my comment I went and looked at the list of supported ChordPro directives for this project and I do notice that the *_of_ly directives are not supported. So in that case I suppose this is to be expected!

martijnversluis commented 1 year ago

Apology, I must admit I never heard of these directives, nor I knew about Lilypond.

I would make sense though, to at least parse this part of the song as literal text instead of applying the main ChordPro grammar rules. This is related to #757. I'm not sure when it will be picked up, but I will complement this existing issue.

ChrisMBarr commented 1 year ago

Cool! Yeah I think that makes sense. I'm no musician and I am only starting to understand some of these things. But it seems the goal of these particular directives are to be used by other software packages, that consume ChordPro files even though these directives are not a "core" part of ChordPro. I guess they are kind of like extensions in a way. I think just returning them as plain text is a good solution since it allows these to not error out in this project, and it passes the data though for anyone to use if they need it.