Approaching Alt expression parsing

This commit is contained in:
2019-03-16 20:45:13 -06:00
parent e446256c97
commit 2344a36eee
5 changed files with 78 additions and 32 deletions

View File

@@ -4,9 +4,10 @@ Multiline comments /*will not
split*/ an output expression. This should parse as one line of output.
Comments at the end of lines won't parse as part of the Output. // I'm my own expression!
You can {insert} the values of expressions.
{you} can start an output line with an insert expression.
{you} can start an output line with an insert expression. {and_end_one}
{shuffle: Things get weird|when you start to use sequence expressions.}
{once: And they don't get any easier|{when you nest them|{insert}}}!
// If you don't believe me, just look at ParserTest.hx!!
{once: And they don't get any {easier}|{when you nest them|{insert}}}!
You can {
if (flag) "insert" else "interpolate"

View File

@@ -1,5 +1,8 @@
package hank;
import haxe.ds.Option;
using Extensions.OptionExtender;
enum AltBehavior {
Sequence;
OnceOnly;
@@ -7,9 +10,42 @@ enum AltBehavior {
Shuffle;
}
typedef Alt = {
@:allow(hank.AltInstance)
class Alt {
var behavior: AltBehavior;
var outputs: Array<Output>;
static var behaviorMap = [
'>' => Sequence,
'!' => OnceOnly,
'&' => Cycle,
'~' => Shuffle,
'seq:' => Sequence,
'once:' => OnceOnly,
'cycle:' => Cycle,
'shuffle:' => Shuffle
];
public function new(behavior: AltBehavior, outputs: Array<Output>) {
this.behavior = behavior;
this.outputs = outputs;
}
public static function parse(buffer: HankBuffer): Option<Alt> {
var rawExpr = buffer.findNestedExpression('{', '}').unwrap().checkValue();
var expr = rawExpr.substr(1, rawExpr.length-2);
for (prefix in behaviorMap.keys()) {
if (StringTools.startsWith(expr, prefix)) {
var _outputs = StringTools.trim(expr.substr(prefix.length));
buffer.take(rawExpr.length);
return Some(new Alt(behaviorMap[prefix], []));
}
}
return None;
}
}
class AltInstance {
@@ -18,10 +54,7 @@ class AltInstance {
var random: Random;
public function new(behavior: AltBehavior, outputs: Array<Output>, random: Random) {
this.alt = {
behavior: behavior,
outputs: outputs
};
this.alt = new Alt(behavior, outputs);
this.random = random;
}

View File

@@ -38,7 +38,7 @@ class BufferSlice {
this.buffer = buffer;
}
public function checkValue() {
public function checkValue(): String {
if (!buffer.position().equals(anchorPosition)) {
throw 'Tried to access an expired BufferSlice.';
}
@@ -91,7 +91,7 @@ class HankBuffer {
return s;
}
public function indexOf(s: String) {
public function indexOf(s: String): Int {
return cleanBuffer.indexOf(s);
}
@@ -104,7 +104,7 @@ class HankBuffer {
}
/** Peek at contents buffer waiting further ahead in the buffer **/
public function peekAhead(start: Int, length: Int) {
public function peekAhead(start: Int, length: Int): String {
return cleanBuffer.substr(start, length);
}

View File

@@ -27,18 +27,10 @@ class Output {
while (!buffer.isEmpty()) {
var endSegment = buffer.length();
var findHaxeExpression = buffer.findNestedExpression('{', '}');
var findAltExpression = buffer.findNestedExpression('{{', '}}', 0, false); // Single brace expressions trip up the double brace search, so don't throw exceptions
switch (findHaxeExpression) {
var findBraceExpression = buffer.findNestedExpression('{', '}');
switch (findBraceExpression) {
case Some(slice):
if (slice.start < endSegment)
endSegment = slice.start;
default:
}
switch (findAltExpression) {
case Some(slice):
if (slice.start < endSegment)
endSegment = slice.start;
endSegment = slice.start;
default:
}
if (endSegment == buffer.length() || endSegment != 0) {
@@ -47,7 +39,9 @@ class Output {
if (peekLine.length < endSegment) {
var text = buffer.takeLine().unwrap();
trace(text);
parts.push(Text(text));
if (text.length > 0) {
parts.push(Text(text));
}
break;
} else {
var text = buffer.take(endSegment);
@@ -55,11 +49,7 @@ class Output {
parts.push(Text(text));
}
} else {
if (buffer.indexOf('{{') == 0) {
parts.push(parseAltExpression(buffer));
} else {
parts.push(parseHaxeExpression(buffer));
}
parts.push(parseBraceExpression(buffer));
}
}
@@ -78,7 +68,16 @@ class Output {
return new Output(parts);
}
public static function parseHaxeExpression(buffer: HankBuffer) {
public static function parseBraceExpression(buffer: HankBuffer): OutputType {
switch (Alt.parse(buffer)) {
case Some(altExpression):
return AltExpression(altExpression);
default:
return parseHaxeExpression(buffer);
}
}
public static function parseHaxeExpression(buffer: HankBuffer): OutputType {
var rawExpression = buffer.findNestedExpression('{', '}').unwrap().checkValue();
// Strip out the enclosing braces
var hExpression = rawExpression.substr(1, rawExpression.length - 2);
@@ -88,8 +87,4 @@ class Output {
buffer.take(rawExpression.length);
return HExpression(hExpression);
}
public static function parseAltExpression(buffer: HankBuffer) {
return AltExpression({behavior: Cycle, outputs:[]});
}
}

View File

@@ -4,6 +4,8 @@ import hank.Parser;
import hank.Parser.HankAST;
import hank.Output;
import hank.Output.OutputType;
import hank.Alt;
import hank.Alt.AltBehavior;
class ParserTest extends utest.Test {
var ast: HankAST;
@@ -25,6 +27,21 @@ class ParserTest extends utest.Test {
assertNextExpr(EOutput(new Output([Text("A line won't be interrupted or anything.")])));
assertNextExpr(EOutput(new Output([Text("Multiline comments an output expression. This should parse as one line of output.")])));
assertNextExpr(EOutput(new Output([Text("Comments at the end of lines won't parse as part of the Output.")])));
assertNextExpr(EOutput(new Output([Text("You can "), HExpression("insert"), Text(" the values of expressions.")])));
assertNextExpr(EOutput(new Output([HExpression("you"), Text(" can start an output line with an insert expression. "), HExpression("and_end_one")])));
assertNextExpr(
EOutput(new Output([
AltExpression(
new Alt(
Shuffle,
[
new Output([Text("Things get weird"), Text("when you start to use sequence expressions.")])
]
)
)
]))
);
}