From b8a47cac7ef57776984366778e28beabb167fad7 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Mon, 29 Aug 2011 09:46:04 -0500 Subject: [PATCH] Starting work on the generation/emitter phase. --- src/main/com/jdblabs/jlp/EchoEmitter.groovy | 13 +++++ src/main/com/jdblabs/jlp/Formatter.groovy | 7 +++ .../com/jdblabs/jlp/FormattingEmitter.groovy | 46 ++++++++++++++++ .../com/jdblabs/jlp/JLPBaseEmitter.groovy | 52 +++++++++++++++++++ .../com/jdblabs/jlp/MarkdownEmitter.groovy | 23 ++++++++ .../com/jdblabs/jlp/MarkdownFormatter.groovy | 16 ++++++ .../jdblabs/jlp/TransparentFormatter.groovy | 7 +++ 7 files changed, 164 insertions(+) create mode 100644 src/main/com/jdblabs/jlp/EchoEmitter.groovy create mode 100644 src/main/com/jdblabs/jlp/Formatter.groovy create mode 100644 src/main/com/jdblabs/jlp/FormattingEmitter.groovy create mode 100644 src/main/com/jdblabs/jlp/JLPBaseEmitter.groovy create mode 100644 src/main/com/jdblabs/jlp/MarkdownEmitter.groovy create mode 100644 src/main/com/jdblabs/jlp/MarkdownFormatter.groovy create mode 100644 src/main/com/jdblabs/jlp/TransparentFormatter.groovy diff --git a/src/main/com/jdblabs/jlp/EchoEmitter.groovy b/src/main/com/jdblabs/jlp/EchoEmitter.groovy new file mode 100644 index 0000000..0a88a9d --- /dev/null +++ b/src/main/com/jdblabs/jlp/EchoEmitter.groovy @@ -0,0 +1,13 @@ +package com.jdblabs.jlp + +import com.jdblabs.jlp.ast.* + +public class EchoEmitter extends JLPEmitter { + + public String emitAuthor(String value) { "Author: $value" } + public String emitDoc(String value) { value } + public String emitExample(String value) { "Example:\n$value" } + public String emitOrg(String value) { "Org: $value" } + + public String emitBlock(TextBlock textBlock) { textBlock.value } +} diff --git a/src/main/com/jdblabs/jlp/Formatter.groovy b/src/main/com/jdblabs/jlp/Formatter.groovy new file mode 100644 index 0000000..801d0cf --- /dev/null +++ b/src/main/com/jdblabs/jlp/Formatter.groovy @@ -0,0 +1,7 @@ +package com.jdblabs.jlp + +public interface Formatter { + String formatText(String text) + String formatCode(String code) + String formatReference(String ref) } + diff --git a/src/main/com/jdblabs/jlp/FormattingEmitter.groovy b/src/main/com/jdblabs/jlp/FormattingEmitter.groovy new file mode 100644 index 0000000..691fdfd --- /dev/null +++ b/src/main/com/jdblabs/jlp/FormattingEmitter.groovy @@ -0,0 +1,46 @@ +package com.jdblabs.jlp + +import com.jdblabs.jlp.ast.* +import com.jdblabs.jlp.ast.Directive.DirectiveType + +import org.slf4j.Logger +import org.slf4j.LoggerFactory + +public class FormattingEmitter extends JLPBaseEmitter { + + Formatter formatter + private Logger log = LoggerFactory.getLogger(this.getClass()) + + public FormattingEmitter(Formatter f, def generationState) { + super(generationState) + this.formatter = f } + + protected String emit(TextBlock textBlock) { + return formatter.format(textBlock) } + + protected String emit(Directive directive) { + switch (directive.type) { + case DirectiveType.Author: + case DirectiveType.Doc: + case DirectiveType.Example: + case DirectiveType.Org: + def orgValue = directive.value + if generationState.orgs.contains(orgValue) { + log.warn("Duplicate @org id: '${orgValue}'.") + def orgMatcher = (orgValue =~ /(.*)-(\d+)/ + if (orgMatcher.matches()) { + orgValue = "${m[0][1]}-${(m[0][2] as int) + 1}" } + else { orgValue += "-1" } } + + generationState.orgs << orgValue + formatter.formatReference(orgValue) + break } } + + private formatText(String s) { + // fix links to internal targets + s = s.eachMatch(/jlp:\/\/([^\s]+)/, s) + + // format with formatter + return formatter.formatText(s) + } +} diff --git a/src/main/com/jdblabs/jlp/JLPBaseEmitter.groovy b/src/main/com/jdblabs/jlp/JLPBaseEmitter.groovy new file mode 100644 index 0000000..c5ca0ff --- /dev/null +++ b/src/main/com/jdblabs/jlp/JLPBaseEmitter.groovy @@ -0,0 +1,52 @@ +package com.jdblabs.jlp + +import com.jdblabs.jlp.ast.* +import com.jdblabs.jlp.ast.Directive.DirectiveType + +public abstract class JLPBaseEmitter { + + def generationState + + public JLPBaseEmitter(def generationState) { + this.generationState = generationState } + + public String emitDocument(List sourceNodes) { + StringBuilder result = + sourceNodes.inject(new StringBuilder()) { sb, node -> + sb.append(emit(node, generationState)) + return sb } + + return result.toString() } + + protected String emit(DocBlock docBlock) { + List printQueue + StringBuilder result + + printQueue = docBlock.directives.collect { directive -> + def queueItem = [line: directive.lineNumber, value: directive] + switch (direcive.type) { + case DirectiveType.Author: queueItem.priority = 90; break + case DirectiveType.Doc: queueItem.priority = 50; break + case DirectiveType.Example: queueItem.priority = 50; break + case DirectiveType.Org: queueItem.priority = 10; break + return queueItem } + + printQueue.addAll(docBlock.textBlocks.collect { textBlock -> + [ priority: 50, line: textBlock.lineNumber, value: textBlock ] } + + // sort by priority, then by line number + printQueue.sort( + {i1, i2 -> i1.priority != i2.priority ? + i1.priority - i2.priority : + i1.line - i2.line} as Comparator) + + + result = printQueue.inject(new StringBuilder()) { sb, printable -> + sb.append(emit(printable.value)) + return sb } + + return result.toString() } + + protected abstract String emit(TextBlock textBlock) + protected abstract String emit(Directive directive) +} diff --git a/src/main/com/jdblabs/jlp/MarkdownEmitter.groovy b/src/main/com/jdblabs/jlp/MarkdownEmitter.groovy new file mode 100644 index 0000000..f038518 --- /dev/null +++ b/src/main/com/jdblabs/jlp/MarkdownEmitter.groovy @@ -0,0 +1,23 @@ +package com.jdblabs.jlp + +import com.jdblabs.jlp.ast.* +import org.pegdown.PegDownParser + +public class MarkdownEmitter extends JLPEmitter { + + protected MarkdownEmitter() {} + + def pegdown = new PegDownParser() + + protected String emitAuthor(String value) { + '${value}' } + + protected String emitDoc(String value) { /* parse as MD */ } + + protected String emitExample(String value) {/* parse as MD */ } + + protected String emitOrg(String value) { } + + protected String emitBlock(TextBlock textBlock) { "todo" } + +} diff --git a/src/main/com/jdblabs/jlp/MarkdownFormatter.groovy b/src/main/com/jdblabs/jlp/MarkdownFormatter.groovy new file mode 100644 index 0000000..91f45ba --- /dev/null +++ b/src/main/com/jdblabs/jlp/MarkdownFormatter.groovy @@ -0,0 +1,16 @@ +package com.jdblabs.jlp + +public class MarkdownFormatter implements Formatter { + + private PegDownProcessor pegdown + + public MarkdownFormatter() { + pegdown = new PegDownProcessor() } + + public String formatText(String s) { pegdown.markdownToHtml(s) } + + public String formatCode(String s) { + pegdown.markdownToHtml(s.replaceAll(/(^|\n)/, /$1 /)) } + + public String formatReference(String s) { '' } +} diff --git a/src/main/com/jdblabs/jlp/TransparentFormatter.groovy b/src/main/com/jdblabs/jlp/TransparentFormatter.groovy new file mode 100644 index 0000000..aaa5af2 --- /dev/null +++ b/src/main/com/jdblabs/jlp/TransparentFormatter.groovy @@ -0,0 +1,7 @@ +package com.jdblabs.jlp + +public class TransparentFormatter implements Formatter { + + public String formatText(String text) { return text } + public String formatCode(String code) { return code } + public String formatReference(String ref) { return "ref#${ref}" } }