diff --git a/.gitignore b/.gitignore index 3ac2aee3..a0552dca 100755 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,4 @@ src/normalize_mappings/suffix-normalize-mapping.ts .parcel-cache src/parser/chord/combined_grammer.pegjs src/parser/chord/suffix_grammar.pegjs +src/parser/chord_pro/sections_grammar.pegjs diff --git a/README.md b/README.md index 9aa5a3ee..89235d14 100644 --- a/README.md +++ b/README.md @@ -306,16 +306,16 @@ use those to change the generated output. ### Environment directives -| Directive | Support | -|:---------------------------- |:------------------------:| -| start_of_chorus (short: soc) | :heavy_check_mark: | -| end_of_chorus (short: eoc) | :heavy_check_mark: | -| start_of_verse | :heavy_check_mark: | -| end_of_verse | :heavy_check_mark: | -| start_of_tab (short: sot) | :heavy_check_mark: | -| end_of_tab (short: eot) | :heavy_check_mark: | -| start_of_grid | :heavy_multiplication_x: | -| end_of_grid | :heavy_multiplication_x: | +| Directive | Support | +|:---------------------------- |:------------------:| +| start_of_chorus (short: soc) | :heavy_check_mark: | +| end_of_chorus (short: eoc) | :heavy_check_mark: | +| start_of_verse | :heavy_check_mark: | +| end_of_verse | :heavy_check_mark: | +| start_of_tab (short: sot) | :heavy_check_mark: | +| end_of_tab (short: eot) | :heavy_check_mark: | +| start_of_grid | :heavy_check_mark: | +| end_of_grid | :heavy_check_mark: | ### Chord diagrams diff --git a/data/sections.ts b/data/sections.ts new file mode 100644 index 00000000..4bbe62ee --- /dev/null +++ b/data/sections.ts @@ -0,0 +1,9 @@ +const sections: [string, boolean][] = [ + // name, generate shorthand tag (eg. sog, eot) + ['abc', false], + ['grid', true], + ['ly', false], + ['tab', true], +]; + +export default sections; diff --git a/doc/README.hbs b/doc/README.hbs index 45bcd1b3..fb14c582 100644 --- a/doc/README.hbs +++ b/doc/README.hbs @@ -306,16 +306,16 @@ use those to change the generated output. ### Environment directives -| Directive | Support | -|:---------------------------- |:------------------------:| -| start_of_chorus (short: soc) | :heavy_check_mark: | -| end_of_chorus (short: eoc) | :heavy_check_mark: | -| start_of_verse | :heavy_check_mark: | -| end_of_verse | :heavy_check_mark: | -| start_of_tab (short: sot) | :heavy_check_mark: | -| end_of_tab (short: eot) | :heavy_check_mark: | -| start_of_grid | :heavy_multiplication_x: | -| end_of_grid | :heavy_multiplication_x: | +| Directive | Support | +|:---------------------------- |:------------------:| +| start_of_chorus (short: soc) | :heavy_check_mark: | +| end_of_chorus (short: eoc) | :heavy_check_mark: | +| start_of_verse | :heavy_check_mark: | +| end_of_verse | :heavy_check_mark: | +| start_of_tab (short: sot) | :heavy_check_mark: | +| end_of_tab (short: eot) | :heavy_check_mark: | +| start_of_grid | :heavy_check_mark: | +| end_of_grid | :heavy_check_mark: | ### Chord diagrams diff --git a/script/build_chord_pro_section_grammar.ts b/script/build_chord_pro_section_grammar.ts new file mode 100644 index 00000000..50cf17d8 --- /dev/null +++ b/script/build_chord_pro_section_grammar.ts @@ -0,0 +1,57 @@ +import sections from '../data/sections'; + +interface BuildOptions { + force: boolean; + release: boolean; +} + +function capitalize(string: string) { + return `${string.charAt(0).toUpperCase() + string.slice(1).toLowerCase()}`; +} + +function sectionRuleName(sectionName: string) { + return `${capitalize(sectionName)}Section`; +} + +function sectionShortTag(sectionName: string, type: 'start' | 'end'): string { + return `${type[0]}o${sectionName[0]}`; +} + +function sectionTags(sectionName: string, shortTag: boolean, type: 'start' | 'end') { + const tags = [`${type}_of_${sectionName}`]; + if (shortTag) tags.push(sectionShortTag(sectionName, type)); + return tags.map((tag) => `"${tag}"`).join(' / '); +} + +export default function buildChordProSectionGrammar(_: BuildOptions, _data: string): string { + const sectionsGrammars = sections.map(([name, shortTags]) => ` +${capitalize(name)}Section + = startTag:${capitalize(name)}StartTag + NewLine + content:$(!${capitalize(name)}EndTag SectionCharacter)* + endTag:${capitalize(name)}EndTag + { + return helpers.buildSection(startTag, endTag, content); + } + +${capitalize(name)}StartTag + = "{" _ tagName:(${sectionTags(name, shortTags, 'start')}) _ tagColonWithValue: TagColonWithValue? _ "}" { + return helpers.buildTag(tagName, tagColonWithValue, location()); + } + +${capitalize(name)}EndTag + = "{" _ tagName:(${sectionTags(name, shortTags, 'end')}) _ "}" { + return helpers.buildTag(tagName, null, location()); + } +`); + + return ` +Section + = ${sections.map(([name, _shortTags]) => sectionRuleName(name)).join(' / ')} + +${sectionsGrammars.join('\n\n')} + +SectionCharacter + = . +`.substring(1); +} diff --git a/script/build_chord_suffix_grammar.ts b/script/build_chord_suffix_grammar.ts index 6aa41fcc..9dea7cb6 100755 --- a/script/build_chord_suffix_grammar.ts +++ b/script/build_chord_suffix_grammar.ts @@ -1,5 +1,9 @@ import { EOL } from 'os'; -import { BuildOptions } from 'esbuild'; + +interface BuildOptions { + force: boolean; + release: boolean; +} export default function buildChordSuffixGrammar(_: BuildOptions, data: string): string { const suffixes: string[] = data diff --git a/script/build_chord_suffix_normalize_mapping.ts b/script/build_chord_suffix_normalize_mapping.ts index 6ea98f51..8a796555 100644 --- a/script/build_chord_suffix_normalize_mapping.ts +++ b/script/build_chord_suffix_normalize_mapping.ts @@ -1,5 +1,9 @@ import { EOL } from 'os'; -import { BuildOptions } from 'esbuild'; + +interface BuildOptions { + force: boolean; + release: boolean; +} export default function buildChordSuffixNormalizeMapping(_: BuildOptions, data: string): string { const suffixes = data diff --git a/src/parser/chord_pro/grammar.pegjs b/src/parser/chord_pro/grammar.pegjs index 60f5f7c3..cb41961b 100644 --- a/src/parser/chord_pro/grammar.pegjs +++ b/src/parser/chord_pro/grammar.pegjs @@ -14,72 +14,6 @@ ComponentWithNewline Component = Section / Line -Section = - ABCSection / GridSection/ LYSection / TabSection - -TabSection - = startTag:TabStartTag NewLine content:$(!TabEndTag SectionCharacter)* endTag:TabEndTag { - return helpers.buildSection(startTag, endTag, content); - } - -TabStartTag - = "{" _ tagName:("sot" / "start_of_tab") _ tagColonWithValue: TagColonWithValue? _ "}" { - return helpers.buildTag(tagName, tagColonWithValue, location()); - } - -TabEndTag - = "{" _ tagName:("eot" / "end_of_tab") _ "}" { - return helpers.buildTag(tagName, null, location()); - } - -ABCSection - = startTag:ABCStartTag NewLine content:$(!ABCEndTag SectionCharacter)* endTag:ABCEndTag { - return helpers.buildSection(startTag, endTag, content); - } - -ABCStartTag - = "{" _ tagName:("start_of_abc") _ tagColonWithValue: TagColonWithValue? _ "}" { - return helpers.buildTag(tagName, tagColonWithValue, location()); - } - -ABCEndTag - = "{" _ tagName:("end_of_abc") _ "}" { - return helpers.buildTag(tagName, null, location()); - } - -LYSection - = startTag:LYStartTag NewLine content:$(!LYEndTag SectionCharacter)* endTag:LYEndTag { - return helpers.buildSection(startTag, endTag, content); - } - -LYStartTag - = "{" _ tagName:("start_of_ly") _ tagColonWithValue: TagColonWithValue? _ "}" { - return helpers.buildTag(tagName, tagColonWithValue, location()); - } - -LYEndTag - = "{" _ name:("end_of_ly") _ "}" { - return helpers.buildTag(name, null, location()); - } - -GridSection - = startTag:GridStartTag NewLine content:$(!GridEndTag SectionCharacter)* endTag:GridEndTag { - return helpers.buildSection(startTag, endTag, content); - } - -GridStartTag - = "{" _ tagName:("sog" / "start_of_grid") _ tagColonWithValue: TagColonWithValue? _ "}" { - return helpers.buildTag(tagName, tagColonWithValue, location()); - } - -GridEndTag - = "{" _ tagName:("eog" / "end_of_grid") _ "}" { - return helpers.buildTag(tagName, null, location()); - } - -SectionCharacter - = . - LineWithNewline = line: Line NewLine { return line; diff --git a/unibuild.ts b/unibuild.ts index 8884148b..32b5abc9 100755 --- a/unibuild.ts +++ b/unibuild.ts @@ -9,6 +9,7 @@ import unibuild, { Builder } from '@martijnversluis/unibuild'; import buildChordSuffixNormalizeMapping from './script/build_chord_suffix_normalize_mapping'; import buildChordSuffixGrammar from './script/build_chord_suffix_grammar'; import buildScales from './script/build_scales'; +import buildChordProSectionGrammar from './script/build_chord_pro_section_grammar'; interface BuildOptions { force: boolean; @@ -55,11 +56,17 @@ unibuild((u: Builder) => { ), }); + const sectionsGrammar = u.asset('sectionsGrammar', { + input: 'data/sections.ts', + outfile: 'src/parser/chord_pro/sections_grammar.pegjs', + build: buildChordProSectionGrammar, + }); + u.asset('chordProParser', { - input: ['src/parser/chord_pro/grammar.pegjs'], + input: ['src/parser/chord_pro/grammar.pegjs', sectionsGrammar], outfile: 'src/parser/chord_pro/peg_parser.ts', - build: ({ release }: BuildOptions, baseGrammar: string) => { - const parserSource = peggyGenerate(baseGrammar, release); + build: ({ release }: BuildOptions, baseGrammar: string, sections: string) => { + const parserSource = peggyGenerate(`${baseGrammar}\n\n${sections}`, release); return `import * as helpers from './helpers';\n\n${parserSource}`; }, });