From 2f731a8ea21ed76a37116f07234cfe065ca468cb Mon Sep 17 00:00:00 2001 From: Ivy Date: Tue, 25 Oct 2022 12:04:35 -0700 Subject: [PATCH 1/5] Add basic tagged flashcards to parser-generator This is a fork of `https://github.com/reuseman/flashcards-obsidian/tree/ohm` that also handles a bug of ohm's greedy matching causing questions to bleed into previous notes' answers. --- parser-generator/assets/grammar.ohm | 32 ++++++++++++++++ parser-generator/assets/testnote.md | 8 ++++ parser-generator/src/generate.js | 57 +++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+) create mode 100644 parser-generator/assets/grammar.ohm create mode 100644 parser-generator/assets/testnote.md create mode 100644 parser-generator/src/generate.js diff --git a/parser-generator/assets/grammar.ohm b/parser-generator/assets/grammar.ohm new file mode 100644 index 0000000..0203529 --- /dev/null +++ b/parser-generator/assets/grammar.ohm @@ -0,0 +1,32 @@ +G { + Main = Flashcard* end + + // PLUGIN SYNTAX + Flashcard = questionTagged backTagged + backTagged = answerTagged flashcardId? // backTagged represents second half of card + answerTagged = (~(flashcardId? answerTaggedDelimiter) answerContentType)* + answerTaggedDelimiter = newline newline + questionTagged = (~tag questionContentType)* tag + tag = "#card" + + answerContentType = any + questionContentType = any + + // Anki card ID - e.g. ^1643061575720 + flashcardId = "^" digit digit digit digit digit digit digit digit digit digit digit digit digit + + // OTHER + newline = "\r\n" | "\n" | "\r" + + // OBSIDIAN SYNTAX + + // Obsidian tag - e.g. #main_tag/sub_tag-with123/other_sub + //Tag = "#" letter (alnum | "_" | "-" | "/")* + + header1 = "#" + header2 = "##" + header3 = "###" + header4 = "####" + header5 = "#####" + header6 = "######" +} \ No newline at end of file diff --git a/parser-generator/assets/testnote.md b/parser-generator/assets/testnote.md new file mode 100644 index 0000000..8e80d96 --- /dev/null +++ b/parser-generator/assets/testnote.md @@ -0,0 +1,8 @@ +Question1 #card Answer 1 ^1666356393425 + +Question2 #card Answer 2a Answer 2b + +Question2 #card +Answer 2a +Answer 2b + diff --git a/parser-generator/src/generate.js b/parser-generator/src/generate.js new file mode 100644 index 0000000..4a0a28a --- /dev/null +++ b/parser-generator/src/generate.js @@ -0,0 +1,57 @@ +const fs = require("fs"); +const ohm = require("ohm-js"); + +const file = fs.readFileSync('../assets/grammar.ohm').toString(); +const grammar = ohm.grammar(file); +const semantics = grammar.createSemantics(); +semantics.addOperation('eval()', { + Main(cards, eof) { + const out = cards.children.map((card) => { + return card.eval(); + }); + return out; + }, + + Flashcard(question, back) { + return { + question: question.eval(), + back: back.eval(), + }; + }, + + questionTagged(question, _tag) { + return { + question: question.sourceString, + } + }, + + backTagged(answer, id) { + return { + answer: answer.sourceString, + id: id.sourceString, + }; + }, + + flashcardId(_, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13) { + // Concatenate all the digits and return the source string + const digits = [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13].map(d => d.sourceString).join(''); + // Convert to a number + return parseInt(digits, 10); + }, +}); + + +const markdownFile = fs.readFileSync('../assets/testnote.md', 'utf-8'); + +const m = grammar.match(markdownFile); +if (m.succeeded()) { + console.log('\x1b[32m%s\x1b[0m', "Parsed successfully."); +} else { + console.log('\x1b[31m%s\x1b[0m', "Could not parse."); +} + +const result = semantics(m).eval(); + +console.log("The final result is: ") +console.log(result); + From c54c8022db29faa69dc3edde5f399dc61b783f6c Mon Sep 17 00:00:00 2001 From: Ivy Date: Tue, 25 Oct 2022 12:45:53 -0700 Subject: [PATCH 2/5] Make `grammar.ohm` rules generic --- parser-generator/assets/grammar.ohm | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/parser-generator/assets/grammar.ohm b/parser-generator/assets/grammar.ohm index 0203529..2e8bc63 100644 --- a/parser-generator/assets/grammar.ohm +++ b/parser-generator/assets/grammar.ohm @@ -2,11 +2,12 @@ G { Main = Flashcard* end // PLUGIN SYNTAX - Flashcard = questionTagged backTagged - backTagged = answerTagged flashcardId? // backTagged represents second half of card - answerTagged = (~(flashcardId? answerTaggedDelimiter) answerContentType)* + Flashcard = frontTagged backTagged + frontTagged = question + backTagged = answer flashcardId? + question = (~delimiter questionContentType)* delimiter + answer = (~(flashcardId? delimiter) answerContentType)* answerTaggedDelimiter = newline newline - questionTagged = (~tag questionContentType)* tag tag = "#card" answerContentType = any From 026910067be57e44d00a7efc0ee88ebea42e07d3 Mon Sep 17 00:00:00 2001 From: Ivy Date: Tue, 25 Oct 2022 12:52:34 -0700 Subject: [PATCH 3/5] Remove unnecessary rules in `grammar.ohm` --- parser-generator/assets/grammar.ohm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/parser-generator/assets/grammar.ohm b/parser-generator/assets/grammar.ohm index 2e8bc63..c520ba5 100644 --- a/parser-generator/assets/grammar.ohm +++ b/parser-generator/assets/grammar.ohm @@ -2,13 +2,12 @@ G { Main = Flashcard* end // PLUGIN SYNTAX - Flashcard = frontTagged backTagged - frontTagged = question - backTagged = answer flashcardId? + Flashcard = question answer flashcardId? question = (~delimiter questionContentType)* delimiter answer = (~(flashcardId? delimiter) answerContentType)* - answerTaggedDelimiter = newline newline + tag = "#card" + answerTaggedDelimiter = newline newline answerContentType = any questionContentType = any From a79c56994165b42e98924a37db8410c9492f6b5d Mon Sep 17 00:00:00 2001 From: Ivy Date: Tue, 25 Oct 2022 12:58:48 -0700 Subject: [PATCH 4/5] Update `generate.js` to match `grammar.ohm` --- parser-generator/assets/grammar.ohm | 3 ++- parser-generator/src/generate.js | 20 +++++++++----------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/parser-generator/assets/grammar.ohm b/parser-generator/assets/grammar.ohm index c520ba5..86aaa91 100644 --- a/parser-generator/assets/grammar.ohm +++ b/parser-generator/assets/grammar.ohm @@ -2,7 +2,8 @@ G { Main = Flashcard* end // PLUGIN SYNTAX - Flashcard = question answer flashcardId? + Flashcard = FlashcardTagged + FlashcardTagged = question answer flashcardId? question = (~delimiter questionContentType)* delimiter answer = (~(flashcardId? delimiter) answerContentType)* diff --git a/parser-generator/src/generate.js b/parser-generator/src/generate.js index 4a0a28a..6fdc9cc 100644 --- a/parser-generator/src/generate.js +++ b/parser-generator/src/generate.js @@ -12,26 +12,24 @@ semantics.addOperation('eval()', { return out; }, - Flashcard(question, back) { + Flashcard(flashcard) { return { - question: question.eval(), - back: back.eval(), + flashcard: flashcard.eval(), }; }, - questionTagged(question, _tag) { - return { - question: question.sourceString, - } - }, - - backTagged(answer, id) { + FlashcardTagged(question, answer, tag) { return { + question: question.eval(), answer: answer.sourceString, - id: id.sourceString, + tag: tag.sourceString, }; }, + question(question, _delimiter) { + return question.sourceString; + }, + flashcardId(_, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13) { // Concatenate all the digits and return the source string const digits = [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13].map(d => d.sourceString).join(''); From a74d62633bc242832db450d7112890b0a4e6b84e Mon Sep 17 00:00:00 2001 From: Ivy Date: Tue, 25 Oct 2022 13:31:27 -0700 Subject: [PATCH 5/5] Add proper tag parsing in parser-generator --- parser-generator/src/generate.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/parser-generator/src/generate.js b/parser-generator/src/generate.js index 6fdc9cc..d7e8117 100644 --- a/parser-generator/src/generate.js +++ b/parser-generator/src/generate.js @@ -19,10 +19,11 @@ semantics.addOperation('eval()', { }, FlashcardTagged(question, answer, tag) { + console.log(Object.getOwnPropertyNames(tag.source)) return { question: question.eval(), answer: answer.sourceString, - tag: tag.sourceString, + tag: tag.child(0)?.eval(), }; }, @@ -31,9 +32,7 @@ semantics.addOperation('eval()', { }, flashcardId(_, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13) { - // Concatenate all the digits and return the source string const digits = [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13].map(d => d.sourceString).join(''); - // Convert to a number return parseInt(digits, 10); }, });