Skip to content

Commit 6b1be81

Browse files
committed
There were some Parser duties that were being mushed into the CommentScript for no good reason.
1 parent dcaf010 commit 6b1be81

File tree

5 files changed

+66
-50
lines changed

5 files changed

+66
-50
lines changed

src/main/java/com/diffplug/freshmark/CommentScript.java

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ protected CommentScript(String intron, String exon, String regex) {
7878
final Parser parser;
7979

8080
/** Compiles a single section/script/input combo into the appropriate output. */
81-
final Parser.Compiler compiler = new Parser.Compiler() {
81+
final Parser.SectionCompiler compiler = new Parser.SectionCompiler() {
8282
@Override
8383
public String compileSection(String section, String script, String input) {
8484
return Errors.rethrow().get(() -> {
@@ -90,20 +90,7 @@ public String compileSection(String section, String script, String input) {
9090
engine.put("input", input);
9191
// evaluate the script and get the result
9292
engine.eval(templatedProgram);
93-
String compiled = Check.cast(engine.get("output"), String.class);
94-
// make sure that the compiled output starts and ends with a newline,
95-
// so that the tags stay separated separated nicely
96-
if (!compiled.startsWith("\n")) {
97-
compiled = "\n" + compiled;
98-
}
99-
if (!compiled.endsWith("\n")) {
100-
compiled = compiled + "\n";
101-
}
102-
return parser.intron + " " + section + "\n" +
103-
script +
104-
parser.exon +
105-
compiled +
106-
parser.intron + " /" + section + " " + parser.exon;
93+
return Check.cast(engine.get("output"), String.class);
10794
});
10895
}
10996
};

src/main/java/com/diffplug/freshmark/CommentScriptMustache.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,15 @@ protected CommentScriptMustache(String intron, String exon, String regex) {
5757
super(intron, exon, regex);
5858
}
5959

60+
/** Replaces whatever is inside of {@code {{key}}} tags using the {@code keyToValue} function. */
6061
protected String template(String section, String script) {
61-
return mustacheTemplate(script, key -> keyToValue(section, script));
62+
return mustacheTemplate(script, key -> keyToValue(section, key));
6263
}
6364

65+
/** For the given section, return the templated value for the given key. */
6466
protected abstract String keyToValue(String section, String script);
6567

66-
/** Replaces whatever is inside of {@code {{key}}} tags using the {@code keyToValue} function. */
68+
/** Mustache templating. */
6769
static String mustacheTemplate(String input, Function<String, String> keyToValue) {
6870
Matcher matcher = MUSTACHE_PATTERN.matcher(input);
6971
StringBuilder result = new StringBuilder(input.length() * 3 / 2);

src/main/java/com/diffplug/freshmark/Parser.java

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -33,28 +33,53 @@ class Parser {
3333
/**
3434
* Given an input string, parses out the body sections from the tag sections.
3535
*
36-
* @param input the raw input string
36+
* @param rawInput the raw input string
3737
* @param body called for every chunk of text outside a tag
3838
* @param tag called for every chunk of text inside a tag
3939
*/
40-
void bodyAndTags(String input, Consumer<String> body, Consumer<String> tag) {
41-
Matcher matcher = pattern.matcher(input);
40+
protected void bodyAndTags(String rawInput, Consumer<String> body, Consumer<String> tag) {
41+
Matcher matcher = pattern.matcher(rawInput);
4242
int last = 0;
4343
while (matcher.find()) {
4444
if (matcher.start() > last) {
45-
body.accept(input.substring(last, matcher.start()));
45+
body.accept(rawInput.substring(last, matcher.start()));
4646
}
4747
tag.accept(matcher.group(1));
4848
last = matcher.end();
4949
}
50-
if (last < input.length()) {
51-
body.accept(input.substring(last));
50+
if (last < rawInput.length()) {
51+
body.accept(rawInput.substring(last));
5252
}
5353
}
5454

55+
/**
56+
* Reassembles a section/script/output chunk back into
57+
* the full file.
58+
*
59+
* @param section
60+
* @param script
61+
* @param output
62+
* @return
63+
*/
64+
protected String reassemble(String section, String script, String output) {
65+
// make sure that the compiled output starts and ends with a newline,
66+
// so that the tags stay separated separated nicely
67+
if (!output.startsWith("\n")) {
68+
output = "\n" + output;
69+
}
70+
if (!output.endsWith("\n")) {
71+
output = output + "\n";
72+
}
73+
return intron + " " + section + "\n" +
74+
script +
75+
exon +
76+
output +
77+
intron + " /" + section + " " + exon;
78+
}
79+
5580
/** Interface which can compile a single section of a FreshMark document. */
5681
@FunctionalInterface
57-
interface Compiler {
82+
public interface SectionCompiler {
5883
String compileSection(String section, String program, String in);
5984
}
6085

@@ -65,7 +90,7 @@ interface Compiler {
6590
* @param compiler used to compile each section
6691
* @return the compiled output string
6792
*/
68-
String compile(String fullInput, Compiler compiler) {
93+
public String compile(String fullInput, SectionCompiler compiler) {
6994
StringBuilder result = new StringBuilder(fullInput.length() * 3 / 2);
7095
/** Associates errors with the part of the input that caused it. */
7196
class ErrorFormatter {
@@ -102,37 +127,37 @@ private int countNewlines(String str) {
102127
class State {
103128
/** The section for which we're looking for a close tag. */
104129
String section;
105-
/** The program for that section. */
106-
String program;
107-
/** The raw input which will be passed to the program. */
130+
/** The script for that section. */
131+
String script;
132+
/** The raw input which will be passed to the script. */
108133
String input;
109134

110135
void body(String body) {
111136
assert(input == null);
112137
if (section == null) {
113-
assert(program == null);
138+
assert(script == null);
114139
result.append(body);
115140
} else {
116-
assert(program != null);
141+
assert(script != null);
117142
input = body;
118143
}
119144
}
120145

121146
void tag(String tag) {
122147
if (section == null) {
123-
assert(program == null);
148+
assert(script == null);
124149
assert(input == null);
125150
// we were looking for an open tag, and now we've got one
126151
int firstLine = tag.indexOf('\n');
127152
if (firstLine < 0 || tag.length() <= firstLine) {
128-
throw new IllegalArgumentException("Section doesn't contain a program.");
153+
throw new IllegalArgumentException("Section doesn't contain a script.");
129154
}
130155
// the section name is the first line (trimmed)
131156
section = tag.substring(0, firstLine).trim();
132-
// the program is the second line
133-
program = tag.substring(firstLine + 1);
157+
// the script is the second line
158+
script = tag.substring(firstLine + 1);
134159
} else {
135-
assert(program != null);
160+
assert(script != null);
136161
assert(input != null);
137162
// we were looking for a close tag
138163
String closing = tag.trim();
@@ -141,11 +166,12 @@ void tag(String tag) {
141166
throw new IllegalArgumentException("Expecting '/" + section + "'");
142167
}
143168
// and we found one! compile it and accumulate the result
144-
String chunk = compiler.compileSection(section, program, input);
145-
result.append(chunk);
169+
String compiled = compiler.compileSection(section, script, input);
170+
String reassembled = reassemble(section, script, compiled);
171+
result.append(reassembled);
146172
// wipe the state
147173
section = null;
148-
program = null;
174+
script = null;
149175
input = null;
150176
}
151177
}

src/test/java/com/diffplug/freshmark/ParserTest.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
import org.junit.Assert;
2121
import org.junit.Test;
2222

23-
import com.diffplug.common.base.StringPrinter;
24-
2523
public class ParserTest {
2624
static final Parser freshmarkParser = new FreshMark(null, null).parser;
2725

@@ -58,15 +56,7 @@ public void testCompileNoTags() {
5856

5957
@Test
6058
public void testCompileWiring() {
61-
testCaseCompileSuccess("simple.txt", StringPrinter.buildStringFromLines(
62-
"Some stuff",
63-
"Nothing special",
64-
"section: simple",
65-
"program: output = 'BLOOPEY\\n' + input + 'DOOP\\n';",
66-
"input: ",
67-
"Does this work?",
68-
"",
69-
"Why yes! Yes it does."));
59+
testCaseCompileSuccess("simple.txt", TestResource.getTestResource("simple_compiled.txt"));
7060
}
7161

7262
static void testCaseCompileSuccess(String file, String expected) {
@@ -90,7 +80,7 @@ public void testCompileMismatched() {
9080

9181
@Test
9282
public void testCompileNoProgram() {
93-
testCaseCompileError("noprogram.txt", "Error on line 3: Section doesn't contain a program.");
83+
testCaseCompileError("noprogram.txt", "Error on line 3: Section doesn't contain a script.");
9484
}
9585

9686
static void testCaseCompileError(String file, String expected) {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Some stuff
2+
Nothing special
3+
<!---freshmark simple
4+
output = 'BLOOPEY\n' + input + 'DOOP\n';
5+
-->
6+
section: simple
7+
program: output = 'BLOOPEY\n' + input + 'DOOP\n';
8+
input:
9+
Does this work?
10+
<!---freshmark /simple -->
11+
Why yes! Yes it does.

0 commit comments

Comments
 (0)